1

I would like to create object properties using a loop, and the setattr function. The problem i run into is that all the properties created with such a loop are equal to one another.

In the following example i create a class A with a single attribute z, a complex number. i then would like to loop over functions such as numpy's real and imag to create other properties, such as z_real and z_imag. The problem then, in the context of this example, is that z_real == z_imag is True.

import numpy as np

class A(object):
    def __init__(self, z):
        self.z = z

        for func in [np.real, np.imag]:
            fget = lambda x: func(x.z)
            print('self.z_%s = %i' % (func.__name__, fget(self)))
            setattr(self.__class__, 'z_%s' % (func.__name__),
                    property(fget))


a = A(1+2j)

print ('a.z_real=%i'% a.z_real)
print ('a.z_imag=%i'% a.z_imag)

running this yields

self.z_real = 1
self.z_imag = 2
a.z_real=2    
a.z_imag=2

It is not clear to me why this is.

1
  • because i want to create many properties in this manner. Commented Mar 4, 2012 at 0:30

2 Answers 2

1

You're doing it wrong.

Don't create more then one instance of the same closure per normal function!

fget = lambda x, f=func: f(x.z)
Sign up to request clarification or add additional context in comments.

3 Comments

thanks! i browsed that link, and not clear on the issue, there is actually a reasonable debate in the comments. could be characterized as a sloppy use of variable scope? because func was used in the lambda function, but not passed.
It is exactly an issue with scope.
1

Your fget is a closure. It closed over the variable func. After the loop is finished, func remains set to np.imag.

You should do the following afer self.z = z:

def make_getter(func):
    return lambda x: func(x.z)

for func in [np.real, np.imag]:
    fget = make_getter(func)

etc.

1 Comment

yes, that has been my work around, but i didnt know why my original way dint work untill now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.