Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between calling a method and accessing an attribute

Tags:

python

oop

I'm very new to Python, and I'm using Python 3.3.1.

class Parent: # define parent class 
    parentAttr = 100
    age = 55

    def __init__(self): 
        print ("Calling parent constructor") 

    def setAttr(self, attr): 
        Parent.parentAttr = attr 

class Child(Parent):
    def childMethod(self):
        print ('Calling child method')

Now I'll create

c=child
c.[here every thing will appear methods and attr (age,setAttr)]

How can I distinguish between methods and atrributes? I mean, when do I use c.SetAtrr(Argument), and c.SetAtrr=value?

like image 295
D007a Avatar asked Jun 08 '13 14:06

D007a


1 Answers

Methods are attributes too. They just happen to be callable objects.

You can detect if an object is callable by using the callable() function:

>>> def foo(): pass
...
>>> callable(foo)
True
>>> callable(1)
False

When you call a method, you look up the attribute (a getattr() operation) and then call the result:

c.setAttr(newvalue)

is two steps; finding the attribute (which in this case looks up the attribute on the class, and treats it as a descriptor), then calls the resulting object, a method.

When you assign to an attribute, you rebind that name to a new value:

c.setAttr = 'something else'

would be a setattr() operation.

If you wanted to intercept getting and setting attributes on instances of your class, you could provide the attribute access hooks, __getattr__, __setattr__ and __delattr__.

If you wanted to add a method to an instance, you would have to treat the function as a descriptor object, which produces a method object:

>>> class Foo: pass
... 
>>> foo = Foo()  # instance
>>> def bar(self): pass
... 
>>> bar
<function bar at 0x10b85a320>
>>> bar.__get__(foo, Foo)
<bound method Foo.bar of <__main__.Foo instance at 0x10b85b830>>

The return value of function.__get__(), when given an instance and a class, is a bound method. Calling that method will call the underlying function with self bound to the instance.

And speaking of descriptors, the property() function returns a descriptor too, making it possible to have functions that behave like attributes; they can intercept the getattr(), setattr() and delattr() operations for just that attribute and turn it into a function call:

>>> class Foo:
...     @property
...     def bar(self):
...         return "Hello World!"
... 
>>> foo = Foo()
>>> foo.bar
"Hello World!"

Accessing .bar invoked the bar property get hook, which then calls the original bar method.

In almost all situations, you are not going to need the callable() function; you document your API, and provide methods and attributes and the user of your API will figure it out without testing each and every attribute to see if it is callable. With properties, you have the flexibility of providing attributes that are really callables in any case.

like image 91
Martijn Pieters Avatar answered Oct 26 '22 06:10

Martijn Pieters