Running super().__init__(value) where value is an @property
<p>I'm just trying to grok how exactly Python handles this behind the scenes.  So take this code snippet (from Effective Python by Brett Slatkin):</p>

<pre><code>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 &lt;= 0:
            raise ValueError('{o} ohms must be &gt; 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
</code></pre>

<p>Running the <code>super()</code> call invokes the property check so that you can't instantiate with a zero or negative value.  What is confusing me to me is that I would think that since the the <code>__init__(ohms)</code> call is being ran on the superclass, shouldn't it be in a different scope (the scope of the superclass) and thus exempt from invoking the <code>@property</code> check?  </p>

<p>Scope doesn't come into play when working with object's attributes.  Consider the following:</p>

<pre><code>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())
</code></pre>

<p>This example code will print 2.  Note that within the scope of <code>bar</code>, there <em>is</em> no way to gain access to the scope of <code>foo</code> or even <code>A.__init__</code>.  The class <em>instance</em> is carrying along all of it's attributes/properties with it (and a reference to it's class which has a reference to <em>it's</em> superclass, etc).</p>

<p>In your code, when you call <code>VoltageResistor</code>, an instance of <code>VoltageResistor</code> is created and passed to <code>__init__</code> as <code>self</code>.  When you call <code>super.__init__(self)</code>, that <code>VoltageResistor</code> instance is passed along to <code>Resistor.__init__</code>.  When it does <code>self.ohms = ohms</code>, python sees that <code>self.ohms</code> resolves to a property and you get the error.  The tl;dr; here is that <code>self</code> is an instance of <code>VoltageResistor</code> and <strong>when working with attributes, the object on which the attributes are accessed is what is important, not the current scope</strong>).</p>

python