Python元类(abc模块)继承与嵌套类

时间:2017-06-28 11:12:05

标签: python inheritance metaclass abc

我编写了一个包含嵌套元类(带有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 ...

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

2 个答案:

答案 0 :(得分:3)

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

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

首先:你没有像你在文本中所建议的那样写一个元类;我已经编写了一个包含嵌套元类的Python 3元类......" - 您正在创建 将ABCmeta作为其元类的普通类。但是你没有创建新的元类 - 如果你继承自type或者ABCMeta本身 - 那么你的新类将被用在后续(普通)类的metaclass=参数中。事实并非如此。

现在,第二,在最外面的A_M类的主体内定义的所有内容将只有#34;可见"作为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的本地或全局命名空间中没有引用,因为它仅作为{{1}的属性存在在A_M语句的正文之外。

那就是说,这仍然没用。如果您希望class A_M...类的实例引用{em>实例 A_nested,则必须在A调用内创建这些实例 - 此时它不会如果在类体内或模块级别声明A.__init__(),则会产生差异:

A_nested

现在,这可能有些用处。您也可以声明实际嵌套的类,但它们唯一有用的方法是创建它们的实例。与嵌套函数不同,嵌套类无法访问在"嵌套"上声明的属性或变量。 class namespace(但是用于通过它们的限定名称引用它们。即在您的示例中,如果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类方法,b内部将调用此方法的方法将必须致电A_nested,而不是A.b()

答案 1 :(得分:0)

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

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

因为A_nested_M是一个内部类,所以您应该像访问任何类属性一样访问它,即A_M.A_nested_M。请参阅this link