python3 元类

pipidi

zhujingdi1998@gmail.com

虽然元类不常用但是还是做了一些了解

def choose_class(name):
    if name=='foo':
        class Foo(object):
            pass
        return Foo
    else:
        class Bar(object):
            pass
        return Bar
MyClass=choose_class('foo')
print(type(MyClass))
#<class 'type'>

type一般是用于查看一个对象的类对吧
之前也是经常用到这个东西 但是 我们知道python一切都是对象 例如函数 例如类 既然类是对象 哪么类对象的类是什么哪 !type! 我们把类对象的类叫做元类

经过尝试 发现所有的python的类都源自于type 那么type是怎么创建类的呢?

print(type('MyShinyClass',(),{}))
#<class '__main__.MyShinyClass'>

type 可以根据传入的参数 不同来进行不同的操作 因为type是这样设置 默认值参数的

type(object_or_name, bases, dict)
        type(object) -> the object's type
        type(name, bases, dict) -> a new type
        # (copied from class doc)

我们可以传入一个类的名字和他的父类和他的属性字典来创建一个新的类 这就是手动取创建一个类 和

class MyShinyClass(object):
    pass

没有区别 其实感觉class关键词 简化了手动创建类的操作

#class Foo(object):
#    bar=True
# 使用type创建类
Foo=type("Foo",(),{'bar':True})

print(Foo)
print(Foo.bar)

#<class '__main__.Foo'>
#True
Foo=type("Foo",(),{'bar':True})

# print(Foo)
# print(Foo.bar)
class FooChild(Foo):
    pass

print(type("Foochild",(Foo,),{}))

这样可以继承父类

我们还可用为子类添加方法

def echo_bar(self):
    print(self.bar)
class Foo(object):
    bar=True
FooChild=type("FooChild",(Foo,),{'echo_bar':echo_bar})
print(hasattr(Foo,'echo_bar'))
print(hasattr(FooChild,'echo_bar'))

#False
#True

那么如何自定义元类呢! 都这么久了,让我来慢慢讲给你听吧!

首先我们知道type是所有类的类把! 首先我们看一下使用元类实现单例模式

class Singleton(type):
    def __init__(self, *args, **kwargs):
        print("__init__")
        self.__instance = None

        super(Singleton,self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        print("__call__")

        if self.__instance is None:
            self.__instance = super(Singleton, self).__call__(*args, **kwargs)
        return self.__instance
#实现单例
class Foo(metaclass=Singleton ): pass
Foo()
class upper_attr(type):
    def __new__(self,future_class_name, future_class_parents, future_class_attr):
        uppercase_attr = {}
        for name,val in future_class_attr.items():
            if not name.startswith("__"):
                uppercase_attr[name.upper()]=val
            else:
                uppercase_attr[name]=val
        # super(upper_attr,self).__init__(future_class_name,future_class_parents,uppercase_attr)
        return type(future_class_name, future_class_parents, uppercase_attr)
#用new 返回一个对象
Foo=upper_attr("Foo",(),{'bar':'bip'})
print(Foo.BAR)
#put bip

上述元类的作用是将Foo的小写的普通方法转换为大写的方法 上面的upper_attr类实现的 主要是通过继承type类 我们使用__new__方法返回一个加工好了之后的类对象

在python3中我们不再采用__metaclass__属性 采用

class FOO(metaclass=upper_attr):
    bar='bip'
print(FOO.BAR)

这样的方法

class UpperAttrMetaclass(type):

    def __new__(upperattr_metaclass, future_class_name,
                future_class_parents, future_class_attr):

        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        # reuse the type.__new__ method
        # this is basic OOP, nothing magic in there
        return super(UpperAttrMetaclass,upperattr_metaclass).__new__(upperattr_metaclass, future_class_name,
                            future_class_parents, uppercase_attr)

我们可以采用super(UpperAttrMetaclass,upperattr_metaclass) 去调用父类type的__new__方法 与用tpye相同

阅读量