day 29 什么是元类、class底层原理分析、通过元类来控制类的产生、通过元类控制类的调用过程、有了元类之后的属性查找

元类

#一切皆对象:类实际上一个一个对象
#Person类也是个对象,那他一定是由一个类实例化得到,这个类,就叫元类
#type是内置的一个元类,所有的类都是由type实例化得到

#产生类的类,叫元类
class Person:
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')

p=Person('nick')

# a=Person
# p1=a('nick')
# print(p1.name)

如何找元类?
# print(type(p))
#同理:type类是产生所有类的元类
# print(type(Person))
print(type(dict))
print(type(list))
print(type(str))
print(type(object))
print(type(type))


class 底层原理
#class 类名 会把类构造出来,实际上是:元类实例化产生类这个对象,类实例化产生对象,一定是: 类名()#Person 类是由type实例化产生,传一堆参数
#class 底层就是调用type来实例化产生类(对象)
#type()  调用类的__init__方法???
#type(object_or_name, bases, dict)
object_or_name:类的名字,是个字符串
bases:是它的所有父类,基类,是一个元组
dict:名称空间,是一个字典

l={}
exec('''
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
''',{},l)
Person=type('Person',(object,),l)
或者
def __init__(self,name):
self.name=name
Person=type('Person',(object,),{'school':'oldboy','__init__':__init__})



#print(Person.__dict__)
#print(Person.__bases__)
# p=Person('nick')
# print(p.name)
# print(p.__dict__)



# class Person:
# school='oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('分数是100')
# a=Person
#
# p=Person('nick')

exec()的用法
# l={}
# exec('''
# school='oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('分数是100')
# ''',{},l)

# print(l)
# g={ 'x':1,'y':2}
# l={}
# exec('''
# global x
# x=100
# z=200
# m=300
# ''',g,l)
# print(g)
# print(l)

# x=1
# y=2
# def test():
# global x
# x = 100
# z = 200
# m = 300


通过元类来控制类的产生
自定义元类来控制类的产生,可以控制类名,可以控制类的继承父类,控制类的名称空间

自定义元类必须继承type,写一个类继承type 这种类都叫元类

class Mymeta(type):
def __init__(self,name,bases,dic):
# self 就是Person类
print(name)
print(bases)
print(dic)
#练习一:加限制 控制类名必须以sb开头
if not name.startswith('sb'):
raise Exception('类名没有以sb开头')




class Person(object,metaclass=Mymeta): #metaclass=Mymeta 指定这个类生成的时候,用自己写的Mymeta这个元类
     '''
注释
'''
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')

p=Person()
#练习二:类必须加注释
class Mymeta(type):
def __init__(self,name,bases,dic):
print(self.__dict__['__doc__'])
doc=self.__dict__['__doc__']
if not doc:
#没有加注释
raise Exception('你的类没有加注释')
class Person(object,metaclass=Mymeta):
'''
我加了注释
'''
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')




通过元类控制类的调用过程
#要使用到__call__
#控制类的调用过程,本质上在控制:对象的产生
class Mymeta(type):
def __call__(self, *args, **kwargs):
print('xxx')

return 1

class Person(object,metaclass=Mymeta):
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')

p=Person('nick')
print(p.name)
#打印xxx,并且p没有name属性


class Person():
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
def __call__(self, *args, **kwargs):
print('xxxx')

p=Person('nick') #自动触发init的执行
p() #先触发元类的__call__,也就是说__call__实例化的对象或者实例化的类加括号调用时才会触发__call__
#__new__方法
#练习:把对象中的所有属性都设置成私有
分析
class Mymeta(type):
def __call__(self, *args, **kwargs):
#self 是Person这个类
# print(args)
# print(kwargs)
# return self(*args) #这里不行,会递归

#实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
#obj 是Person类的对象,只不过是空的
obj=object.__new__(self)
#或者 obj=self.__new__(self)
         #调用__init__方法完成初始化
#类来调用__init__方法,就是个普通函数,有几个参数就穿几个惨
self.__init__(obj,*args, **kwargs)
#对象来调用__init__方法,对象的绑定方法,会把自身穿过来
obj.__init__(*args, **kwargs)
print(obj)
return obj


class Person(object, metaclass=Mymeta):
school = 'oldboy'
def __init__(self, name):
self.name = name
def score(self):
print('分数是100')
p = Person(name='nick')
print(p)
print(p.name)

#把对象所有的属性都变成私有
class Mymeta(type):
def __call__(self, *args, **kwargs):
obj=object.__new__(self)
obj.__init__(*args, **kwargs)
# print(obj.__dict__)
obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
# print(obj.__dict__)
return obj

class Person(object, metaclass=Mymeta):
school = 'oldboy'
def __init__(self, name):
self.name = name
def score(self):
print('分数是100')
p = Person(name='nick')
print(p.__dict__)
print(p.name)
# print(p)
# print(p.name)

 

有了元类之后的属性查找

对象最高查找到object
类最高查找到type




 
原文地址:https://www.cnblogs.com/wwei4332/p/11454150.html