python 如何在后台向嵌套函数传递参数?
How passing arguments to nested functions work in the background in python?
这是我前几天解决的随机问题。给定以秒为单位的年龄,必须计算某人在特定星球上的年龄。我试图动态地向我的 class 添加新方法并想出了这个解决方案:
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
的值不改变,直接在循环里传就改变了?
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's binding to local values
总而言之,python lambda 只包含对外部变量的引用。如果值改变,变量也会改变。
通过使用外部变量的值定义局部变量,在本例中为 planet=planet
,您可以在定义时将值绑定到 lambda。
这是我前几天解决的随机问题。给定以秒为单位的年龄,必须计算某人在特定星球上的年龄。我试图动态地向我的 class 添加新方法并想出了这个解决方案:
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
的值不改变,直接在循环里传就改变了?
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's binding to local values
总而言之,python lambda 只包含对外部变量的引用。如果值改变,变量也会改变。
通过使用外部变量的值定义局部变量,在本例中为 planet=planet
,您可以在定义时将值绑定到 lambda。