如何将被装饰函数的__dict__属性传递给functools.partial实例?
如何让functools.partial继承原函数的自定义属性?
问题背景
我们有一个自定义装饰器,会给被装饰的函数添加自定义属性:
from typing import Callable def decorator() -> Callable: def wrapper(f: Callable) -> Callable: f.foo = "bar" return f return wrapper @decorator() def func(a: int, b: int) -> int: return a + b
正常调用时,我们可以直接访问函数的自定义属性:
>>> func.foo "bar" >>> func(1,2) 3
但当使用functools.partial包装函数后,无法直接通过partial实例访问原函数的自定义属性:
>>> from functools import partial >>> p = partial(func, a=1) >>> p(b=2) 3 >>> p.foo AttributeError: 'partial' object has no attribute 'foo'
虽然可以通过p.func.foo访问属性,但希望找到更直观的方式,让partial实例能直接继承原函数的自定义属性。
现有临时方案
目前尝试了继承partial并重写__init__的方式,在初始化时复制原函数的属性:
class new_partial(partial): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for k, v in self.func.__dict__.items(): setattr(self, k, v)
使用该类包装后可以直接访问属性:
>>> p = new_partial(func, a=1) >>> p(b=2) 3 >>> p.foo "bar"
但这种方式存在局限性:初始化时复制的属性是静态的,如果原函数的属性后续发生变化,partial实例不会同步更新;另外partial的实例是在__new__方法中创建的,重写__init__的方式不够规范。
更优解决方案
方案1:通过__getattr__动态代理属性
继承partial并重写__getattr__方法,当访问partial实例不存在的属性时,自动去原函数中查找:
from functools import partial class PartialWithAttrs(partial): def __getattr__(self, name): # 先尝试自身属性,不存在则代理到原函数 try: return super().__getattr__(name) except AttributeError: return getattr(self.func, name)
使用示例:
>>> p = PartialWithAttrs(func, a=1) >>> p(b=2) 3 >>> p.foo "bar" # 原函数属性更新后,partial实例也能拿到最新值 >>> func.foo = "new_bar" >>> p.foo "new_bar"
这种方式的优势:
- 无需提前复制属性,内存更高效
- 原函数属性更新时,partial实例会自动同步
- 符合Python的属性查找逻辑,行为更直观
方案2:函数式包装partial
如果不想创建自定义类,可以用函数包装partial,在创建partial实例后复制原函数的属性:
from functools import partial def partial_with_attrs(func, *args, **kwargs): p = partial(func, *args, **kwargs) # 只复制partial实例没有的属性 for attr_name, attr_value in func.__dict__.items(): if not hasattr(p, attr_name): setattr(p, attr_name, attr_value) return p
使用示例:
>>> p = partial_with_attrs(func, a=1) >>> p.foo "bar"
这种方式更轻量,但同样是静态复制属性,原函数属性更新后不会同步到partial实例。
总结
如果需要属性动态同步,优先选择方案1(__getattr__动态代理);如果只需要初始化时复制属性,且不想自定义类,可以选择方案2(函数式包装)。
内容的提问来源于stack exchange,提问作者Josmoor98
相关产品推荐
相关产品推荐

