2016-10-04 51 views
1

我只是想知道Python究竟是如何在幕後處理這個問題的。因此,採取(由Brett斯拉特金從有效的Python)這樣的代碼片段:正在運行super().__ init __(值)其中value是@property

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檢查?

+1

沒有; 'self'仍然是'Resistor .__ init__'中'VoltageResistor'的一個實例;範圍與它無關。 – chepner

回答

2

使用對象的屬性時,範圍不起作用。考慮以下幾點:

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,創建並傳遞給__init__selfVoltageResistor一個實例。當您撥打super.__init__(self)時,該VoltageResistor實例將傳遞至Resistor.__init__。當它確實self.ohms = ohms,python看到self.ohms解析爲一個屬性,你會得到錯誤。 tl; dr; selfVoltageResistor的一個實例,當使用屬性時,訪問屬性的對象是重要的,而不是當前範圍)。

+0

這很清楚,謝謝! – flybonzai

1

爲了補充上述出色答卷,只是添加在父類的構造以下行來獲得正在發生的事情的一個更好的主意:

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

它將打印VoltageResistor再扔一個ValueError。所述Python docs確認:

如果c是Ç一個實例,c.x將調用吸氣劑,c.x =值將調用設定器和德爾c.x的刪除器。

相關問題