【问题标题】:can't sort out multiple inheritance in Python3无法在 Python3 中解决多重继承问题
【发布时间】:2018-10-07 02:21:36
【问题描述】:

文档是这样说的:

Python supports a form of multiple inheritance as well. A class 
definition with multiple base classes looks like this:

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>
For most purposes, in the simplest cases, you can think of the search 
for attributes inherited from a parent class as depth-first, left-to-
right, not searching twice in the same class where there is an overlap 
in the hierarchy. Thus, if an attribute is not found in 
DerivedClassName, it is searched for in Base1, then (recursively) in 
the base classes of Base1, and if it was not found there, it was 
searched for in Base2, and so on.

所以,我有这段代码来测试它:

class Class1:
        c1_1 = 1.1

class Class2:
        c2_1 = 2.1


class Blob(Class1, Class2):

    def dump():
        print('c1_1 = ' + str(c1_1))

Blob.dump()

但是,我明白了:

Traceback (most recent call last):
  File "classinherit.py", line 13, in <module>
    Blob.dump()
  File "classinherit.py", line 11, in dump
    print('c_1.1 = ' + str(c1_1))
NameError: name 'c1_1' is not defined

文档似乎说 Python 将首先在 Blob 类的范围内寻找一个(在这种情况下是类范围的)变量,而不是找到它会搜索 Class1 和 Class2 类......但这显然不会发生。

什么给了?

【问题讨论】:

  • 这与多重继承无关,您正在尝试访问未定义的变量。 c1_1。你的意思是self. c1_1
  • 如果您访问属性,Python 只会进行基于类的查找。在dump 中你永远不会尝试这样做

标签: python python-3.x inheritance multiple-inheritance


【解决方案1】:

如果要访问类变量,则必须以某种方式引用该类:

class Class1:
        c1_1 = 1.1

class Class2:
        c2_1 = 2.1

class Blob(Class1, Class2):

    @classmethod
    def dump(cls):
        print('c1_1 = ' + str(cls.c1_1))

Blob.dump()

为了清楚起见,您必须始终引用类,而不仅仅是在继承的情况下。

例如,以下将工作:

class Klass():
    v1 = 1

    def dump():
        print('class var = ' + str(v1))

Klass.dump()

NameError:名称“v1”未定义

同样,您必须引用该类才能使其工作:

class Klass():
    v1 = 1

    @classmethod
    def dump(cls):
        print('class var = ' + str(cls.v1))

Klass.dump()

如果您不想使用@classmethod,您还可以执行以下操作:

class Klass():
    v1 = 1

    def dump():
        print('class var = ' + str(Klass.v1))

Klass.dump()

但请记住,更改类名称 Klass 也需要更改 Klass.v1

【讨论】:

  • 这似乎不是文档所说的。而且,如果是这样的话,为什么还要支持多重继承呢?如果我声明 'class Blob():...' 我可以很容易地说 "print( 'c1_1= ' + str(Class1.c1_1))" 。多重继承有什么好处,为什么文档似乎另有说明?
  • 那么类继承有什么好处呢?我可以做同样的事情来声明'class Blob():',然后打印'str(Class1.c1_1)'。 @classmethod 似乎是一种笨拙的方式,因为更多的混乱而无处可去。而且,它与文档无关。
  • 您的问题是访问类变量,请参阅我的更新答案。
  • 在这里提出类方法是令人困惑的。您可以轻松地使用带有 selfnormal 方法。
  • @juanpa.arrivillaga 但OP没有在他的问题中创建类实例,因此我没有使用实例方法。实际上,如果您只访问类属性而不是实例属性,则创建实例可能会更令人困惑,并且在更改属性时会导致错误的预期。
【解决方案2】:

你正在做的是你试图访问类变量和(或)属性实际上没有告诉它属于哪个类或没有引用该类。 您可以查看@Mike Scotty 的答案,或者只是正确调用您的类变量,然后您就可以清楚地看到 Python 中的 MRO(方法解析顺序)是如何工作的。

class A:
    a = 8

class B:
    b = 9

class C(A, B):
    c = 99

输出

d = C() #After instantiating
print(d.a, d.b, d.c)
>> 8 9 99
# Without instantiating
print(C.a, C.b, C.c)
>> 8 9 99

【讨论】:

  • 您无需创建实例即可访问父类中的属性。您可以根据需要执行print(C.a, c.b, C.c),而无需创建实例d
  • @Blckknght 是的,你是对的,我匆忙错过了。编辑了我的答案,现在可以了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
  • 2019-12-05
相关资源
最近更新 更多