当前位置:  开发笔记 > 编程语言 > 正文

"MetaClass","__ new__","cls"和"super" - 究竟是什么机制?

如何解决《"MetaClass","__new__","cls"和"super"-究竟是什么机制?》经验,为你挑选了2个好方法。

我看过这样的帖子:

    什么是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__ 为元类 - >



1> James Brady..:

好的,你在这里混合了很多概念!我将提出你遇到的一些具体问题.

一般来说,理解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'



2> S.Lott..:

这是更务实的答案.

这很重要

    " 什么是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用语中的"静态").

我找到了一些类级方法的用例.我几乎没有类变量的用例.我从来没有改变对象构建方式的情况.


@ S.Lott:我认为对MRO和super的正确理解是一个非常有价值的工具.在没有意识到多重继承*可以让你离开的肮脏之处,我们不知道为什么需要线性继承链,简单的混合等等.知道错误的选项仍然有用!
他说的是我们都是羊,需要排队.别担心,你不需要知道.这对你来说太难了._you_知道_his_工作的安全性越低.**拧那个.**尽可能多地学习你使用的语言,不要让这些(python)灌输者告诉你你需要知道什么.和平.
关于多重继承,我不同意.一个简单的立场链接到对象是好的设计IMO,但混合很好,我鼓励他们在适当的时候使用.一旦你使用混合,你真的需要了解MRO,以确保你不会在脚下射击.
@hiwaylon:"所有的羊都需要排队"?真?我以为我说它很少需要."尽可能多地学习你使用的语言".难道我没有建议专门看看Django的一个好例子吗?为什么所有的愤怒?
推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有