1

Let's say I have a bunch of instances of the following class:

class Test:

    def __init__(self):
        self.x = 1

tests = [Test() for _ in range(10)]

Now, let's say I want to update x for each of the instances to range(10). What's a good, pythonic way to do that?

The most straightforward would be something like:

for t, val in zip(tests,range(10)):
    t.x = val

Is it possible to do it in a list comprehension?

[z[0].x = z[1] for z in zip(tests, range(10))]

gives an error. I guess you could add a setter method in the function and call that?

class Test:

    def __init__(self):
        self.x = 1

    def setter(self, val):
        self.x = val

tests = [Test() for _ in range(10)]

[z[0].setter(z[1]) for z in zip(tests, range(10)]

The for loop starts to look better and better. Is that the way to go?

Jeremy
  • 1,960
  • 4
  • 21
  • 42
  • 2
    Go with the first option. Using a list comp for a side effect is an anti-pattern. – DeepSpace Aug 28 '19 at 20:42
  • 1
    Note, python actually has a function for setting an attribute with a string, `settattr(obj, 'some_attribute_name', value)` but still, you should never use list-comprehensions for side-effects. I would say that in general, all functional programming constructs shouldn't be used for side-effects. It is not idiomatic, and will be confusing to readers. – juanpa.arrivillaga Aug 28 '19 at 20:43
  • 1
    Also, in general, note that for loops can almost always be considered pythonic, especially if you use the idiomatic looping constructs. List comprehensions and similar constructs are sugar, they are there for writing clean code, in the world of Python which is very much an imperative, object-oriented language, for-loops are about as idiomatic as it gets. Let me put it this way, I would never reject code in a review for having an equivalent for-loop instead of a list comprehension, but I would certainly do it for the reverse situation. – juanpa.arrivillaga Aug 28 '19 at 20:48

0 Answers0