代码之家  ›  专栏  ›  技术社区  ›  JV.

“元类”、“新的”、“cls”和“super”-具体的机制是什么?

  •  27
  • JV.  · 技术社区  · 17 年前

    我读过这样的文章:

    1. What is a metaclass in Python?
    2. What are your (concrete) use-cases for metaclasses in Python?
    3. Python's Super is nifty, but you can't use it

    但不知怎么的,我搞糊涂了。许多困惑如:

    什么时候,为什么我要做如下的事情?

    # 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中的类注册和注销,它到底是如何工作的?(我认为这与 singleton . 我可能错了,因为我是C背景的。我的编码风格仍然混合了函数和OO)。

    类实例化(子类、元类、super、类型)和方法调用的流程是什么?(

    metaclass->__new__, metaclass->__init__, super->__new__, subclass->__init__ inherited from metaclass
    

    )使用注释良好的工作代码(尽管第一个链接非常接近,但它不讨论cls关键字、super(..)和注册表)。最好是具有多重继承的示例。

    P.S.:我把最后一部分作为代码,因为堆栈溢出格式正在转换文本 metaclass->__new__ 到元类-> 新的

    2 回复  |  直到 17 年前
        1
  •  18
  •   Community Mohan Dere    9 年前

    好吧,你已经在这里的混合中加入了很多概念!我将提出一些具体的问题。

    一般来说,理解super、mro和metclasses会变得更加复杂,因为在过去几个版本的python中,这个棘手的领域发生了很多变化。

    Python's own documentation 是一个很好的参考资料,完全是最新的。有一个 IBM developerWorks article 这是一个很好的介绍,并采取了一个更基于教程的方法,但请注意,它是五年前的,并花了很多时间讨论元类的老式方法。

    super 是如何访问对象的超级类的。它比(例如)Java更复杂。 超级的 关键字,主要是因为python中存在多个继承。AS Super Considered Harmful 解释,使用 super() 会导致隐式使用一系列超类,其顺序由 Method Resolution Order (MRO)。

    通过调用 mro() 在类上(而不是在实例上)。注意,元类不在对象的超级类层次结构中。

    Thomas '元类的描述 here 优秀:

    元类是类的类。 类定义了实例 类的行为,一个元类 定义类的行为方式。一个班 是元类的实例。

    在您给出的示例中,发生了以下情况:

    1. 呼唤 __new__ 正在被 冒泡到下一件事 MRO。在这种情况下, super(MyType, cls) 会下决心 type ; 打电话 type.__new__ 让蟒蛇 完成这是正常情况 创建步骤。

    2. 这个例子使用的是元类 执行一个单例。他是 压倒一切 __call__ 在 元类,这样每当一个类 实例被创建,他截取 可以绕过实例 如果已经存在,则创建 (存储在 cls.instance )注释 压倒一切 新西兰 在 元类还不够好, 因为只有在 创建 . 压倒一切 新西兰 在课堂上会有用的, 然而。

    3. 这显示了一种动态 创建一个类。这是他的 附加提供的类的名称 创建的类名,以及 将其添加到类层次结构 也是。

    我不确定您要找的是哪种类型的代码示例,但下面是一个简短的示例,其中显示了元类、继承和方法解析:

    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'
    
        2
  •  10
  •   Community Mohan Dere    9 年前

    这是更务实的答案。

    很少有关系

    1. What is a metaclass in Python “。底线, type 是所有类的元类。你几乎没有实际的用处。

      class X(object):
          pass
      type(X) == type
      
    2. What are your (concrete) use cases for metaclasses in Python? “。底线。一个也没有。

    3. Python's Super is nifty, but you can't use it “。有趣的注释,但实用价值不大。您永远不需要解决复杂的多继承网络。很容易通过使用一个明确的 策略 设计而不是多重继承。

    下面是我在过去7年的Python编程中的经验。

    1. 一个类有一个或多个超类,从我的类到 object .

    2. “类”的概念由名为 类型 . 我可能想扩展“类”的概念,但到目前为止,它还没有在实践中出现。一次也没有。 类型 总是做正确的事。

    3. 使用 super 在实践中效果很好。它允许子类遵从它的超类。它恰巧出现在这些元类示例中,因为它们扩展了内置元类, 类型 .

      但是,在所有子类情况下,您将使用 超级的 扩展超类。

    元类

    元类的问题是:

    • 每个对象都有一个对其类型定义的引用,或“类”。

    • class 本身也是一个对象。

    • 因此,对象类型为 具有对其类型或“类”的引用。“class”的“class”是一个元类。

    因为“类”不是C++运行时对象,这在C++中是不存在的。它确实发生在爪哇,SimultTalk和Python。

    元类定义类对象的行为。

    • 90%的与类的交互是要求类创建一个新对象。

    • 10%的时间,你将使用类方法或类变量(C++中的静态)或Java语言。

    我发现了一些类级方法的用例。我几乎没有类变量的用例。我从未有过改变物体构造工作方式的情况。