python中有很多关于类的内置函数和方法,这部分的知识,自己也是一直拖着没去总结,这周抽出时间写一篇总结类的博客。
基本方法
对于一个普通对象而言,它有以下常用的内建方法:
__class__
: 创建此对象的类
__init__
: 初始化对象,在创建的时候被调用。
注意这并不是严格意义的构造函数,只能说是在初始化的时候,会被调用的钩子函数。
那么说道这个方法,就有必要提到调用父类构造函数常用到的函数:super函数,这个函数可以方便的调用父类的构造函数,super(ChildObject, self).__init__()
,不用提及父类名。
__del__
: 释放对象,在对象删除的时候被调用。
__str__
: print 的时候会被调用(给人看的)。
__repr__
: 给机器看的字符串。
既然说到了类方法,那么不得不提到,__new__
方法。
实际上new才算是python对象的构造函数,用于生成实例对象,我们看见的单例模式,就是在这个函数上做文章。
1 | class Singleton(object): |
在python中,类也是对象,所以对于一个类对象而言:
__class__
: 类也是对象,类的class是type.
__name__
: 类的名称
__doc__
: 类的文档,在使用help的时候会拿出来。
__mro__
: mro即method resolution
order,主要用于在多继承时判断调的属性的路径(来自于哪个类)(这里还可能会提到: 深度优先搜索算法 )
访问对象属性。
python对象中有一个内建属性,__dict__
,所有python对象的属性,都放在这里,比如你有一个对象a,它有一个属性 a.b == 5
,那么你也一定能在a.__dict__["b"]
中访问到它。
你可以用这两个内建函数,以字符串路径引用的方式从一个对象中获取属性和方法(方法也算是属性。)
1 | getattr |
1 | class A(object): |
一些钩子函数
__getattr__
为内置方法,当使用点号获取实例属性时,如果属性不存在就自动调用__getattr__
方法,你可以定义它返回一个值,或者抛出一个异常。
如果你需要一个在每一个属性访问的钩子时, __getattribute__()
可以满足。钩子的顺序是先调用__getattribute__()
,再调用__getattr__
,
还有一点需要注意的是,当使用类访问不存在的变量是,不会经过__getattr__
函数。
__setattr__
当设置类实例属性时自动调用。
描述符
描述符是一个一开始很难理解的东西,你如果看见一个类中定义的属性,不是在__init__
中定义的,而是像java那样的声明式定义,那就很可能是一个描述符。
作为描述符对象,需要实现以下方法:
__set__
: 在任何特性被设置的时候调用。
__get__
: 在任何特性被读取的时候被调用。
__delete__
: 在特性被del的时候被调用。
普通python对象的属性,都是在__dict__
上进行操作的,但是Description就不同了,这个东西在被对象作为属性访问的时候,就不是通过dict来访问的,而是调用Descriptor的__get__
, __set__
, __delete__
.
你看这个应该很熟,首先在python的@property装饰器描述符,就是通过Description实现的。
在django-orm和sqlalchemy orm中,定义字段,也是在使用描述符。
1 | class User(Base): |
容器对象
__getitem__(self,key)
,这个方法实际上就是对应 seq[key]
可迭代对象
__iter__
: 返回迭代器自己
next()
: 返回迭代后的下一个值,这个函数是以前版本的兼容,python3中,必须实现一个__next__
方法。
其它方法
__cmp__
看命名就知道排序会用到这个方法。
__gt__
判断self对象是否大于另一个对象。
__lt__
判断self对象是否小于另一个对象。
__ge__
判断一个兑现是否大于等于另一个对象。
__le__
判断一个对象是否小于等于另一个对象。
__eq__
判断一个对象是否等于另一个对象。
__call__
让一个对象可以被调用。