【问题标题】:A Python class inherited from a temporary class从临时类继承的 Python 类
【发布时间】:2018-11-20 10:16:50
【问题描述】:

当我试图找出以下 codes 时,我被卡住了:

def with_metaclass(meta, base=object):
    print("[2]")
    return meta("NewBase", (base,), {})

class BaseForm(object):
    def __init__(self, fields, prefix=''):
       print(self.__class__)

    def say(self):
        print("BaseForm")


class FormMeta(type):
    def __init__(cls, name, bases, attrs):
        print("[3]: {!r}, {!r}, {!r}, {!r}, {!r}".format(cls, name, type(cls), bases, attrs))
        type.__init__(cls, name, bases, attrs)

    def __call__(cls, *args, **kwargs):
        print("[4]: {!r}, {!r}".format(cls, type(cls)))
        return type.__call__(cls, *args, **kwargs)

print("[1]")
class Form(with_metaclass(FormMeta, BaseForm)):
    print("[5]")
    def __init__(self):
        NewBase.__init__(self)
        print("[6]: {!r}, {!r}".format(self, type(self)))


# confused position
print(Form.__bases__)

# Form is based on NewBase, however, there is no NewBase
print(dir())

这里是代码输出:

[1]
[2]
[3]: <class '__main__.NewBase'>, 'NewBase', <class '__main__.FormMeta'>, (<class '__main__.BaseForm'>,), {}
[5]
[3]: <class '__main__.Form'>, 'Form', <class '__main__.FormMeta'>, (<class '__main__.NewBase'>,), {'__module__': '__main__', '__qualname__': 'Form', '__init__': <function Form.__init__ at 0x7f6ad4d76f28>}
(<class '__main__.NewBase'>,)
['BaseForm', 'Form', 'FormMeta', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'with_metaclass']

就像我注释掉的一样,Form 是基于NewBase,但是,主模块中没有NewBase 类。一个类的基类不可访问,是错误吗?但有趣的是,Form 仍然可以调用该方法,该方法来自其父级的父级。

【问题讨论】:

    标签: python inheritance subclass


    【解决方案1】:

    为了回答,我们一开始不需要 FormMeta 类。 想象一下Form的定义如下:

    class Form(with_metaclass(meta=type, base=BaseForm)):
        # ...
    

    with_metaclass 调用只返回meta("NewBase", (base,), {}),在本例中为type("NewBase", (base,), {}),它创建了一个名为NewBase 的新类,它派生自base(在本例中为BaseForm),没有额外的方法。 你可以在type documentation阅读它。

    在这种情况下,FormMeta 元类什么也不做。它继承type(这就是为什么它是一个元类),然后只是将它接收到的数据传递给type,加上一些打印语句。所以基本上和上面一样。 您可以阅读有关元类的更多信息here

    【讨论】:

    • 可能我没说清楚,我的问题是Form类基于NewBase类,但是NewBase类不在模块命名空间中,即dir()。因此,Form 类的父级无法访问。但是Form的实例可以访问BaseForm的方法(NewBase的父类)。
    • 如果你想在全局命名空间中使用它,只需使用NewForm = with_metaclass(FormMeta),然后使用class Form(NewForm)。或者只使用super():__init__ 而不是NewForm.__init__。如果这不是你的意思,我不明白你的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 2018-03-10
    • 2018-05-27
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多