Difference between calling a method and accessing an attribute
Asked Answered
D

1

7

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?

Dryly answered 8/6, 2013 at 14:23 Comment(1)
The class documentation should tell you which attributes are methods meant to be called and which are attributes whose value you can safely change.Holcombe
A
14

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.

Acrophobia answered 8/6, 2013 at 14:25 Comment(4)
So .. Can i use c.SetAtrr=value and c.SetAtrr(Value) ,, and they will be the same ??Dryly
@disasterromio: No, one is setting the attribute, the other is calling the function.Acrophobia
Thank u for ur time thou the best practice is to check if the object is callable or not first ?Dryly
@D007a: but what is your goal here? Generally, that is up to documentation, isn't it? The user of the class learns once what your API is, you usually do not need to detect if something is callable or not.Acrophobia

© 2022 - 2024 — McMap. All rights reserved.