python :面向对象 学习笔记(2)
创建一个类的特殊方式:
类的创建过程:类的创建,先是寻找它是否有元类,如果没有会找它继承的父类是否有元类,如果没有就继续寻找父类的父类,直到所有父类都没有,就会调用type来创建这个类。否则,用找到的元类对这个类进行创建。但实际上元类是继承type的,所有最终还是需要调用type创建一个类!
(1)使用type创建类的方式:
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
def func(self): print("%s xxxx"%self.name) def __init__(self,name): self.name = name Foo =type('Foo',(object,),{'talk':func, '__init__':__init__,}) a = Foo('leo') a.talk()
(2)使用元类(metaclass)创建类:
def func(self): print("%s xxxx"%self.name) class Mytype(type): ''' 相当于中间商, ''' def __new__(cls,name, base,attr): print("Mytype __new__ ****", name,"****",base,"****",attr) attr["talk"] = func return type.__new__(cls,name,base,attr) def __init__(self,name,base,attr): super(Mytype, self).__init__(name,base,attr) if name.islower(): raise TypeError('类名必须使用驼峰体') doc = attr.get('__doc__') if doc is None or len(doc) == 0 or len(doc.strip('\n ')) == 0: raise TypeError('类体中必须有文档注释,且不能为空') print("Mytype __init__ ****",name,"****",base,"****",attr) def __call__(self, *args, **kwargs): print("-----cal--------", args, kwargs) args = ("aaa",) obj = self.__new__(self,*args, **kwargs)#Foo.__new__(cls, name, bases, attrs) self.__init__(obj,*args, **kwargs) return obj class Foo(object,metaclass = Mytype):# metaclass = Mytype ''' # __metaclass__ = Mytype ''' def __init__(self, name, *args, **kwargs): self.name = name print("__init__",args,kwargs) def __new__(cls, *args, **kwargs): print("__new__",args,kwargs) return object.__new__(cls,) #继承父类的__new__方法 def sleep(self): print("Foo sleep") obj =Foo("alex") obj.talk() print(obj.name)
一个类的创建,第一步是调用__new__(),而不是__init__()。如果继承了父类,首先调用父类的__new__(),而后是父类的__init__(),如果父类中有__call__就会接着调用,之后才是子类的__new__()和__init__()。
class MyMeta(type): def __new__(cls, name, bases, attr): # 1 attr['add'] = lambda self, x, y : x+y attr['age'] = 0 print("MyMeta__new__",name, bases, attr) attr['addr'] = 'gz' return type.__new__(cls, name, bases, attr) def __call__(self, *args, **kwargs):# 3 print("__call__") obj= self.__new__(self, *args, **kwargs) self.gender ='female' self.__init__(self, *args, **kwargs) return obj def __init__(cls, name, bases, attr): # 2 super(MyMeta, cls).__init__(name, bases, attr) cls.gender = 'male' print("***********************8888") print(cls) print(name) print(bases) print(attr) print("***********************8888") class MyClass(object, metaclass=MyMeta): def __init__(self): # self.age = 1 self.name = 'hh' m = MyClass() print(m.name) print(m.gender) print(m.addr) print(m.age)