如何在不使用列表或字典等可变类型的情况下传递函数引用
How to pass function reference without using mutable type like list or dict
我的目标:传递对函数的引用,并能够在以后更新函数。
在 Python 中,我相信函数是通过引用传递的,但函数的引用被认为是不可变的。因此,该功能以后无法更新。
本题进入核心问题:Python functions call by reference
答案都指向解决方法:在可变类型中传递函数,例如 list
或 dict
.
我想知道:是否有更直接的方法?可能有一些 functools
函数、types
实用程序或外部库可以实现此功能行为?
示例代码
**更新**:我没兴趣制作foo._on_call
public。我试图通过引用从外部更改 on_call
,而不是直接在 foo
对象上实际操作。
from typing import Callable, List
class Foo:
def __init__(self, on_call: Callable[[], int]):
self._on_call = on_call
def __call__(self) -> int:
return self._on_call()
def do_something() -> int:
return 0
def do_something_else() -> int:
return 1
foo = Foo(do_something)
do_something = do_something_else # Updating do_something
print(do_something()) # This prints 1 now
print(foo()) # This still prints 0, I want this to print 1 now too
已知(不良)解决方法:
- 在列表中传递
do_something
- 重新创建
foo
对象
- 制作
Foo
的 _on_call
属性 public 或使用 property
装饰器
Python版本:3.8
在 Foo
之外分配 do_something = do_something_else
不会更改称为 do_something
的函数,它只是将模块范围中的名称 do_something
指向不同的功能。 Foo
实例范围内的名称 _on_call
不受此影响,仍指向原始函数。
实现你想要的最简单和最惯用的方法是使 _on_call
成为 Foo
实例的 public 属性,或者添加一个更新它的方法:
1。属性
class Foo:
def __init__(self, on_call):
self.on_call = on_call
# ...
foo = Foo(do_something)
# ...
foo.on_call = do_something_else
(您不必重命名属性即可执行此操作,但将下划线开头的属性视为不应该从 class 外部访问的属性是一种很好的风格。)
2。方法
class Foo:
def __init__(self, on_call):
self._on_call = on_call
def update(self, on_call):
self._on_call = on_call
# ...
foo = Foo(do_something)
# ...
foo.update(do_something_else)
函数实际上是可变的,通过 __code__
. 。但是,不知道这是否是个好主意。
do_something.__code__ = do_something_else.__code__
print(do_something()) # -> 1
print(foo()) # -> 1
我的目标:传递对函数的引用,并能够在以后更新函数。
在 Python 中,我相信函数是通过引用传递的,但函数的引用被认为是不可变的。因此,该功能以后无法更新。
本题进入核心问题:Python functions call by reference
答案都指向解决方法:在可变类型中传递函数,例如 list
或 dict
.
我想知道:是否有更直接的方法?可能有一些 functools
函数、types
实用程序或外部库可以实现此功能行为?
示例代码
**更新**:我没兴趣制作foo._on_call
public。我试图通过引用从外部更改 on_call
,而不是直接在 foo
对象上实际操作。
from typing import Callable, List
class Foo:
def __init__(self, on_call: Callable[[], int]):
self._on_call = on_call
def __call__(self) -> int:
return self._on_call()
def do_something() -> int:
return 0
def do_something_else() -> int:
return 1
foo = Foo(do_something)
do_something = do_something_else # Updating do_something
print(do_something()) # This prints 1 now
print(foo()) # This still prints 0, I want this to print 1 now too
已知(不良)解决方法:
- 在列表中传递
do_something
- 重新创建
foo
对象 - 制作
Foo
的_on_call
属性 public 或使用property
装饰器
Python版本:3.8
在 Foo
之外分配 do_something = do_something_else
不会更改称为 do_something
的函数,它只是将模块范围中的名称 do_something
指向不同的功能。 Foo
实例范围内的名称 _on_call
不受此影响,仍指向原始函数。
实现你想要的最简单和最惯用的方法是使 _on_call
成为 Foo
实例的 public 属性,或者添加一个更新它的方法:
1。属性
class Foo:
def __init__(self, on_call):
self.on_call = on_call
# ...
foo = Foo(do_something)
# ...
foo.on_call = do_something_else
(您不必重命名属性即可执行此操作,但将下划线开头的属性视为不应该从 class 外部访问的属性是一种很好的风格。)
2。方法
class Foo:
def __init__(self, on_call):
self._on_call = on_call
def update(self, on_call):
self._on_call = on_call
# ...
foo = Foo(do_something)
# ...
foo.update(do_something_else)
函数实际上是可变的,通过 __code__
.
do_something.__code__ = do_something_else.__code__
print(do_something()) # -> 1
print(foo()) # -> 1