0

I have the following piece of code:

d = dict(q='q', w='w', e='e')

class A(object):
    pass

for o in d.items():
    print o
    def _method(self):
        return o[0]
    setattr(A, o[1], _method)

a = A()
print a.q()
print a.w()
print a.e()

Output:

('q', 'q')
('e', 'e')
('w', 'w')
w
w
w

Desired output:

('q', 'q')
('e', 'e')
('w', 'w')
q
w
e

For the sake of simplicity, I have simplified the dictionary d and the class A. In reality, they are complex. Basically, I am trying to add methods dynamically to my class A since they are all pretty much similar and I don't want to copy paste code for each method. But the problem is all the dynamically assigned methods are equivalent to the last value of _method. How do I get the desired output?

Thanks in advance!

Nannan AV
  • 419
  • 7
  • 22
  • 3
    This has nothing to do with the way you’re adding them to classes; it’s because you’re creating three closures that all capture the same `o` variable and then use that variable’s current value at call time. There’s a nice dup for this with an answer that explains it in detail (which I or someone else will find for you shortly), and it’s also in the official Python FAQ. – abarnert Apr 24 '18 at 15:47
  • Related reading and/or possible duplicate: [Local variables in Python nested functions](https://stackoverflow.com/q/12423614/953482) – Kevin Apr 24 '18 at 15:49
  • But meanwhile, the quickest solution is the “default value hack” (which, despite the name, is perfectly clean, and idiomatic): `def _method(self, o=o):` – abarnert Apr 24 '18 at 15:50
  • See this: https://stackoverflow.com/a/534597/459745 – Hai Vu Apr 24 '18 at 15:54
  • Actually, in this case, it’s probably better to do `def _method(self, s=o[1]):` and then use `s` in the body. But if you can understand why one works, you can understand the other, and then come up with whatever makes sense for your design. – abarnert Apr 24 '18 at 15:55
  • Perfect, the default value hack worked.., But yet to digest it! – Nannan AV Apr 25 '18 at 10:05

0 Answers0