如何将参数传递给嵌套函数在 python 的后台工作



这是我前几天解决的随机问题。给定以秒为单位的年龄,必须计算某人在特定星球上的年龄。我试图动态地向我的类添加新方法,并提出了这个解决方案:

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())

因此,当我从单独的方法(注释部分(调用lambdasetattr时,它工作得很好。但是当它们从__init__调用时,只有最后一个值,海王星,在调用on_mercuryon_mars或其他类似方法时被使用。

我知道在__init__中,它从外部函数的闭包中获取值,并且planet s 的值在循环中更改。但我不太明白这两种情况下到底发生了什么。以下是一些问题:

  • 它是传递给_add_method的行星变量的副本吗?
  • 为什么传递给_add_method的值没有改变,而是在直接在循环中传递时发生变化?
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 planet=planet: 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())
可以

在此处阅读为什么这样做的详细信息:Python lambda 与本地值的绑定

总之,python lambda只包含对外部变量的引用。如果值更改,变量也会更改。

通过使用外部变量的值定义局部变量(在本例中为 planet=planet(,您可以在定义时将该值绑定到 lambda。

最新更新