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:
class MyClass:
pass
my_instance = MyClass()
str(my_instance)
This snippet prints the following:
‘<main.MyClass instance at 0x108ec4290>’
So, I don’t have any explicit inheritance and I didn’t overload the str method. However, this doesn’t raise an exception for the supposedly missing method. Why?
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 str method on the ‘instance’ type that my instance is implicitly connected to?
Here are some clues:
dir(my_instance) – Returns:
['__doc__', '__module__']
type(my_instance) – Returns:
<type 'instance'>
dir(type(my_instance)) – Returns:
['__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']
Can anyone explain exactly the relationship between classes and types in old-style classes and what is happening here?
I am sure other people can give you more concrete reasons that this, but there is a quote from a similar discussion located here: old-style class
That part about the “magic” I believe is just that… black-box magic. Obviously the MRO (method resolution order) of old style classes was much more magical, in that it probably had to check both explicit definitions on the
instanceobject, as well as on thetype. Either that, or part of the mechanics of an old style class is to always provide a default__str__method when one cannot be located.It would be less magical now with new-style classes, because due to the inheritance, the methods are really right there on the instance.
Here is another site with some good quotes and examples: Principle of Biggest Surprise
New-style:
Old-Style: