How to determine which Python class provides attributes when inheriting
<p>What's the easiest way to determine which Python class defines an attribute when inheriting? For example, say I have:</p>

<pre><code>class A(object):

    defined_in_A = 123

class B(A):
    pass

a = A()
b = B()
</code></pre>

<p>and I wanted this code to pass:</p>

<pre><code>assert hasattr(a, 'defined_in_A')
assert hasattr(A, 'defined_in_A')
assert hasattr(b, 'defined_in_A')
assert hasattr(B, 'defined_in_A')

assert defines_attribute(A, 'defined_in_A')
assert not defines_attribute(B, 'defined_in_A')
</code></pre>

<p>How would I implement the fictional <code>defines_attribute</code> function? My first thought would be to walk through the entire inheritance chain, and use <code>hasattr</code> to check for the attribute's existence, with the deepest match assumed to be the definer. Is there a simpler way?</p>

<p>(Almost) Every python object is defined with it's own instance variables (instance variables of a class object we usually call class variables) to get this as a dictionary you can use the <a href="https://docs.python.org/3/library/functions.html?highlight=built#vars" rel="nofollow"><code>vars</code></a> function and check for membership in it:</p>

<pre><code>&gt;&gt;&gt; "defined_in_A" in vars(A)
True
&gt;&gt;&gt; "defined_in_A" in vars(B)
False
&gt;&gt;&gt; "defined_in_A" in vars(a) or "defined_in_A" in vars(b)
False
</code></pre>

<p>the issue with this is that it does not work when a class uses <code>__slots__</code> or builtin objects since it changes how the instance variables are stored:</p>

<pre><code>class A(object):
    __slots__ = ("x","y")
    defined_in_A = 123

&gt;&gt;&gt; A.x
&lt;member 'x' of 'A' objects&gt;
&gt;&gt;&gt; "x" in vars(a)
Traceback (most recent call last):
  File "&lt;pyshell#5&gt;", line 1, in &lt;module&gt;
    "x" in vars(a)
TypeError: vars() argument must have __dict__ attribute
&gt;&gt;&gt; vars(1) #or floats or strings will raise the same error
Traceback (most recent call last):
   ...
TypeError: vars() argument must have __dict__ attribute
</code></pre>

<p>I'm not sure there is a simple workaround for this case.</p>

python inheritance