回顾
一、sorted()和sort()的区别
sorted():是内置函数,并不会修改原来的列表,可以针对字典等 迭代,有返回值
sort():是绑定方法,会改变原有的列表,不能针对字典等迭代,没有返回值
二、自定义字典
自定义字典,使其具备点取值和点赋值功能
class Mymeta(dict):
def __setattr__(self, key, value): #字典.get获取值会出现递归
self[key] = value #key = sex #value = female
def __getattr__(self, item):
return self[item] #就是获取键值对 name:yjy
di = Mymeta(name = 'yjy',age = 20)
print(di.name) #点取值
di.sex = 'female' #点赋值
print(di['sex'])
## 三、自定义元类
自定义元类,定义一个类,类的名称空间中必须有name
字段才能成功,否则失败
class Mymeta(type):
def __init__(self,name,bases,dic): #dic是类的属性和方法
if 'name' not in dic:
raise Exception ('属性没有name字段')
class Person(metaclass=Mymeta):
name = 'oldboy'
p = Person() #oldboy
print(p.name)
自定义元类,定义一个类,继承字典,使其具备点取值和点赋值功能,通过元类控制的产生,把所有对象的属性放到attr字典中,属性全删除
eg:di = Mydict(name = 'yjy',age = 18)
di的名称空间中没有属性,只有attr字典,但是在attr字典中有其属性
class Mymeta(type):
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
obj.__init__(*args, **kwargs)
attr = kwargs
obj.__dict__.clear()
obj.__dict__['attr'] = attr
return obj
class Mydict(dict,object,metaclass=Mymeta):
def __init__(self,**kwargs):
self.__dict__.update(kwargs)
def __getattr__(self, item):
return self.__dict__['attr'][item]
def __setattr__(self, key, value):
self.__dict__['attr'][key] = value
di = Mydict(name = 'qqq',age = 18)
print(di.name)
di.sex= 'male'
print(di.sex)
在元类中控制把自定义类的数据属性都变成大写
class Mymeta(type):
def __new__(cls, name,bases,dic):
for k,v in dic.items():
if not k.startswith('__'):
print(k.upper())
class Person(metaclass=Mymeta):
school='oldboy'
age=10
在元类中控制自定义类,无需__init__方法
class Mymeta(type):
def __call__(self, name,age):
obj = object.__new__(self)
obj.name = name
obj.age = age
return obj
class Person(metaclass=Mymeta):
school='oldboy'
age=10
p = Person('yjy',18)
print(p.__dict__)
在元类中控制把自定义类的数据属性都放在attr中
class Mymeta(type):
def __new__(cls, name,bases,dic):
dic2={'attr':{}}
for k,v in dic.items():
if not k.startswith('__'):
dic2['attr'][k]=v
return type.__new__(cls,name,bases,dic2)
class Person(metaclass=Mymeta):
school='oldboy'
age=10
print(Person.attr['school'])
#自定义元类:继承type
class Mymeta(type):
def __init__(self,name,bases,dic):
#self 是Person 这个类(对象)
#在这个位置,其实self也就说Person这个类,内部已经有东西了,名称空间已经有东西了
#所以在这个地方,可以通过dic来判断名称空间
#也可以直接通过self.__dict__/self.属性 来判断
a=dic.get('name')
if not a :
raise Exception('没有name属性,不能创建')
class Person(metaclass=Mymeta): #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
# class Person(): #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
def __init__(self,name):
self.name=name
raise Exception('就不让你创建')
p=Person('yjy') #自动触发Person类__init__的执行
#总结:可以通过自定义元类,重写__init__方法来控制类的产生
#通过元类控制类的调用过程,实例化产生对象的过程
class Mymeta(type):
def __call__(self, *args, **kwargs):
#该方法必须返回一个对象(类对象),这个地方返回什么 p=Person('lqz') p就是什么
#返回一个真正的Person类的对象
#第一步:产生一个空对象
#object.__new__(self) 传一个参数,传类,就会产生一个该类的空对象
#obj是Person类的空对象
obj=object.__new__(self)
# print(self.__new__ is object.__new__) # True
#第二步:初始化该对象,把初始值放到对象中
#obj是Person类的空对象 obj.__init__ 调用自己的绑定方法,也就说Person类中写的__init__方法
obj.__init__(*args, **kwargs)
#还可以类来调用
# Person.__init__(obj,*args, **kwargs)
# self.__init__(obj,*args, **kwargs)
# print(obj.name)
#第三步:把该对象返回
return obj
class Person(metaclass=Mymeta):
# class Person():
def __init__(self,name):
self.name=name
def __call__(self, *args, **kwargs):
print('xxx')
p=Person('lqz')
print(p.name)
print(p)
# 原来的理解Person('lqz') 会调用Person类的__init__的方法
# 这个位置会调用元类的__call__方法,所以在__call__方法中调用了Person __init__方法,来完成对象的初始化
p()
#模板:控制对象的产生
class Mymeta(type):
def __call__(self, *args, **kwargs):
obj=object.__new__(self)
obj.__init__(*args, **kwargs)
return obj
class Person(metaclass=Mymeta):
def __init__(self,name):
self.name=name
def __call__(self, *args, **kwargs):
print('xxx')
p=Person('lqz')
#不用init方法,但是能完成对象的初始化
class Mymeta(type):
def __call__(self, name,age):
# print(name)
# print(age)
obj=object.__new__(self)
# obj.__init__(name,age)
# obj.name=name
# obj.age=age
obj.__dict__['attr']={'name':name,'age':age}
return obj
class Person(metaclass=Mymeta):
def __init__(self,name,age):
self.name=name
self.age=age
p=Person('lqz',18)
print(p.__dict__)
print(p.attr['name'])
元类高阶
__new__和__init__的区别
__new__ 创建空对象
__init__ 初始化空对象
------------------------------------------------------------------------------------
class Person():
def __init__(self,name,age):
print('__init__')
self.name=name
self.age=age
def __new__(cls, *args, **kwargs):
print('__new__')
#生成一个Person类的空对象
return object.__new__(cls)
p=Person('lqz',19)
print(p)
object.__new__ 传哪个类就得到哪个类的空对象
p=object.__new__(Person)
print(p)
object.__new__(Person) :生成Person类的对象 空的
type.__new__(cls,name,bases,dic) :生了cls这个类对象,里面有东西
元类中
__init__:控制类的产生,在__new__之后
__call__:对着对象的产生
__new__:控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了了
---------------------------------------------------------------------------------
class Mymeta(type):
def __init__(self,name,bases,dic):
#self 是Person类,Person类中有名称空间之类的了
pass
def __new__(cls, name,bases,dic):
#产生空对象(空类),在这里面生成的并不是空类,是有数据的类了
#如何完成类的初始化,并且把name,bases,dic这些东西放入
# return type.__new__(cls,name,bases,dic)
dic2={'attr':{}}
for k,v in dic.items():
#加入这一句,类名称空间中带__的就不会放到attr中
if not k.startswith('__'):
dic2['attr'][k]=v
print('-------',dic2)
return type.__new__(cls,name,bases,dic2)
class Person(metaclass=Mymeta): # Person=Mymeta(name,bases,dic) 调用type的__call__,内部调用了Mymeta.__new__,又掉Mymeta的__init__
school='oldboy'
age=10
def __init__(self,name,age):
self.name=name
self.age=age
print(Person.__dict__)
print(Person.attr['school'])