#type只传一个参数有什么用?
#打印对象的类型
# print(type(1))
#class 底层原理,通过type类来实例化得到类
# def __init__(self,name):
# self.name=name
# Person=type('Person',(object,),{'x':1,'__init__':__init__})
# p=Person('lqz')
# print(Person.__dict__)
# print(p.__dict__)
# print(p.x)
#等同于
# class Person(object):
# x=1
# def __init__(self, name):
# self.name = name
# p=Person('lqz')
# print(Person.__dict__)
# print(p.__dict__)
# print(p.x)
#exec 执行字符串的代码,当成python解释器
# ss='''
# x=1
# print(x)
# '''
# g={}
# l={}
# exec(ss,g,l)
# print(l)
#自定义元类:继承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属性,不能创建')
# # def __call__(self, *args, **kwargs):
# # pass
#
# 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('lqz') #自动触发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')
#昨天的作业
# 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'])
#不用init方法,但是能完成对象的初始化
#赠送元类
# object.__new__
# 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)
#__new__和__init__的区别
#__new__ 创建空对象
#__init__ 初始化空对象
#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类中有名称空间之类的了
# print('xxxxxxx')
# print(args)
# print(kwargs)
# print(name)
# print(bases)
# print(dic)
pass
# self.name='xxxxxxx'
def __new__(cls, name,bases,dic):
# print(name)
# print(bases)
# print(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'])
# p=Person('nick',18)