能否将property与singledispatch/singledispatchmethod特性结合使用?
如何将property与singledispatch/singledispatchmethod结合使用?
当然可以结合,但你当前的写法存在问题——把singledispatch函数嵌套在setter内部会导致每次调用属性设置时都重新定义分发函数,既低效又不符合singledispatch的设计初衷。下面是两种正确的实现方式,满足你“仅允许将Foo.bar设置为str类型”的需求:
方案1:使用singledispatch定义外部处理函数
把类型分发逻辑抽离到类外部的独立函数中,在setter里调用这个函数即可:
from functools import singledispatch @singledispatch def _bar_setter(value): raise AttributeError(f"Can't set attribute 'bar' to type {type(value).__name__}") @_bar_setter.register(str) def _(value): return value class Foo(object): def __init__(self): self._bar = 'baz' @property def bar(self): return self._bar @bar.setter def bar(self, value): self._bar = _bar_setter(value)
方案2:使用singledispatchmethod定义类内部方法
如果希望分发逻辑和类绑定,可以用singledispatchmethod(Python 3.8+支持)将处理函数定义为类的方法:
from functools import singledispatchmethod class Foo(object): def __init__(self): self._bar = 'baz' @property def bar(self): return self._bar @bar.setter def bar(self, value): self._bar = self._process_bar_value(value) @singledispatchmethod def _process_bar_value(self, value): raise AttributeError(f"Can't set attribute 'bar' to type {type(value).__name__}") @_process_bar_value.register(str) def _(self, value): return value
测试验证
运行以下代码可以验证效果:
foo = Foo() foo.bar = "new_str" # 正常设置 print(foo.bar) # 输出: new_str foo.bar = 123 # 抛出AttributeError: Can't set attribute 'bar' to type int
原代码问题说明
你之前把_set函数定义在bar.setter内部,每次调用foo.bar = ...时都会重新创建这个分发函数并注册str类型的处理逻辑,这完全违背了singledispatch“一次注册、多次分发”的设计目的,同时会带来不必要的性能开销。将分发逻辑移到外部或类顶层,才能正确利用singledispatch的特性。
内容的提问来源于stack exchange,提问作者jay
相关产品推荐
相关产品推荐

