标签:foo 数据 过程 概念 元组 格式 ges containe weakref
前面我们讲了类的方法,有普通方法,就是我们自己定义的方法,还有静态方法,类方法,属性方法,其实类还有另外一种方法,叫做类的特殊成员方法
说明:表示类的描述信息
|
1
2
3
4
5
6
7
8
9
10
11
|
class Dog(object): """此类是形容Dog这个类""" #类的描述信息 def __init__(self,name): self.name = nameprint(Dog.__doc__) #打印类的描述信息#输出此类是形容Dog这个类 |
说明:

aa.py的代码:
|
1
2
3
4
|
class C(object): def __init__(self): self.name = "shuaigaogao" |
index.py的代码:
|
1
2
3
4
5
6
7
8
9
10
|
from lib.aa import Cobj = C()print(obj.__module__) #表示当前操作的对象在哪个模块print(obj.__class__) #表示当前操作的对象的类是什么#输出lib.aa<class ‘lib.aa.C‘> |
说明:构造方法,通过类创建对象时,自动触发执行
说明:析构方法,当对象在内存中被释放时,自动触发执行
|
1
2
|
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的 |
说明: 对象后面加括号,触发执行
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class Foo(object): def __init__(self): self.name = "shuaigaogao" def __call__(self, *args, **kwargs): #重写call方法 print("running call",args,kwargs)f = Foo() #执行__init__f(1,2,3,name=333) # 执行call方法,也可以写成 Foo()(1,2,3,name=333)#输出running call (1, 2, 3) {‘name‘: 333} |
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
说明: 查看类或对象中的所有成员
①类.__dict__
效果:打印类中所有的属性,不包括实例属性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Province(object): country = ‘China‘ def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print("func")print(Province.__dict__) #类.__dict__#输出{‘__doc__‘: None, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Province‘ objects>, ‘__init__‘:<function Province.__init__ at 0x00000247F3CAD488>, ‘country‘: ‘China‘, ‘__dict__‘:<attribute ‘__dict__‘ of ‘Province‘ objects>, ‘func‘: <function Province.func at0x00000247F3CAD510>, ‘__module__‘: ‘__main__‘} #打印类中所有的属性,不包括实例属性 |
②实例名.__dict__
效果:打印该实例的所有属性,不包括类属性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Province(object): country = ‘China‘ def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print("func")p = Province("jiangsu",20000) #实例化print(p.__dict__) #实例名.__dict__#输出{‘count‘: 20000, ‘name‘: ‘jiangsu‘} #打印该实例的所有属性,不包括类属性 |
说明:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Province(object): country = ‘China‘ def __init__(self, name): self.name = name def __str__(self): return "<obj:{0}>".format(self.name)p = Province("jiangsu")print(p) #打印这个对象#输出<obj:jiangsu> #给对象重新起了一个名字 |
注:这个以后会在django框架里面会用到,这边就不多说了
说明:用于索引操作,如字典。以上分别表示获取、设置、删除数据
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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)f = Foo()f["name"] = "shuaigaogao" #自动触发__setitem__方法f["name"] #自动触发__getitem__方法del f["name"] #自动触发__delitem__方法#输出__setitem__: name shuaigaogao__getitem__: name__delitem__ name |
注:这边的__delitem__没有做真正的删除,只是触发这个方法,想要真正删除,只需要在__delitem__函数中添加删除功能即可
前面我们学习了大篇幅的关于类,通过类创建对象,那我们想知道这个类到底是怎么产生的呢?它的一切来源是什么?还有对象,对象是通过什么方法创建的,现在我们一头雾水,行的,下面我们就来揭开类的面纱,看看类和对象到底是怎么创建的,通过什么创建的。
|
1
2
3
4
5
|
class Foo(object): def __init__(self,name): self.name = namef = Foo("shuaigaogao") |
f 是通过 Foo 类实例化的对象,其实,不仅 f 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象,按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
|
1
2
|
print(type(f)) #输出:<class ‘__main__.Foo‘> 表示:f 对象由Foo类创建print(type(Foo)) #输出:<class ‘type‘> 表示:Foo类对象由 type 类创建 |
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建
说明: type创建类的格式,类名 = type(‘类名‘,(父类,),{‘方法名‘:方法的内存地址})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
def func(self): #创建方法 print("hello {0}".format(self.name))def __init__(self,name): #创建构造方法 self.name = name#通过type创建类,如果是经典类的话则写成:Foo = type("Foo",(),{"talk":func,"__init__":__init__})Foo = type("Foo",(object,),{"talk":func,"__init__":__init__}) f = Foo("shuaigaogao") #创建对象f.talk()#输出hello shuaigaogao |
总结:类 是由 type 类 实例化产生的
值得注意的是,新式类的写法,在继承父类那边,你继承一个父类后面就要加一个逗号,加逗号,它就把它当做一个元组,不加逗号,就是一个值了

