0

I have a long list of assignments like below which copies all local variables into class variables in the constructor.

self.x = x
self.y = y.
....

The reason is that I have complicated initialization expressions and and I'm using x rather than self.x for readability for all the intermediate computations.

I tried to simplify this block to something like

for name in ["x","y",...]:
  eval("self.%s = %s"%(name, name))

However, I'm getting SyntaxError inside eval, is their a better way to cut down this list?

Yaroslav Bulatov
  • 57,332
  • 22
  • 139
  • 197
  • https://docs.python.org/3/library/functions.html#setattr ? – hiro protagonist Apr 28 '17 at 15:13
  • https://stackoverflow.com/questions/16156797/how-to-not-put-self-when-initializing-every-attribute-in-a-python-class https://stackoverflow.com/questions/1118006/most-pythonic-way-of-organising-class-attributes-constructor-arguments-and-su https://stackoverflow.com/questions/5931474/automatically-generated-python-constructor – Josh Lee Apr 28 '17 at 15:16

2 Answers2

0

Attributes of self can be set using the builtin setattr function. Values of local variables can be looked up by name in the dictionary returned by locals().

For example:

class flying_sheep:
    def __init__(self):

        x = 1
        y = 2

        for name in ['x', 'y']:
            setattr( self, name, locals()[name] )
jez
  • 14,867
  • 5
  • 37
  • 64
0

I would make the object immutable, separate the concern of computing the values from initializing the object's attributes, and guard against the list of defined attributes being different from the intermediate variables. In other words, use namedtuple and a factory function.

>>> import collections
>>> class Thing(collections.namedtuple('Thing', ['x', 'y'])):
    pass

>>> def create_thing():
        x = 42
        y = 24
        return Thing(**locals())

>>> create_thing()
Thing(x=42, y=24)

If this looks opinionated, that's because it is: Any Python code that handles attributes by name should be written defensively.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275