Python自学笔记-第8章高级程序设计技术(2)

送分小仙女□ 提交于 2020-05-02 20:12:25

1.4.装饰器

装饰器时一个函数,其入参是一个函数或方法,并返回一个新的函数或方法。这样可以在不改动原函数的基础上,同时也新增一些附加功能。比如可以将日志记录等操作用装饰器来完成。 具体可以参考第4章内容。

 

1.5.函数注释

Python3提供一种语法,用于为函数声明中的参数和返回值附加元数据。下面的例子是注解后的版本,特点在第一行:

In [4]:
def clip(text : str, max_len : 'int > 0' = 80) -> str:
    """在max_len前面或后面的第一个空格处截断文本 
    """
    end = None
    if len(text) > max_len:
        space_before = text.rfind(' ', 0, max_len)
        if space_before >= 0:
            end = space_before
        else:
            # 返回字符串最后一次出现的位置,没有则返回-1 
            space_after = text.rfind(' ', max_len)       
            if space_after >= 0:
                end = space_after
    # 没找到空格
    if end is None:        
        end = len(text)
    # 删除字符串末尾指定的字符串,默认为空格
    return text[:end].rstrip()
 
  1. 函数声明中的各个参数可以在:(冒号)后增加注解表达式。
  2. 如果参数由默认值,注解放在参数名和 = 号之间。
  3. 如果注解有返回值,在 ) 和函数末尾的:之间增加 -> 和一个表达式。那个表达式可以是任何类型。注解中最常用的类型是类(如 str 或 int)和字符串(如 'int > 0')。
In [5]:
clip
Out[5]:
<function __main__.clip(text:str, max_len:'int > 0'=80) -> str>
 

Python对注解所做的唯一的事情是,把他们存储在函数的annotations属性里。仅此而已,Python不做检查,不做强制,不做验证,什么操作都不做。换句话,注解对Python解释器没任何意义。注解只是元数据,可以供IDE、框架和装饰器等工具使用。

 

2.面向对象程序设计进阶

第1节,描述了在过程性程序开发中可以参考和借鉴的方法。本节主要针对面向对象开发中应该注意的事情进行说明

 

2.1.控制属性存取

控制属性的读取,第6章已经介绍过通过装饰器的方案。如下:

In [7]:
class test(object):
    def __init__(self):
        self.__x=None
    @property
    def x(self):
        print('getter')
        return self.__x
    @x.setter
    def x(self,value):
        print('setter')
        self.__x=value
    @x.deleter
    def x(self):
        print('deleter')
        del self.__x
In [8]:
t = test()
t.x = 12
 
setter
In [9]:
print(t.x)
 
getter
12
 

此种方式易于便, 但是如果有大量的只读属性,就会变得非常乏味。可以通过魔法方法来实现此种功能。

 
  • 用于属性存取的特殊方法有
特殊方法 使用 描述
__delattr__(self,name) del x.n 删除对象x的属性
__dir__(self) dir(x) 返回x的属性名列表
__getattr__(self,name) v=x.n 返回对象x的n属性值(如果没有直接找到)
__getattribute__(self,name) v=x.n 返回对象x的n属性值
__setattr__(self,name,value) x.n=v 将对象x的n属性值设置为v
In [65]:
class test1(object):
    b = 234
    
    def __getattr__(self,name):
        print('getattr',name)
        if name == 'x':
            return 'x is None'
        elif name == 'y':
            return self.__dict__['y']
        else:
            raise AttributeError(name,'has not found')
    
    def __setattr__(self,name,value):
        print('setattr',name)
        self.__dict__[name]=value
In [66]:
t1 = test1()
print(t1.x)
 
getattr x
x is None
In [60]:
t1.y = 123
 
setattr y
In [61]:
print(t1.__dict__)
 
{'y': 123}
In [62]:
print(t1.y)
 
123
 
  • 对象的所有非特殊属性都存放在self.__dict__中,因此我们可以直接存取这些属性。对于,私有属性,其名称在其中的存储key为__className__attributeName
In [52]:
class A(object):
    """
    Class A.
    """
    a = 0
    b = 1

    def __init__(self):
        self.a = 2
        self.b = 3

    def test(self):
        print('a normal func.')

    @staticmethod
    def static_test(self):
        print('a static func.')

    @classmethod
    def class_test(self):
        print('a calss func.')
In [53]:
obj = A()
print(A.__dict__)
 
{'__module__': '__main__', '__doc__': '\n    Class A.\n    ', 'a': 0, 'b': 1, '__init__': <function A.__init__ at 0x00000199A4071268>, 'test': <function A.test at 0x00000199A40711E0>, 'static_test': <staticmethod object at 0x00000199A40739E8>, 'class_test': <classmethod object at 0x00000199A4073AC8>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>}
In [54]:
print(obj.__dict__)
 
{'a': 2, 'b': 3}
 
  • __getattr__方法是在属性不存在时,可以访问。
 
  • __getattribute__方法在__getattr__前被调用,但是比方法要重写时要格外注意 ,以防止对自身进行递归调用--super().__getattribute__()object.__getattribute__
 

2.2.函子

在Python中,函数对象就是到任何可以调用对象(比如函数,lambda函数或方法)的对象引用。在计算机科学中,函子是指一个对象,该对象可以像函数一样进行调用,因此,在Python术语中,函子就是另一种类型的函数对象。任何包含了特殊方法__call__()的类,都是一个函子。

 

函子可以提供的关键好处是可以维护一些状态信息。

In [68]:
class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

    def __call__(self, friend):
        print('My name is %s...' % self.name)
        print('My friend is %s...' % friend)
In [69]:
p = Person('Bob','Tom')
p('John')
 
My name is Bob...
My friend is John...
 

2.3.上下文管理器

使用上下文管理器可以简化代码,这是通过确保某些操作在特定代码块执行前与执行后在进行来实现的。

 

上下文管理器提供了2个特殊方法__enter__()__exit__(),在with语句范围内,Python会对其进行特别处理。

 

在with语句内创建上下文管理器时,其__enter__()方法会自动被调用,在with语句后,上下文管理器作用范围之外时,其__exit__()方法会自动被调用。

 

内置的open()函数返回的文件对象就是上下文管理器。使用上下文管理器的语法如下:

with expression as variable:
    suite
In [74]:
class DbConnection:
    def __enter__(self):
        print('Connecting DB')
        
    # exc_type如果抛出异常,这里获取异常的类型 
    # exc_val如果抛出异常,这里显示异常内容
    # exc_tb如果抛出异常,这里显示所在位置    
    def __exit__(self,exc_type,exc_val,exc_tb):
        print('Connect is down')
In [75]:
with DbConnection() as db:
    print('db working')
 
Connecting DB
db working
Connect is down
 

2.4.描述符

具体可以查看第6章内容

更多文章,请关注:
        

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!