欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

什么是python中的元类

程序员文章站 2022-04-30 21:02:49
所属网站分类: python高级 > 面向对象 作者:goodbody 原文链接: http://www.pythonheidong.com/blog/article/11/ 来源:python黑洞网 www.pythonheidong.com 元类是类的类。就像类定义了类的实例的行为一样,元类定义 ......

所属网站分类: python高级 > 面向对象


作者:goodbody

原文链接: 

来源:python黑洞网 

 

元类是类的类。就像类定义了类的实例的行为一样,元类定义了类的行为方式。类是元类的实例。

虽然在python中你可以为元类使用任意的callables,实际上更有用的方法是使它成为一个真正的类本身。

type是python中常用的元类。type它本身就是一个类,它是它自己的类型。

你将无法使用type在python中重新创建纯粹的东西。

元类最常用作类工厂。就像通过调用类创建类的实例一样,python通过调用元类创建了一个新类(当它执行'class'语句时)。结合__init____new__方法,元类因此允许您在创建类时执行“额外的事情”,例如使用某个注册表注册新类,或者甚至完全用其他内容替换类。

 

元类是通过查看待定类的基类(继承的元类),__metaclass__将要在类的属性(如果有)或__metaclass__全局变量来确定的。然后使用类的名称,基数和属性调用元类来实例化它。

 

但是,元类实际上定义了类的类型,而不仅仅是它的工厂,所以你可以用它们做更多的事情。例如,您可以在元类上定义常规方法。这些元类方法就像类方法一样,因为它们可以在没有实例的类上调用,但它们也不像类方法,因为它们不能在类的实例上调用。type.__subclasses__()是type元类的方法示例。您还可以定义常规的“魔术”方法,例如__add__,__iter__以及__getattr__实现或更改类的行为方式。

这是例示:

 

def make_hook(f):
    """decorator to turn 'foo' method into '__foo__'"""
    f.is_hook = 1
    return f

class mytype(type):
    def __new__(mcls, name, bases, attrs):

        if name.startswith('none'):
            return none

        # go over attributes and see if they should be renamed.
        newattrs = {}
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, 'is_hook', 0):
                newattrs['__%s__' % attrname] = attrvalue
            else:
                newattrs[attrname] = attrvalue

        return super(mytype, mcls).__new__(mcls, name, bases, newattrs)

    def __init__(self, name, bases, attrs):
        super(mytype, self).__init__(name, bases, attrs)

        # classregistry.register(self, self.interfaces)
        print "would register class %s now." % self

    def __add__(self, other):
        class autoclass(self, other):
            pass
        return autoclass
        # alternatively, to autogenerate the classname as well as the class:
        # return type(self.__name__ + other.__name__, (self, other), {})

    def unregister(self):
        # classregistry.unregister(self)
        print "would unregister class %s now." % self

class myobject:
    __metaclass__ = mytype


class nonesample(myobject):
    pass

# will print "nonetype none"
print type(nonesample), repr(nonesample)

class example(myobject):
    def __init__(self, value):
        self.value = value
    @make_hook
    def add(self, other):
        return self.__class__(self.value + other.value)

# will unregister the class
example.unregister()

inst = example(10)
# will fail with an attributeerror
#inst.unregister()

print inst + inst
class sibling(myobject):
    pass

examplesibling = example + sibling
# examplesibling is now a subclass of both example and sibling (with no
# content of its own) although it will believe it's called 'autoclass'
print examplesibling
print examplesibling.__mro__