JV.*_*JV. 28 python types metaclass super
我看过这样的帖子:
但不知怎的,我感到困惑.许多混淆如:
何时以及为什么我必须做以下事情?
# Refer link1
return super(MyType, cls).__new__(cls, name, bases, newattrs)
Run Code Online (Sandbox Code Playgroud)
要么
# Refer link2
return super(MetaSingleton, cls).__call__(*args, **kw)
Run Code Online (Sandbox Code Playgroud)
要么
# Refer link2
return type(self.__name__ + other.__name__, (self, other), {})
Run Code Online (Sandbox Code Playgroud)
超级工作怎么样?
什么是link1中的类注册表和unregistry以及它究竟是如何工作的?(我认为它与单身人士有关.我可能是错的,来自C背景.我的编码风格仍然是功能和OO的混合).
类实例化(子类,元类,超类型)和方法调用的流程是什么(
metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass
Run Code Online (Sandbox Code Playgroud)
)具有良好评论的工作代码(虽然第一个链接非常接近,但它没有谈论cls关键字和超级(..)和注册表).优选地,具有多重继承的示例.
PS:我把最后一部分作为代码,因为Stack Overflow格式化将文本转换metaclass->__new__
为元类 - > 新
Jam*_*ady 21
好的,你在这里混合了很多概念!我将提出你遇到的一些具体问题.
一般来说,理解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 (<type 'object'>,)
meta: creating B (<type 'object'>,)
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 <module>
c_obj.meta_meth()
AttributeError: 'C' object has no attribute 'meta_meth'
Run Code Online (Sandbox Code Playgroud)
这是更务实的答案.
这很重要
" 什么是Python中的元类 ".底线type
是所有类的元类.你几乎没有实际用途.
class X(object):
pass
type(X) == type
Run Code Online (Sandbox Code Playgroud)" Python中元类的(具体)用例是什么? " 底线.没有.
" Python的超级很漂亮,但你无法使用它 ".有趣的是,但实用价值不大.您永远不需要解析复杂的多继承网络.通过使用明确的策略设计而不是多重继承,可以很容易地防止出现此问题.
这是我在过去7年的Python编程中的经验.
一个类有一个或多个超类,形成一个简单的链从我的班级到object
.
"类"的概念由名为的元类定义type
.我可能想扩展"阶级"的概念,但到目前为止,它从未在实践中出现过.不止一次. type
总是做正确的事.
super
在实践中使用效果非常好.它允许子类遵循它的超类.它恰好出现在这些元类示例中,因为它们扩展了内置的元类,type
.
但是,在所有子类情况下,您将使用super
扩展超类.
元类
元类问题是这样的:
每个对象都引用它的类型定义或"类".
A class
本身也是一个对象.
因此,类型的对象class
具有对其类型或"类"的引用."类"的"类"是元类.
由于"类"不是C++运行时对象,因此在C++中不会发生这种情况.它确实发生在Java,Smalltalk和Python中.
元类定义了类对象的行为.
您与班级交互的90%是要求班级创建新对象.
10%的情况下,您将使用类方法或类变量(C++或Java用语中的"静态").
我找到了一些类级方法的用例.我几乎没有类变量的用例.我从来没有改变对象构建方式的情况.