Вот случайная проблема, которую я решал на днях.Учитывая возраст в секундах, нужно рассчитать, сколько лет кому-то будет на конкретной планете.Я пытался динамически добавлять новые методы в свой класс и придумал следующее решение:
class MyClass(object):
year_in_seconds_on_earth = 31557600
planets = {
'earth': 1,
'mercury': 0.2408467,
'venus': 0.61519726,
'mars': 1.8808158,
'jupiter': 11.862615,
'saturn': 29.447498,
'uranus': 84.016846,
'neptune': 164.79132
}
def __init__(self, seconds):
self.seconds = seconds
for planet in self.planets:
func = lambda: self._on_planet(planet)
self.__setattr__('on_' + planet, func)
# self._add_method(planet)
# def _add_method(self, planet):
# func = lambda: self._on_planet(planet)
# self.__setattr__('on_' + planet, func)
def _on_planet(self, planet):
return round(self.seconds / self.year_in_seconds_on_earth / self.planets[planet], 2)
print(MyClass(2134835688).on_mercury())
Поэтому, когда я вызываю lambda
и setattr
из отдельного метода (закомментированная часть), он работает отличнохорошо.Но когда они вызываются из __init__
, при вызове on_mercury
, on_mars
или других подобных методов используется только последнее значение, neptune.
Я понимаю, что в __init__
оно принимает значениеот замыкания внешней функции и значение planet
s изменяется в цикле.Но я не совсем понимаю, что именно происходит в обоих случаях.Вот некоторые вопросы:
- Это копия переменной планеты, переданная в
_add_method
? - Почему значение, переданное в
_add_method
, не изменяется, а изменяется при его передачепрямо в петле?