一、上下文管理协议
1.1、什么叫上下文管理协议?
with open('a.txt') as f:
'代码块'
即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
with语句小结:
with obj as f:
'代码块'
1)with obj ==>触发obj.__enter__(),拿到返回值
2)as f ==> f=返回值
3)with obj as f ==> f=obj.__enter__()
4) 执行代码块
一:没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为None
二:有异常的情况下,从异常出现的位置直接触发__exit__
a:如果__exit__的返回值为True,代表吞掉了异常
b:如果__exit__的返回值不为True,代表吐出了异常
c:__exit__的的运行完毕就代表了整个with语句的执行完毕
1.2、方法使用
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f: #触发__enter__方法
print('=====>执行代码块')
print(f,f.name) #<__main__.Open object at 0x0000022813E55C88> a.txt
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('异常产生')
print('0'*100) #------------------------------->不会执行
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type) #<class 'AttributeError'>
print(exc_val) #产生异常
print(exc_tb) #<traceback object at 0x000001E54419AF08>
return True
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('产生异常')
print('0'*100) #------------------------------->会执行
模拟open:
class Open:
def __init__(self,filepath,mode='r',encoding='utf-8'):
self.filepath=filepath
self.mode=mode
self.encoding=encoding
def __enter__(self):
print('enter')
self.f=open(self.filepath,mode=self.mode,encoding=self.encoding) #拿到文件句柄
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
# print('exit')
self.f.close()
return True
def __getattr__(self, item):
return getattr(self.f,item)
with Open('a.txt','w') as f: #f==open(self.filepath,mode=self.mode,encoding=self.encoding)
print(f) #<_io.TextIOWrapper name='a.txt' mode='w' encoding='utf-8'>
f.write('aaaaaa')
f.wasdf #抛出异常,交给__exit__处理
1.3、上下文管理用途
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
二、描述符
2.1、什么是描述符?
描述符本质就是一个新式类,在这个新式类中,至少实现__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
class Foo: #在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
pass
def __delete__(self, instance):
pass
2.2、描述符是干什么的?
描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
#描述符Int
class Int:
def __get__(self, instance, owner):
print('Int调用')
def __set__(self, instance, value):
print('Int设置...')
def __delete__(self, instance):
print('Int删除...')
class People:
name=Str()
age=Int()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age
p1=People('alex',18) #触发str类的__set__,触发int类的__set__
print("========")
#描述符Str的使用
print(p1.name) #Str调用 None
p1.name='egon'
del p1.name
#描述符Int的使用
p1.age #Int调用
p1.age=18 #Int设置...
del p1.age #Int删除...
print(p1.__dict__) #{}
print(People.__dict__) #{'__init__': <function People.__init__ at 0x000001714E4CE620>, 'age': <__main__.Int object at 0x000001714E4D46D8>, '__module__': '__main__', 'name': <__main__.Str object at 0x000001714E4D46A0>, '__dict__': <attribute '__dict__' of 'People' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'People' objects>}
#补充
print(type(p1) == People) #True,type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__) #True
2.3、描述符的种类
1)数据描述符:至少实现了__get__()和__set__()
class Foo:
def __set__(self, instance, value):
print('set')
def __get__(self, instance, owner):
print('get')
2)非数据描述符:没有实现__set__()
class Foo:
def __get__(self, instance, owner):
print('get')
2.4、描述符注意事项
1)描述符本身应该定义成新式类,被代理的类也应该是新式类
2)必须把描述符定义成这个类的类属性,不能为定义到构造函数中
3)要严格遵循该优先级,优先级由高到底分别是
- 类属性
- 数据描述符
- 实例属性
- 非数据描述符
- 找不到的属性(触发__getattr__)
2.5、描述符优先级
1)类属性>数据描述符
#数据描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
class People:
name=Str()
def __init__(self,name,age): #name被Str类代理
self.name=name
self.age=age
#在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典
People.name #Str调用 ==>调用类属性name,本质就是在调用描述符Str,触发了__get__()
People.name="AAA" #没有触发__set__
print(People.name) #AAA
del People.name #没有触发__delete__
'''
原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级
People.name #调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()
People.name='egon' #直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()
del People.name #同上
'''
2)数据描述符>实例属性
#数据描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
class People:
name=Str()
def __init__(self,name,age): #name被Str类代理
self.name=name
self.age=age
p1=People('egon',18) #触发__set__
#如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
p1.name="AAA" #触发__set__
p1.name #Str调用
print(p1.__dict__) #{'age': 18} ==>并没有name属性 ==>name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
print(People.__dict__) #'name': <__main__.Str object at 0x00000202C1DF5D30>
del p1.name #Str删除...
3)实例属性>非数据描述符
#非数据描述符
class Str:
def __get__(self, instance, owner):
print('Str调用')
class People:
name=Str()
def __init__(self,name,age): #name被Str类代理
self.name=name
self.age=age
p1=People('egon',18)
print(p1.name) #egon #没有触发__get__方法
print(p1.__dict__) #{'age': 18, 'name': 'egon'}
4)非数据描述符>找不到
class Foo:
def func(self):
print('我胡汉三又回来了')
def __getattr__(self, item):
print('找不到了当然是来找我啦',item)
f1=Foo()
f1.xxxxxxxxxxx #找不到了当然是来找我啦 xxxxxxxxxxx
2.6、描述符的使用
2.6.1、参数类型限制
python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能
class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
return instance.__dict__[self.name]
def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name)
class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=People('egon',18,3231.3) #set---> <__main__.People object at 0x00000274AA9B4668> egon
#调用
print(p1.__dict__) #{'salary': 3231.3, 'age': 18, 'name': 'egon'}
p1.name #get---> <__main__.People object at 0x000001BCB50B4668> <class '__main__.People'>
print(p1.name) #egon
#赋值
print(p1.__dict__) #{'age': 18, 'name': 'egon', 'salary': 3231.3}
p1.name='egonlin' #触发set
print(p1.__dict__) #{'age': 18, 'name': 'egonlin', 'salary': 3231.3}
#删除
print(p1.__dict__) #{'salary': 3231.3, 'name': 'egonlin', 'age': 18}
del p1.name #触发delete
print(p1.__dict__) #{'salary': 3231.3, 'age': 18}
实例二:
class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
return instance.__dict__[self.name]
def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name)
class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
# 疑问:如果我用类名去操作属性呢 ==>没有初始化实例
People.name #报错,错误的根源在于类去操作属性时,会把None传给instance
#修订__get__方法
class Str:
def __init__(self,name):
self.name=name
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
print('set--->',instance,value)
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name)
class People:
name=Str('name')
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(People.name)
#输出
# get---> None <class '__main__.People'>
# <__main__.Str object at 0x0000020ABCE05D68>
实例三:
class Typed:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
print('set--->',instance,value)
if not isinstance(value,self.expected_type):
raise TypeError('Expected %s' %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name)
class People:
name=Typed('name',str)
age=Typed('name',int)
salary=Typed('name',float)
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
# p1=People(123,18,3333.3) #TypeError: Expected <class 'str'>
# p1=People('egon','18',3333.3) #TypeError: Expected <class 'int'>
p1=People('egon',18,3333) #TypeError: Expected <class 'float'>
2.7、类的装饰器
1)类的装饰器--无参
def decorate(cls):
print("类的装饰器")
return cls
@decorate #People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=People("AAA",18,333.33)
2)类的装饰器--有参
def typeassert(**kwargs):
def decorate(cls):
print('类的装饰器开始运行啦------>',kwargs)
return cls
return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
p1=People('egon',18,3333.3)
#类的装饰器开始运行啦------> {'salary': <class 'float'>, 'age': <class 'int'>, 'name': <class 'str'>}
3)与描述符结合
class Typed:
def __init__(self,name,expected_type):
self.name=name
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get--->',instance,owner)
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
print('set--->',instance,value)
if not isinstance(value,self.expected_type):
raise TypeError('Expected %s' %str(self.expected_type))
instance.__dict__[self.name]=value
def __delete__(self, instance):
print('delete--->',instance)
instance.__dict__.pop(self.name)
def typeassert(**kwargs):
def decorate(cls):
print('类的装饰器开始运行啦------>',kwargs)
for name,expected_type in kwargs.items():
setattr(cls,name,Typed(name,expected_type))
return cls
return decorate
@typeassert(name=str,age=int,salary=float) #有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
class People:
def __init__(self,name,age,salary):
self.name=name
self.age=age
self.salary=salary
print(People.__dict__)
#{'age': <__main__.Typed object at 0x000001C81FC155F8>, '__doc__': None, 'name': <__main__.Typed object at 0x000001C81FC156A0>, '__weakref__': <attribute '__weakref__' of 'People' objects>, 'salary': <__main__.Typed object at 0x000001C81FC15668>, '__dict__': <attribute '__dict__' of 'People' objects>, '__init__': <function People.__init__ at 0x000001C81FC0E620>, '__module__': '__main__'}
p1=People('egon',18,3333.3)
# p1=People('egon','18',3333.3) #TypeError: Expected <class 'int'>
2.8、描述符总结
描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性
描述父是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件.
2.9、自定制@property
利用描述符原理完成一个自定制@property,实现延迟计算(本质就是把一个函数属性利用装饰器原理做成一个描述符:类的属性字典中函数名为key,value为描述符类产生的对象)
1)@property回顾
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@property
def area(self):
return self.width * self.length
r1=Room('AA',1,1)
print(r1.area) #1
2)自定制property
class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None: #如果是类调用,会返回none ==>Room.area
return self
return self.func(instance)
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
def area(self):
return self.width * self.length
print(Room.__dict__) #==>相当于在类中添加了一个属性 ==>'area': <__main__.Lazyproperty object at 0x000001ED1F016C50>}
r1=Room('alex',1,1)
print(r1.__dict__) #{'length': 1, 'width': 1, 'name': 'alex'}
print(r1.area) #先在实例属性中查找,没找到到类中查找,属性被描述符代理,触发__get__方法
print(Room.area) #<__main__.Lazyproperty object at 0x000001D492CF5358>
3)实现延迟计算功能
class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None:
return self
else:
print('--->')
# print(self) #<__main__.Lazyproperty object at 0x0000024F8E435550>
# print(self.func) #<function Room.area at 0x000001E9D740E488>
value=self.func(instance) #self.func ===>传进来的area(),需要 将实例传进去 ==>值为1
# print(self.func.__name__) #area
setattr(instance,self.func.__name__,value) #计算一次就缓存到实例的属性字典中
return value
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@Lazyproperty #area=Lazyproperty(area) 相当于'定义了一个类属性,即描述符'
def area(self):
return self.width * self.length
r1=Room('alex',1,1)
# print(r1.__dict__) #{'width': 1, 'name': 'alex', 'length': 1}
print(r1.area) #先从自己的属性字典找,没有再去类的中找,然后触发了area的__get__方法
# print(r1.__dict__) #{'name': 'alex', 'area': 1, 'width': 1, 'length': 1}
# print(r1.area) #先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算,直接在实例属性字典中查找
4)小小改动
class Lazyproperty:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner):
print('这是我们自己定制的静态属性,r1.area实际是要执行r1.area()')
if instance is None:
return self
else:
value=self.func(instance)
instance.__dict__[self.func.__name__]=value
return value
# return self.func(instance)
def __set__(self, instance, value): #实现了set方法,此时是数据描述符,优先级高于实例属性
print('hahahahahah')
class Room:
def __init__(self,name,width,length):
self.name=name
self.width=width
self.length=length
@Lazyproperty #area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
def area(self):
return self.width * self.length
print(Room.__dict__) #==>'area': <__main__.Lazyproperty object at 0x000001D868D35550>}
r1=Room('alex',1,1)
print(r1.area)
print(r1.area)
print(r1.area)
print(r1.area) #缓存功能失效,每次都去找描述符了,因为描述符实现了set方法,它由非数据描述符变成了数据描述符,数据描述符比实例属性有更高的优先级,因而所有的属性操作都去找描述符了
#输出
这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
1
这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
1
这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
1
这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
1
2.10、自制@classmethod
class ClassMethod:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(owner,*args,**kwargs)
return feedback
class People:
name='AAA'
@ClassMethod # say_hi=ClassMethod(say_hi)
def say_hi(cls,msg):
print('%s %s' %(cls.name,msg))
print(People.__dict__) #==>'say_hi': <__main__.ClassMethod object at 0x000001EF2EA16B00>
People.say_hi('hello')
p1=People()
p1.say_hi('hello')
2.11、自制@staticmethod
class StaticMethod:
def __init__(self,func):
self.func=func
def __get__(self, instance, owner): #类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
def feedback(*args,**kwargs):
print('在这里可以加功能啊...')
return self.func(*args,**kwargs)
return feedback
class People:
@StaticMethod #say_hi=StaticMethod(say_hi)
def say_hi(x,y,z):
print('------>',x,y,z)
print(People.__dict__) #==>'say_hi': <__main__.StaticMethod object at 0x000001C3D63C5518>
People.say_hi(1,2,3)
p1=People()
p1.say_hi(4,5,6)
三、property使用
3.1、property本质
一个静态属性property本质就是实现了get,set,delete三种方法
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊')
@AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA #get的时候运行我啊
f1.AAA='aaa' #set的时候运行我啊
del f1.AAA #delete的时候运行我啊
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#第二种写法
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
3.2、property使用
使用示例一:
class Goods:
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
print(obj.price)
del obj.price # 删除商品原价
四、元类
4.1、元类的引出
参考文档:https://www.cnblogs.com/linhaifeng/articles/8029564.html
python中一切都是对象,类本身也是一个对象,当使用class时,解释器会在加载class时就会创建一个对象(这里的对象值的是类而不是实例)
class Foo:
pass
f1=Foo()
#使用type()查看类型
print(type(f1)) #<class '__main__.Foo'>
print(type(Foo)) #<class 'type'>
print(type(object)) #<class 'type'>
4.2、什么是元类
元类是类的类,是类的模板
元类是控制如何创建类的,正如类是创建对象的模板一样
元类的实例是类,正如类的实例是对象(f1对象是Foo类的一个实例,Foo类是type类的一个 实例)
type是python中一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类的实例
一个类如果没有声明自己的元类,默认他的类就是type,除了使用元类,用户也可以通过继承type来自定义元类
4.3、类的创建方式
方式一:
class Foo:
def func(self):
print("func")
print(Foo) #<class '__main__.Foo'>
print(Foo.__dict__)
#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, 'func': <function Foo.func at 0x0000024EDB86E158>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
方式二:
def func(self):
print("func")
x=1
Foo=type("Foo",(object,),{"func":func,"x":1})
print(Foo) #<class '__main__.Foo'>
print(Foo.__dict__)
#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, 'x': 1, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'func': <function func at 0x0000019343BA7F28>}
4.4、自定制元类
分析版:
class MyType(type):
def __init__(self,a,b,c):
print('元类的构造函数执行')
# print(a) #Foo
# print(b) #()
# print(c) #{'__module__': '__main__', '__init__': <function Foo.__init__ at 0x000001BE2AB9E400>, '__qualname__': 'Foo'}
def __call__(self, *args, **kwargs):
print('=-======>')
print(self) #<class '__main__.Foo'>
print(args,kwargs) #('alex',) {}
obj=object.__new__(self) #object.__new__(Foo)-->f1 #创建Foo实例化出来的实例f1
# print(obj) #<__main__.Foo object at 0x0000020492F45550>
self.__init__(obj,*args,**kwargs) #Foo.__init__(f1,*arg,**kwargs),传入参数
return obj #返回实例化的对象给f1
class Foo(metaclass=MyType): #Foo=MyType(Foo,'Foo',(),{})---》__init__
def __init__(self,name):
self.name=name #f1.name=name
print(Foo) #<class '__main__.Foo'>
f1=Foo('alex') #实例() ==>调用父类的__call__方法
print(f1) #<__main__.Foo object at 0x00000133525E5550>
print(f1.__dict__) #{'name': 'alex'}
精简版:
#通过断点分析
class MyType(type):
def __init__(self,a,b,c):
print('元类的构造函数执行')
def __call__(self, *args, **kwargs):
obj=object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj
class Foo(metaclass=MyType):
def __init__(self,name):
self.name=name
f1=Foo('alex')