new方法是类自带的一个方法,可以重构,__new__方法在实例化的时候也会执行,并且先于__init__方法之前执行
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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("shuaigaogao")#输出Foo __new__ <class ‘__main__.Foo‘> shuaigaogao #执行了new方法Foo __init__ #执行了__init__方法 |
作用:所有对象都是通过new方法来实例化的,new里面调用了init方法,所以在实例化的过程中先执行的是new方法,而不是init方法。
①重构__new__方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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("shuaigaogao") #实例化#输出Foo __new__ <class ‘__main__.Foo‘> shuaigaogao |
由上面的例子看出,没有执行__init__方法
②重构__new__方法,并继承父类的__new__方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Foo(object): def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): #cls相当于传入类Foo print("Foo __new__",cls, *args, **kwargs) return object.__new__(cls) #继承父类的__new__方法,这边必须以返回值的形式继承f = Foo("shuaigaogao")#输出Foo __new__ <class ‘__main__.Foo‘> shuaigaogaoFoo __init__ |
由上面不难看出,大多数情况下,你都不要去重构你的__new__方法,因为你父类中已经有__new__方法了,已经帮你写好了怎么去创建类,如果你重写的话,就会覆盖父类的里面的__new__方法。但是你重构可以增加一点小功能,但是你覆盖了以后还是需要继承父类回来,要不然你的这个实力就创建不了。
我想对我自己写的一些类进行定制,就在它实例化之前就进行定制,就可以用到__new__方法,new方法就是用来创建实力的,重构new方法,必须以返回值的形式继承父类的new方法。
①需求:我在创建对象时候,同时创建一个类变量
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Foo(object): def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): #cls相当于是传入的类名Foo cls.name = "shuaigaogao" #创建对象是定义静态变量 print(cls.name) return object.__new__(cls) #继承父类的__new__方法f = Foo("shuaigaogao")print(Foo.name)#输出shuaigaogaoFoo __init__shuaigaogao |
metaclass这个属性叫做元类,它是用来表示这个类是由谁来帮他实例化创建的,说白了,就是相当于自己定制一个类,就这么一个意思。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
class MyType(type): def __init__(self,*args,**kwargs): print("Mytype __init__",*args,**kwargs) def __call__(self, *args, **kwargs): print("Mytype __call__", *args, **kwargs) obj = self.__new__(self) print("obj ",obj,*args, **kwargs) print(self) self.__init__(obj,*args, **kwargs) return obj def __new__(cls, *args, **kwargs): print("Mytype __new__",*args,**kwargs) return type.__new__(cls, *args, **kwargs)class Foo(object,metaclass=MyType): #python3统一用这种 #__metaclass__ = MyType #python2.7中的写法 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("shuaigaogao")print("f",f)print("fname",f.name)#输出Mytype __new__ Foo (<class ‘object‘>,) {‘__new__‘: <function Foo.__new__ at 0x0000025EF0EFD6A8>,‘__init__‘: <function Foo.__init__ at 0x0000025EF0EFD620>, ‘__qualname__‘: ‘Foo‘, ‘__module__‘: ‘__main__‘}Mytype __init__ Foo (<class ‘object‘>,) {‘__new__‘: <function Foo.__new__ at 0x0000025EF0EFD6A8>, ‘__init__‘: <function Foo.__init__ at 0x0000025EF0EFD620>, ‘__qualname__‘: ‘Foo‘, ‘__module__‘: ‘__main__‘}Mytype __call__ shuaigaogaoFoo __new__ <class ‘__main__.Foo‘>obj <__main__.Foo object at 0x0000025EF0F05048> shuaigaogao<class ‘__main__.Foo‘>Foo __init__f <__main__.Foo object at 0x0000025EF0F05048>fname shuaigaogao |

类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
metaclass 详解文章:猛击这里 得票最高那个答案写的非常好
面向对象【day08】:类的特殊成员-类的起源与metaclass
标签:foo 数据 过程 概念 元组 格式 ges containe weakref
原文地址:http://www.cnblogs.com/luoahong/p/7208395.html