Lookup of magic methods on old-style Python classes
<p>I know old-style Python classes aren't recommended anymore, especially since Python 3 removes them.  However, I'd still like to understand what is happening here:</p>

<pre><code>class MyClass:
  pass

my_instance = MyClass()
str(my_instance)
</code></pre>

<p>This snippet prints the following:</p>

<p>'&lt;<strong>main</strong>.MyClass instance at 0x108ec4290>'</p>

<p>So, I don't have any explicit inheritance and I didn't overload the <strong>str</strong> method.  However, this doesn't raise an exception for the supposedly missing method.  Why?</p>

<p>I know that old-style classes have the concept of an 'instance' and a 'type' and that new-style classes aim to unify these concepts.  So is Python finding and calling the <strong>str</strong> method on the 'instance' type that my instance is implicitly connected to?</p>

<p>Here are some clues:</p>

<p>dir(my_instance) - Returns:</p>

<pre><code>['__doc__', '__module__']
</code></pre>

<p>type(my_instance) - Returns:</p>

<pre><code>&lt;type 'instance'&gt;
</code></pre>

<p>dir(type(my_instance)) - Returns:</p>

<pre><code>['__abs__', '__add__', '__and__', '__call__', '__class__', '__cmp__', '__coerce__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__', '__idiv__', '__ifloordiv__', '__ilshift__', '__imod__', '__imul__', '__index__', '__init__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__', '__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', '__len__', '__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'next']
</code></pre>

<p>Can anyone explain exactly the relationship between classes and types in old-style classes and what is happening here?</p>
