python进阶-面向对象编程六:元类

什么是元类

# typer===>produce class===>produce obj
# type称谓元类,是所有类的类,利用type控制类的行为

模拟class关键字创建类的过程:类被创建的2种方法

# 模拟class关键字创建类的过程



# 创建类的两种方式
# 方式一:

class Foo:
    def func(self):
        print('from func')

# 方式二:
x = 1
def func(self):
    print('from func')
Foo=type('Foo',(object,),{'func':func,'x':1})





# 创建类的两种方式
# 方式一:
class Foo:
    x=1
    def run(self):
        pass

print(type(Foo))
# <class 'type'>



# 方式二:
class_name="Bar"

def Run(self):
    print("%s is running"%self.name)
bases=(object,)

class_dic={
    "x":1,
    "run":Run
}

Bar=type(class_name,bases,class_dic)
print(Bar)
print(type(Bar))
print(type("123"))
print(type(123))

# 运行结果:
# <class '__main__.Bar'>
# <class 'type'>
# <class 'str'>
# <class 'int'>

 

自定制一个元类,让它必需具有注释

# 元类,我们重定义的元类如果不写注释就暴错

class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dic):
        for key in class_dic:
            if not callable(class_dic[key]):continue
            if not class_dic[key].__doc__:
                raise TypeError("all the func must be notes")


class Foo(metaclass=Mymeta):
    x=1
    def run(self):
        '所有函数必须写注释'
        print("class Foo")


Foo().run()

  

创建元类的具体过程

# 一切皆对象,类也是对象,元类就是类的类

# type()内建函数可以创建类

class C(object):
    pass
c=C()
print(c)
print(C)

# <__main__.C object at 0x10d41fc18>
# <class '__main__.C'>


# type(类名, 父类的元组(可以为空), 属性的字典)
def printinfo(self):
    print("%s age %s"%(self.name,self.age))
S = type("Student",(object,),{"name":'adamanter',"age":24,"printinfo":printinfo})

print(type(S))
s=S()
print(type(s))
s.printinfo()
# <class 'type'>
# <class '__main__.Student'>
# adamanter age 24


# 函数type实际上是一个元类,元类就是用来创建类的"模板"。
# 我们可以通过类"模板"创建实例对象,同样,也可以使用元类"模板"来创建类对象;
# 也就是说,元类就是类的类.

# 创建类的过程是,__new__,__init__,创建出类来进行实例化的过程是__call__


# python2
# 在创建一个类的时候,可以设置"__metaclass__"属性来指定元类。
# __metaclass__ = QueueMetaclass
# 属性后面对应的就是创建类的代码,可以是函数,也可以是一个类
# 元类的查找就是根据__metaclass__属性一层层向父类查找,如果找不到就用type创建类对象

# python3:
# class Hello(matacalss=QueueMetaclass):
#   pass


def queueMeta(name, bases, attrs):
    attrs['InQueue'] = lambda self, value: self.append(value)

    def deQueue(self):
        if len(self) > 0:
            return self.pop(0)

    attrs['DeQueue'] = deQueue

    # 直接调用type内建函数
    return type(name, bases, attrs)


# 元类从`type`类型派生
class QueueMetaclass(type):
    def __new__(cls, name, bases, attrs):
        cls.name = name
        cls.bases = bases
        attrs['InQueue'] = lambda self, value: self.append(value)
        print("cls",cls)
        print("name",cls.name)
        print("bases",cls.bases)

        def deQueue(self):
            if len(self) > 0:
                return self.pop(0)

        attrs['DeQueue'] = deQueue

        # 直接调用type内建函数
        # return type(name, bases, attrs)

        # 通过父类的__new__方法
        return type.__new__(cls, name, bases, attrs)


class MyQueue(metaclass=QueueMetaclass):
    # 设置metaclass属性,可以使用一个函数,也可以使用一个类,只要是可以创建类的代码
    # __metaclass__ = queueMeta

    pass


q = MyQueue()
print(q)

# 拦截类的创建
# 根据"__metaclass__"对应的代码修改类
# 返回修改之后的类


class MyMetaclass(type):
    def __new__(meta, name, bases, attrs):
        print('-----------------------------------')
        print("Allocating memory for class:", name)
        print(meta)
        print(bases)
        print(attrs)
        return super(MyMetaclass, meta).__new__(meta, name, bases, attrs)

    def __init__(cls, name, bases, attrs):
        print('-----------------------------------')
        print("Initializing class:", name)
        print(cls)
        print(bases)
        print(attrs)
        super(MyMetaclass, cls).__init__(name, bases, attrs)


class MyClass(metaclass=MyMetaclass):
    def foo(self, param):
        pass


myclass = MyClass()

# -----------------------------------
# Allocating memory for class MyClass
# <class '__main__.MyMetaclass'>
# ()
# {'foo': <function MyClass.foo at 0x10757e620>, '__module__': '__main__', '__qualname__': 'MyClass'}
# -----------------------------------
# Initializing class MyClass
# <class '__main__.MyClass'>
# ()
# {'foo': <function MyClass.foo at 0x10757e620>, '__module__': '__main__', '__qualname__': 'MyClass'}

  

 

posted @ 2017-09-13 20:34  Adamanter  阅读(98)  评论(0编辑  收藏  举报