繁体   English   中英

从具有自引用的实例内部访问类变量时会发生什么?

[英]What happens when you access a class-variable from inside an instance with a self-reference?

我的一位同事写了一个类似的代码:

class A(object):
    foo = "bar"


class B(A):
    def baz(self):
        print self.foo

并且违背我的个人信仰,这很有效! 我来自一个主要的Java背景,这伤害了我的眼睛......就个人而言,我会这样写:

class A(object):
    foo = "bar"


class B(A):
    def baz(self):
        print A.foo  # or dynamically determine the superclass.

我理解,在Python中,变量名通常与“标签”进行比较。 但这仍然在我的嘴里留下酸味。 编写这样的代码有什么意义? 这真是个坏主意吗? 可能会出错吗?

我可以想象的唯一“坏”的事情是,在类层次结构的更深处,一个实例变量可能会影响类变量......所以,你可以说它是......好吗?

你基本上可以做到这两点。

如果您的类只有一个父级,则可以直接使用名称引用该变量。

class A(object):
    foo = "bar"


class B(A):
    def baz(self):
        print self.foo  

如果你使用multi,你所做的就有意义了

class A(object):
    foo = "bar"

class A2(object):
    foo = "bar 2"

class B(A, A2):
    def baz(self):
        #print foo # would throw NameError: global name 'foo' is not defined
        #print self.foo # prints "bar"
        print A.foo # prints "bar"
        print A2.foo # prints "bar 2"  

编辑:如果我们忽略Java没有多重继承的事实,我认为它的行为方式类似。

public class A {
    String foo = "bar";
}

public class B extends A {

    public void baz() {
        System.out.println(this.foo);
    }

}
public static void main(String[] args) {
    B b = new B();
    b.baz(); // prints "bar"
}

唯一的区别是在Java中可以使用this.foosuper.foo以及foo访问它,而在Python中你可以使用self.foo<superclass>.foo ,但不是foo

嗯,首先,Python不是Java。 有些事情只是不同。

根据Python的语义,类中的名称解析必须以这种方式工作。 否则,无法从实例调用方法,因为方法也是类属性。

你是对的,其他地方的实例变量可能会影响类变量。 但在我看来,这是一个功能,而不是一个错误。 如果你真的想确定你总是访问类变量,你可以做self.__class__.foo ,但我认为没有任何需要。

这是一个复杂的问题。 您的两个代码示例的行为略有不同。

在您的同事的实现中, B的实例可能具有其自己的foo值。 上面的代码中没有任何内容可以建立一个,但您可以轻松地这样做:

example_B = B()
example_B.foo = 'foobar'

然后example_B.baz()将返回'foobar'

如果使用您的版本实现, example_B.baz()将不检查实例的值。 相反,它会返回'bar' ,无论在example_B设置了什么。

在实践中,您通常应该在设计类时告诉您名称是应该引用特定于实例的信息还是引用特定于类的信息。 只应在类级别声明特定于类的信息。

有些人使用类级声明作为快捷方式来确保某个类的所有实例都有值,即使它们没有设置它,但我发现这通常会导致混淆,只要它们声明一个可变变量为一个“默认值”:

class BadExample(object):
    accidentally_shared_value = []

相反,您通常应该在__init__声明特定于实例的值:

class BetterExample(object):
    def __init__(self):
        self.unshared_value = []

意外地共享可变值是在误解什么是类属性与什么是实例属性时可能出错的主要情况。

我可以想象的唯一“坏”的事情是,在类层次结构的深层,实例变量可能会影响类变量

它实际上可能没有任何深层次结构。

class TestClass(object):
    var = 'foo'
    def __init__(self):
        self.var = 'bar'

x = TestClass()
print x.var
>>> 'bar'
del x.var
print x.var
>>>> 'foo'

但它在Python中没问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM