【问题标题】:Python metaclass (abc module) inheritance with nested classes嵌套类的 Python 元类(abc 模块)继承
【发布时间】:2017-12-01 17:18:22
【问题描述】:

我编写了一个包含嵌套元类(带有 abc)的 Python 3 元类,例如:

class A_M(object, metaclass=abc.ABCMeta):
    class A_nested_M(object, metaclass=abc.ABCMeta):
        def ... # some methods

现在,像这样实现

class A(A_M):
     class A_nested(A_nested_M):
        def ...

不起作用。那么,我是否错过了有关元类使用的一些内容,或者这种嵌套元类的实现根本不起作用?

【问题讨论】:

  • 这样继承能行吗class A_nested(A_M.A_nested_M):
  • A_nested_MA_M 中“隐藏”。也许您可以通过class A_nested(A_M.A_nested_M): ... 访问它?
  • 谢谢!不知何故,这适用于普通的嵌套类,但不适用于元类。正如我所说,我是否错过了有关元类概念的某些内容?
  • 你真正想要达到什么目的?这些 sn-ps 提出了一些根本没有实际用途的尝试。

标签: python inheritance metaclass abc


【解决方案1】:

第一件事: 嵌套类声明对 Python 中的任何东西几乎没有用处。除非您将嵌套类层次结构本身用作硬编码的命名空间来保留属性,否则您可能已经在做错事了。

您没有说明您的(实际)问题是什么以及您想要在那里实现什么,也没有说明您为什么使用 ABCmeta 元类。所以很难提出任何真正有用的答案——但我们可以尝试澄清一些事情:

首先:您不是在编写元类,正如您在文本“我已经编写了一个包含嵌套元类的 Python 3 元类...”中所建议的那样 - 您正在创建具有的普通类ABCmeta 作为它的元类。但是您并没有创建新的元类 - 如果您从 typeABCMeta 本身继承 - 您的新类将在后续(普通)类的 metaclass= 参数中使用。事实并非如此。

现在,第二,在最外层 A_M 类的主体内定义的所有内容都将仅作为 A_M 本身的属性“可见”。这就是您的错误的根源 - 当您尝试从 A_nested_M 继承时,您实际上应该写:

class A_M(object, metaclass=abc.ABCMeta):
    class A_nested_M(object, metaclass=abc.ABCMeta):
        def ... # some methods


class A(A_M):
     class A_nested(A_M.A_nested_M):
        def ...

参见 - A_M.A_nested_M 将使 Python 找到 A_nested 的超类:在 A_nested_M 的本地或全局命名空间中没有引用,因为它仅作为 A_M 的属性存在于 @ 的主体之外987654332@声明。

也就是说,这仍然没用。如果你想让A_nestedinstancesA 类的实例引用,你必须在A.__init__() 调用中创建这些实例——此时如果A_nested 是在类体内或模块级别声明:

class A_M(object, metaclass=abc.ABCMeta):
    pass

class A_nested_M(object, metaclass=abc.ABCMeta):
    def ... # some methods

class A_nested(A_nested_M):
   ...

class A(A_M):
    def __init__(self):
         self.nested = A_nested()

现在,这可能有点用处。您还可以声明实际嵌套的类,但它们有用的唯一方法是创建它们的实例。与嵌套函数不同,嵌套类无法访问在“嵌套”类命名空间中声明的属性或变量(但用于通过其限定名称引用它们。即在您的示例中,如果 A 类将包含 @987654339 @classmethod,A_nested 中的一个方法调用这个方法必须调用A.b(),而不是b())

【讨论】:

    【解决方案2】:

    你应该像这样实现你的类:

    class A(A_M):
         class A_nested(A_M.A_nested_M):
            def ...
    

    因为A_nested_M 是一个内部类,你应该像访问任何类属性一样访问它,即A_M.A_nested_M。见this link

    【讨论】:

    • 这给我一个AttributeError: module 'A_M' has no attribute 'A_nested_M'
    • @norb 我不确定为什么它不适用于元类。这可能会让我失去一些反对意见,但我会暂时留下这个答案,也许有人知道为什么这不适用于元类的解释。
    猜你喜欢
    • 2019-12-12
    • 1970-01-01
    • 2011-06-19
    • 2019-01-04
    • 2020-12-16
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多