metaclass概述
metaclass 像一个魔法盒,可以动态修改python 类对象 的属性及方法等。没错,我这里暂且称之为类对象,
因为它以对象的方式来表示一个类(比如 class Myclass:pass);在python中,一切皆对象。
本文主要介绍在python2.7的环境下,如何增加模块级的__metaclass__。
对于不清楚metaclass的同学,可以参考这篇文章:
深刻理解 Python 中的元类(metaclass)
采用函数方法增加模块metaclass
代码如下:
# metaclass函数
def upper(cls_name, cls_parents, cls_attr):
""" Make all class attributes uppper case """
attrs = ((name, value) for name, value in cls_attr.items()
if not name.startswith('__'))
upper_atts = dict((name.upper(), value) for name, value in attrs)
return type(cls_name, cls_parents, upper_atts)
__metaclass__ = upper #module level
class Foo:
foo = 1
class Bar:
bar = 1
此时,Foo类中的的foo属性变成了Foo,Bar类中的的bar属性变成了BAR。如果只需要对某个类增加metaclass属性,则只需要在该类中增加 metaclass = upper。
注意:在python3.5中,不支持这种方式来定论模块metaclass属性。
采用OPP方式增加模块metaclass
一开始开心地以为可以直接采用类似函数的方式来实现模块级metaclass,代码如下:
class UpperAttrMetaclass(type):
def __new__(cls, name, bases, dct):
attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
__metaclass__ = UpperAttrMetaclass
class Foo(object):
foo = 1
def __init__(self, foo1):
self.foo1 = foo1
此时还高兴的以为Foo增加了metaclass属性,将foo属性变成了FOO; 而实际上并没有。多么痛的领悟啊!那怎么办呢?经过各种查,找到了一个解决方法,可以采用继承的方式来实现metaclass属性,而且这各方式还可以灵活的选择所要继承的metaclass。
代码如下:
class UpperAttrMetaclass(type):
def __new__(cls, name, bases, dct):
attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
class Up(object):
__metaclass__ = UpperAttrMetaclass
class Foo(Up):
foo = 1
def __init__(self, foo1):
self.foo1 = foo1
该方法可以解决python3.5中不支持 函数式metaclass 的问题
也许还有更好的方法,望大神们指正与探讨!!!