首页 > 技术文章 > python :面向对象 学习笔记(2)

gtq7512 2019-08-31 16:27 原文

创建一个类的特殊方式

  类的创建过程:类的创建,先是寻找它是否有元类,如果没有会找它继承的父类是否有元类,如果没有就继续寻找父类的父类,直到所有父类都没有,就会调用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()
type创建类 

  (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)
metaclass创建类

  一个类的创建,第一步是调用__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)
View Code

 

推荐阅读