if the type of instances is simply 'instance', how does Python know these are instances of the foo class?

72 views Asked by At

Is putting objects in a list (in python) just like putting class object in ArrayList<object> ?? I tried this code

class foo():
    def __init__(self):
        self.name = "frank"
        self.id = 007


obj1 = foo()
obj2 = foo()

element_list = []
element_list.append(obj1)
element_list.append(obj2)

for element in element_list:
    print(type(element))
    print(element.name)

The object type turned out to be <type 'instance'>. But then the object correctly printed the variable assigned.

How does python identify the type of these instances? Even if it is getting an instance object, how is it able to map the class?

2

There are 2 answers

4
Martijn Pieters On BEST ANSWER

type() does not work correctly for instances of old-style classes (Python 2 classes that do not inherit from object). Python looks at the .__class__ attribute instead:

>>> class Foo:
...     def __init__(self):
...         self.name = 'frank'
...         self.id = 7
... 
>>> f = Foo()
>>> type(f)
<type 'instance'>
>>> f.__class__
<class __main__.Foo at 0x107b321f0>

For instances of new-style classes (so those classes that do inherit from object), type() simply returns the __class__ attribute directly.

Not that it matters here; all you are really doing is looking at attributes, stored directly on the instance itself. Those are stored in the __dict__ attribute of each instance:

>>> f.__dict__
{'name': 'frank', 'id': 7}

Method lookups (as well as any other attribute that is defined on the class or its bases), do require that Python looks at the class:

>>> f.__init__
<bound method Foo.__init__ of <__main__.Foo instance at 0x107b1d710>>
>>> f
<__main__.Foo instance at 0x107b1d710>

For that the __class__ attribute is used here.

2
Larry Lustig On

Python performs method calls without looking at the type of the object on which you're calling the method. It simply checks to see whether the object (not the class) contains an attribute which matches the method name, and then checks to see whether that attribute is callable.

In Python, you can take an object of class X() where X() does not contains a method of blah() and add to that object instance a method named blah() and call that method -- even though the type knows nothing of such a method.

To see this in action:

class C(object): pass

obj1 = C()
obj2 = C()

obj1.double = lambda x: x*2

Now, you can call obj1.double():

obj1.double("hello")
'hellohello'

but not obj2.double():

obj2.double("hello")
AttributeError: 'C' object has no attribute 'double'