类的特殊成员方法
Posted 当幸福来敲门
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类的特殊成员方法相关的知识,希望对你有一定的参考价值。
类的特殊成员方法
1、__doc__ 表示类的描述信息
class Dog(object): \'\'\'这个是描述狗的一个类\'\'\' def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print(\'my wigth is \', self.__weight,) d = Dog(\'二哈\') print(d.__doc__) #这个是描述狗的一个类 print(Dog.__doc__) #这个是描述狗的一个类
2、__module__ 和 __class__
__module__ 表示当前操作的对象在哪个模块
__class__ 表示当前操作的对象是哪个类
3、__init__ 构造方法,类在实例化创建对象时,自动触发的方法
4、__del__ 析构方法 当对象在内存被释放时,自动触发执行。
5、__call__ 对象后面加括号,触发执行
class Dog(object): \'\'\'这个是描述狗的一个类\'\'\' def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print(\'my wigth is \', self.__weight,) def __call__(self, *args, **kwargs): print(\'runing call\',args,kwargs) d = Dog(\'二哈\')
Dog(\'二哈\')() #runing call () {}
d(1,2,3,4,5,name=888) #runing call (1, 2, 3, 4, 5) {\'name\': 888}
6、__dict__ 查看类或者对象中的所有成员
class Dog(object): \'\'\'这个是描述狗的一个类\'\'\' def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print(\'my wigth is \', self.__weight,) def __call__(self, *args, **kwargs): print(\'runing call\',args,kwargs) d = Dog(\'二哈\') print(Dog.__dict__) #{\'__dict__\': <attribute \'__dict__\' of \'Dog\' objects>, \'__doc__\': \'这个是描述狗的一个类\', \'__init__\': <function Dog.__init__ at 0x00000000010501E0>,
#\'__call__\': <function Dog.__call__ at 0x00000000010502F0>, \'sayhi\': <function Dog.sayhi at 0x0000000001050268>, \'__module__\': \'__main__\',
#\'__weakref__\': <attribute \'__weakref__\' of \'Dog\' objects>} #打印类里面的所有属性,不包括实例。 print(d.__dict__) #{\'_Dog__weight\': 100, \'name\': \'二哈\'} 打印所有实例的属性,不包括类。
7、__str__ 如果一个类定义了__str__方法 ,那么在打印对象时。默认输出该方法的返回值
class Dog(object): \'\'\'这个是描述狗的一个类\'\'\' def __init__(self,name): self.name = name self.__weight = 100 def sayhi(self): print(\'my wigth is \', self.__weight,) def __call__(self, *args, **kwargs): print(\'runing call\',args,kwargs) def __str__(self): return "obj:%s" % self.name d = Dog(\'二哈\') d1 = Dog(\'秋田\') print(d) # obj:二哈 print(d1) # obj:秋田
8、__getitem__、__setitem__、__delitem__
用于索引操作,比如字典、以上表示获取、设置、删除数据。
class Foo(object): def __getitem__(self, key): print(\'__getitem__\',key) def __setitem__(self, key, value): print(\'__setitem__\',key,value) def __delitem__(self, key): print(\'__delitem__\',key) obj = Foo() result = obj[\'k1\'] # __getitem__ k1 obj[\'k2\'] = \'alex\' # __setitem__ k2 alex del obj[\'k1\'] # __delitem__ k1
9、__new__ \\ __metaclass__
一切事物皆对象。
class Foo(object): def __init__(self,name): self.name = name f = Foo(\'alex\') print(type(f)) #<class \'__main__.Foo\'> print(type(Foo)) #<class \'type\'>
可以看到f是实例化Foo后的一个对象,不仅f是一个对象,Foo类本身也是一个对象。
f对象是Foo的一个实例,Foo类是type类的一个实例。说明Foo类是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
1、普通方式
class Foo(object): def __init__(self,name): self.name = name f = Foo(\'alex\')
2、特殊方式
def func(self): print(\'hello world\') Foo = type(\'Foo\',(),{\'func\':func}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法 print(type(Foo)) f= Foo() #<class \'type\'> f.func() #hello world
既然可以通过这种方式创建类,并且可以添加类的方法,也可以把__init__这种方法装载进去。
def func(self): print(\'hello world\') def __init__(self,name,age): self.name = name self.age = age Foo = type(\'Foo\',(),{\'func\':func,\'__init__\':__init__}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法 f= Foo() #TypeError: __init__() missing 2 required positional arguments: \'name\' and \'age\'
这里提示实例化的时候__init__里面要传入两个参数。
def func(self): print(\'hello world\') def __init__(self,name,age): self.name = name self.age = age Foo = type(\'Foo\',(),{\'func\':func,\'__init__\':__init__}) #Foo表示要实例化之后的类,()表示要继承的类,func表示类里面的方法 f= Foo(\'alex\',\'age\') print(f.name,f.age) #alex age
那么,类默认是通过type类实例化产生,type类如何创建类?类又是如何创建对象的?
其实类中有一个属性 __metaclass__,其用来表示该类由谁来实例化创建的。所以可以为__metaclass__设置一个type类的派生类,从而查看类创建的过程。
1 class MyType(type): 2 def __init__(self,*args,**kwargs): 3 4 print("Mytype __init__",*args,**kwargs) 5 6 def __call__(self, *args, **kwargs): 7 print("Mytype __call__", *args, **kwargs) 8 obj = self.__new__(self) 9 print("obj ",obj,*args, **kwargs) 10 print(self) 11 self.__init__(obj,*args, **kwargs) 12 return obj 13 14 def __new__(cls, *args, **kwargs): 15 print("Mytype __new__",*args,**kwargs) 16 return type.__new__(cls, *args, **kwargs) 17 18 print(\'here...\') 19 class Foo(object,metaclass=MyType): 20 21 22 def __init__(self,name): 23 self.name = name 24 25 print("Foo __init__") 26 27 def __new__(cls, *args, **kwargs): 28 print("Foo __new__",cls, *args, **kwargs) 29 return object.__new__(cls) 30 31 f = Foo("Alex") 32 print("f",f) 33 print("fname",f.name) 34 35 自定义元类
__new__()方法
class Foo(object): def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): print("Foo __new__",cls, *args, **kwargs) return object.__new__(cls) f = Foo("Alex") #=========执行结果============ Foo __new__ <class \'__main__.Foo\'> Alex Foo __init__
实例化Foo类的时候会执行__init__,也会执行__new__。并且__new__会在__init__之前执行。
有一点不明白的是__new__()方法里面的return object.__new__(cls) 做什么用的?
尝试去掉这个return:
class Foo(object): def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): print("Foo __new__",cls, *args, **kwargs) f = Foo("Alex") #=============执行结果============ Foo __new__ <class \'__main__.Foo\'> Alex
可以看到只执行了__new__()方法,并没有执行__init__这个方法。说明这个实例并没有真正被创建。
print(f.name) #AttributeError: \'NoneType\' object has no attribute \'name\'
说明__new__()用来创建实例的,object.__new__用父类的方法创建实例,那么传过去的cls做什么的?
cls 相当于self,也就是Foo,因为Foo也是一个对象,你要继承父类的东西就要把自己传过去。
print(object.__new__(cls)) #<__main__.Foo object at 0x0000000000A52320> #Foo内存对象
__metaclass__
1 class MyType(type): 2 def __init__(self,*args,**kwargs): 3 4 print("Mytype __init__",*args,**kwargs) 5 super(MyType, self).__init__( *args,**kwargs) 6 7 def __call__(self, *args, **kwargs): 8 print("Mytype __call__", *args, **kwargs) 9 #obj = self.__new__(self) 10 #self.__init__(obj,*args, **kwargs) 11 12 class Foo(object): 13 __metaclass__ = MyType 14 def __init__(self,name): 15 self.name = name 16 17 print("Foo __init__") 18 19 def __new__(cls, *args, **kwargs): 20 print("Foo __new__",cls, *args, **kwargs) 21 return object.__new__(cls) 22 23 f = Foo("Alex")
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好
以上是关于类的特殊成员方法的主要内容,如果未能解决你的问题,请参考以下文章
面向对象day08:类的特殊成员-类的起源与metaclass