正在运行super()。\uuu init\uuu(value),其中value是@property

2024-07-05 10:16:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我只是想弄清楚Python究竟是如何在幕后处理这个问题的。因此,请看以下代码片段(来自Brett Slatkin的Effective Python):

class Resistor(object):
    def __init__(self, ohms):
        self.ohms = ohms
        self.voltage = 0
        self.current = 0


class VoltageResistor(Resistor):
    def __init__(self, ohms):
        super().__init__(ohms)
        self._voltage = 0

    @property
    def ohms(self):
        return self._ohms

    @ohms.setter
    def ohms(self, ohms):
        if ohms <= 0:
            raise ValueError('{o} ohms must be > 0'.format(o=ohms))
        self._ohms = ohms

    @property
    def voltage(self):
        return self._voltage

    @voltage.setter
    def voltage(self, voltage):
        self._voltage = voltage
        self.current = self._voltage / self.ohms

VoltageResistor(-1) # fails

运行super()调用调用属性检查,这样就不能用零值或负值进行实例化。让我困惑的是,我认为既然__init__(ohms)调用是在超类上运行的,那么它不应该在另一个作用域(超类的作用域)中,从而免于调用@property检查吗?你知道吗


Tags: 代码selfreturninitdefpropertycurrent作用域
2条回答

为了补充上述出色的答案,只需在父构造函数中添加以下行,就可以更好地了解发生了什么:

class Resistor(object):
    def __init__(self, ohms):
        print (type(self).__name__)
        self.ohms = ohms

它将打印VoltageResistor,然后抛出一个ValueErrorPython docs确认这一点:

If c is an instance of C, c.x will invoke the getter, c.x = value will invoke the setter and del c.x the deleter.

在处理对象的属性时,作用域不起作用。考虑以下几点:

class A(object):
    def __init__(self):
        self.a = 1

def foo():
    a = A()
    a.a = 2
    return a

def bar(a):
    print(a.a)

bar(foo())

此示例代码将打印2。注意,在bar范围内,没有办法访问foo范围,甚至A.__init__。类实例携带着它的所有属性(以及对它的类的引用,该类引用引用了它的超类,等等)。你知道吗

在您的代码中,当您调用VoltageResistor时,VoltageResistor的实例被创建并作为self传递给__init__。调用super.__init__(self)时,VoltageResistor实例被传递给Resistor.__init__。当它执行self.ohms = ohms操作时,python会看到self.ohms解析为一个属性,您就会得到错误。太长了,读不下去了,这里是^ {CD7}}是^ {< CD4}}和<强>的实例,当使用属性时,访问属性的对象是重要的,而不是当前的范围< /强>。你知道吗

相关问题 更多 >