我看过这样的帖子:
什么是Python中的元类?
Python中元类的(具体)用例是什么?
Python的超级很漂亮,但是你无法使用它
但不知怎的,我感到困惑.许多混淆如:
何时以及为什么我必须做以下事情?
# Refer link1 return super(MyType, cls).__new__(cls, name, bases, newattrs)
要么
# Refer link2 return super(MetaSingleton, cls).__call__(*args, **kw)
要么
# Refer link2 return type(self.__name__ + other.__name__, (self, other), {})
超级工作怎么样?
什么是link1中的类注册表和unregistry以及它究竟是如何工作的?(我认为它与单身人士有关.我可能是错的,来自C背景.我的编码风格仍然是功能和OO的混合).
类实例化(子类,元类,超类型)和方法调用的流程是什么(
metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass
)具有良好评论的工作代码(虽然第一个链接非常接近,但它没有谈论cls关键字和超级(..)和注册表).优选地,具有多重继承的示例.
PS:我把最后一部分作为代码,因为Stack Overflow格式化将文本转换metaclass->__new__
为元类 - > 新
好的,你在这里混合了很多概念!我将提出你遇到的一些具体问题.
一般来说,理解super,MRO和metclasses变得更加复杂,因为在最后几个版本的Python中,这个棘手的领域发生了很多变化.
Python自己的文档是一个非常好的参考,并且完全是最新的.有一篇IBM developerWorks文章很好地作为一个介绍并采用了更多基于教程的方法,但请注意它已经有五年了,并且花了很多时间讨论元类的旧式方法.
super
是如何访问对象的超类.它比(例如)Java的super
关键字更复杂,主要是因为Python中的多重继承.正如Super Considered Harmful所解释的那样,使用super()
可能会导致您隐式使用超级类链,其顺序由方法解析顺序(MRO)定义.
您可以通过调用mro()
类(而不是实例)轻松地查看类的MRO .请注意,元类不在对象的超类层次结构中.
托马斯元类的"说明这里是极好的:
元类是类的类.就像类定义了类的实例的行为一样,元类定义了类的行为方式.类是元类的实例.
在您给出的示例中,这是正在发生的事情:
呼吁__new__
正在冒泡到MRO的下一件事.在这种情况下,super(MyType,
cls)
将决心type
; 调用type.__new__
让Python完成它的正常实例创建步骤.
此示例使用元类来强制执行单例.他__call__
在元类中重写,因此无论何时创建类实例,他都会拦截它,并且如果已经存在(存储在cls.instance
)中,则可以绕过实例创建.请注意,覆盖__new__
元类中的覆盖将不够好,因为只有在创建类时才会调用它.__new__
然而,压倒
在课堂上会起作用.
这显示了一种动态创建类的方法.这是他将提供的类名称附加到创建的类名称,并将其添加到类层次结构中.
我不确定你正在寻找什么样的代码示例,但这里有一个简短的例子,显示了元类,继承和方法解析:
class MyMeta(type): def __new__(cls, name, bases, dct): print "meta: creating %s %s" % (name, bases) return type.__new__(cls, name, bases, dct) def meta_meth(cls): print "MyMeta.meta_meth" __repr__ = lambda c: c.__name__ class A(object): __metaclass__ = MyMeta def __init__(self): super(A, self).__init__() print "A init" def meth(self): print "A.meth" class B(object): __metaclass__ = MyMeta def __init__(self): super(B, self).__init__() print "B init" def meth(self): print "B.meth" class C(A, B): __metaclass__ = MyMeta def __init__(self): super(C, self).__init__() print "C init" >>> c_obj = C() meta: creating A (,) meta: creating B ( ,) meta: creating C (A, B) B init A init C init >>> c_obj.meth() A.meth >>> C.meta_meth() MyMeta.meta_meth >>> c_obj.meta_meth() Traceback (most recent call last): File "mro.py", line 38, in c_obj.meta_meth() AttributeError: 'C' object has no attribute 'meta_meth'
这是更务实的答案.
这很重要
" 什么是Python中的元类 ".底线type
是所有类的元类.你几乎没有实际用途.
class X(object): pass type(X) == type
" Python中元类的(具体)用例是什么? " 底线.没有.
" Python的超级很漂亮,但你无法使用它 ".有趣的是,但实用价值不大.您永远不需要解析复杂的多继承网络.通过使用明确的策略设计而不是多重继承,可以很容易地防止出现此问题.
这是我在过去7年的Python编程中的经验.
一个类有一个或多个超类,形成一个简单的链从我的班级到object
.
"类"的概念由名为的元类定义type
.我可能想扩展"阶级"的概念,但到目前为止,它从未在实践中出现过.不止一次. type
总是做正确的事.
super
在实践中使用效果非常好.它允许子类遵循它的超类.它恰好出现在这些元类示例中,因为它们扩展了内置的元类,type
.
但是,在所有子类情况下,您将使用super
扩展超类.
元类
元类问题是这样的:
每个对象都引用它的类型定义或"类".
A class
本身也是一个对象.
因此,类型的对象class
具有对其类型或"类"的引用."类"的"类"是元类.
由于"类"不是C++运行时对象,因此在C++中不会发生这种情况.它确实发生在Java,Smalltalk和Python中.
元类定义了类对象的行为.
您与班级交互的90%是要求班级创建新对象.
10%的情况下,您将使用类方法或类变量(C++或Java用语中的"静态").
我找到了一些类级方法的用例.我几乎没有类变量的用例.我从来没有改变对象构建方式的情况.