Class: @property -> .__dict__

U

Ulrich

Good morning,

I wonder if someone could please help me out with the @property
function as illustrated in the following example.

class te():
def __init__(self):
self.a = 23
@property
def b(self):
return 2 * self.a


t = te()
In [4]: t.a
Out[4]: 23

In [5]: t.b
Out[5]: 46

#works asexpected so far, now let's have a look into t.__dict__
In [6]: t.__dict__
Out[6]: {'a': 23}
-> b does not show up.

Could anyone please explain me why this does not work / how to get b
into .__dict__ / hint me to an explanation?

Thanks a lot in advance!

Cheers,

Ulrich
 
S

Steven D'Aprano

Good morning,

I wonder if someone could please help me out with the @property function
as illustrated in the following example.

class te():
def __init__(self):
self.a = 23
@property
def b(self):
return 2 * self.a [...]
Could anyone please explain me why this does not work / how to get b
into .__dict__ / hint me to an explanation?

b is a property object. Like any other assignment inside the body of the
class, it is shared across all instances, so you won't find it in the
instance's personal dict. You will find it in the shared class dict.

t.__dict__['b'] # not found
te.__dict__['b'] # will return the property object

(By the way: it is the usual convention to start the name of a class with
initial capital, so Te would be a better name.)

To get something into the instance dict, you need to assign it onto the
instance:

t.x = 42 # puts 'x':42 into t.__dict__
 
U

Ulrich

Good morning,
I wonder if someone could please help me out with the @property function
as illustrated in the following example.
class te():
    def __init__(self):
        self.a = 23
    @property
    def b(self):
        return 2 * self.a [...]
Could anyone please explain me why this does not work / how to get b
into .__dict__ / hint me to an explanation?

b is a property object. Like any other assignment inside the body of the
class, it is shared across all instances, so you won't find it in the
instance's personal dict. You will find it in the shared class dict.

t.__dict__['b']  # not found
te.__dict__['b']  # will return the property object

(By the way: it is the usual convention to start the name of a class with
initial capital, so Te would be a better name.)

To get something into the instance dict, you need to assign it onto the
instance:

t.x = 42  # puts 'x':42 into t.__dict__

Hi Steven,

Thanks a lot for your quick and helpful answer!


This would imply that I have to search in the dict of the class and
the dict of the instance. - works nicely.

I wonder if there is somewhere a "merge of the two" already available.

In the meantime, I came across dir()
In [7]: dir(t)
Out[7]: ['__doc__', '__init__', '__module__', 'a', 'b']

This seems to return 'a' and 'b', but now crashes

@property
def attributelist(self):
# find all attributes to the class that are of type numpy
arrays:
return [attr for attr in self.__dict__ if
isinstance(getattr(self, attr), numpy.ndarray)]
 
U

Ulrich

Good morning,
I wonder if someone could please help me out with the @property function
as illustrated in the following example.
class te():
    def __init__(self):
        self.a = 23
    @property
    def b(self):
        return 2 * self.a [...]
Could anyone please explain me why this does not work / how to get b
into .__dict__ / hint me to an explanation?
b is a property object. Like any other assignment inside the body of the
class, it is shared across all instances, so you won't find it in the
instance's personal dict. You will find it in the shared class dict.
t.__dict__['b']  # not found
te.__dict__['b']  # will return the property object
(By the way: it is the usual convention to start the name of a class with
initial capital, so Te would be a better name.)
To get something into the instance dict, you need to assign it onto the
instance:
t.x = 42  # puts 'x':42 into t.__dict__

Hi Steven,

Thanks a lot for your quick and helpful answer!

This would imply that I have to search in the dict of the class and
the dict of the instance. - works nicely.

I wonder if there is somewhere a "merge of the two" already available.

In the meantime, I came across dir()
In [7]: dir(t)
Out[7]: ['__doc__', '__init__', '__module__', 'a', 'b']

This seems to return 'a' and 'b', but now crashes

@property
def attributelist(self):
        # find all attributes to the class that are of type numpy
arrays:
        return [attr for attr in self.__dict__ if
isinstance(getattr(self, attr), numpy.ndarray)]


hi again,

I must have hit the send accidently before finishing.

This attributelist should return me all attributes of type
numpy.ndarry.

if I replace it to
def attributelist(self):
# find all attributes to the class that are of type numpy
arrays:
return [attr for attr in dir(self) if
isinstance(getattr(self, attr), numpy.ndarray)]

it crashes going into some kind of endless loop.

Do you happen to have any idea?

thanks again!

cheers,

ulrich
 
P

Peter Otten

Ulrich said:
if I replace it to
def attributelist(self):
# find all attributes to the class that are of type numpy
arrays:
return [attr for attr in dir(self) if
isinstance(getattr(self, attr), numpy.ndarray)]

it crashes going into some kind of endless loop.

Do you happen to have any idea?

dir(self) finds an attribute named "attributelist", getattr(self,
"attributelist") then tries to calculate the value of that attribute,
invokes dir(self) which finds an attribute named "attributelist" and so on
ad infinitum or the stack overflows. Try (untested)

@property
def attributelist(self):
return [attr for attr in dir(self) if attr != "attributelist" and
isinstance(getattr(self, attr), numpy.ndarray)]

to avoid the infinite recursion.
 
T

Thomas Rachel

Am 16.12.2011 09:52 schrieb Ulrich:
Could anyone please explain me why this does not work / how to get b
into .__dict__ / hint me to an explanation?

b is not a data element of the particular instance, but it lives in the
class. It is, roughly spoken, a "kind of method", just to be used
without calling. These things are called "data descriptors"
(http://docs.python.org/reference/datamodel.html#descriptors).

t.b is internally reflected to te.__dict__['b'].__get__(t, te) in order
to call the __get__ method of the property object. This is done on every
call and the value is, in your case, derived from the instance value a.

HTH,

Thomas
 
I

Ian Kelly

Ulrich said:
if I replace it to
def attributelist(self):
         # find all attributes to the class that are of type numpy
arrays:
         return [attr for attr in dir(self) if
isinstance(getattr(self, attr), numpy.ndarray)]

it crashes going into some kind of endless loop.

Do you happen to have any idea?

dir(self) finds an attribute named "attributelist", getattr(self,
"attributelist") then tries to calculate the value of that attribute,
invokes dir(self) which finds an attribute named "attributelist" and so on
ad infinitum or the stack overflows. Try (untested)

@property
def attributelist(self):
   return [attr for attr in dir(self) if attr != "attributelist" and
           isinstance(getattr(self, attr), numpy.ndarray)]

to avoid the infinite recursion.

Or remove attributelist from the class (it feels more like a generic
function than a class property to me) or make it a method instead of a
property.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top