Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get a reference to a Python property?

If I have this:

class foo(object):     @property     def bar(self):         return 0  f = foo() 

How do I get a reference to f.bar without actually invoking the method, if this is even possible?

Edited to add: What I want to do is write a function that iterates over the members of f and does something with them (what is not important). Properties are tripping me up because merely naming them in getattr() invokes their __get__() method.

like image 928
kindall Avatar asked Sep 09 '10 23:09

kindall


People also ask

How do you call a property in Python?

You can create a property by calling property() with an appropriate set of arguments and assigning its return value to a class attribute. All the arguments to property() are optional. However, you typically provide at least a setter function.

How do you access properties in Python?

getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute. If the attribute does not exist, then it would be created.

Are Python objects passed by reference?

Python passes arguments neither by reference nor by value, but by assignment.

Are Python properties inherited?

Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.


1 Answers

get_dict_attr (below) looks up attr in a given object's __dict__, and returns the associated value if its there. If attr is not a key in that __dict__, the object's MRO's __dict__s are searched. If the key is not found, an AttributeError is raised.

def get_dict_attr(obj, attr):     for obj in [obj] + obj.__class__.mro():         if attr in obj.__dict__:             return obj.__dict__[attr]     raise AttributeError 

For example,

class Foo(object):     x=1     def bar(self):         pass     @property     def baz(self):         return 0  foo=Foo() print(get_dict_attr(foo,'x')) # 1 print(get_dict_attr(foo,'bar')) # <unbound method Foo.bar> print(get_dict_attr(foo,'baz')) # <property object at 0xb77c0dc4> print(get_dict_attr(foo,'y')) # AttributeError 

Note that this is very different than the normal rules of attribute lookup. For one thing, data-descriptors in obj.__class__.__dict__ (descriptors with both __get__ and __set__ methods) normally have precedence over values in obj.__dict__. In get_dict_attr, obj.__dict__ has precedence.

get_dict_attr does not try calling __getattr__.

Finally, get_dict_attr will only work with objects obj which are instances of new-style classes.

Nevertheless, I hope it is of some help.


class Foo(object):     @property     def bar(self):         return 0  f = Foo() 

This references the property bar:

print(Foo.bar) # <property object at 0xb76d1d9c> 

You see bar is a key in Foo.__dict__:

print(Foo.__dict__['bar']) # <property object at 0xb775dbbc> 

All properties are descriptors, which implies it has a __get__ method:

print(Foo.bar.__get__) # <method-wrapper '__get__' of property object at 0xb76d7d74> 

You can call the method by passing the object f, and the class of f as arguments:

print(Foo.bar.__get__(f,Foo)) # 0 

I am fond of the following diagram. Vertical lines show the relationship between an object and the object's class.

When you have this situation:

   Foo                                B    | Foo.__dict__={'bar':b}           | B.__dict__={'__get__':...}    |                      \           |          f                       `--------> b 

f.bar causes b.__get__(f,Foo) to be called.

This is explained in detail here.

like image 166
unutbu Avatar answered Sep 26 '22 20:09

unutbu