好问题!您使用描述符可以轻松完成您所寻求的内容.
Descriptors是实现描述符协议的Python对象,通常以__get __()开头.
它们主要存在于不同类中的类属性.在访问它们时,将调用它们的__get __()方法,并传入实例和所有者类.
class DifferentFunc:
"""Deploys a different function accroding to attribute access
I am a descriptor.
"""
def __init__(self, clsfunc, instfunc):
# Set our functions
self.clsfunc = clsfunc
self.instfunc = instfunc
def __get__(self, inst, owner):
# Accessed from class
if inst is None:
return self.clsfunc.__get__(None, owner)
# Accessed from instance
return self.instfunc.__get__(inst, owner)
class Test:
@classmethod
def _get_other_thing(cls):
print("Accessed through class")
def _get_other_thing_inst(inst):
print("Accessed through instance")
get_other_thing = DifferentFunc(_get_other_thing,
_get_other_thing_inst)
现在结果如下:
>>> Test.get_other_thing()
Accessed through class
>>> Test().get_other_thing()
Accessed through instance
那很简单!
顺便问一下,你注意到我在类和实例函数上使用了__get__吗?你猜怎么着?函数也是描述符,这就是它们的工作方式!
>>> def func(self):
... pass
...
>>> func.__get__(object(), object)
>
在访问函数属性时,会调用__get__,这就是你如何获得函数绑定.
有关更多信息,我强烈建议阅读上面链接的Python manual和“How-To”.描述符是Python最强大的功能之一,几乎不为人所知.
为什么不在实例化时设置功能?
或者为什么不在__init__中设置self.func = self._func?
在实例化时设置函数会带来很多问题:
> self.func = self._funccauses循环引用.该实例存储在self._func返回的函数对象中.另一方面,这在分配期间存储在实例上.最终结果是实例引用自身并以更慢和更重的方式清理.
>与您的类交互的其他代码可能会尝试直接从该类中获取该函数,并使用__get __()(这是通常的预期方法)来绑定它.他们将收到错误的功能.
>不适用于__slots__.
>虽然使用描述符需要了解机制,但在__init__上设置它并不是很干净,需要在__init__上设置多个函数.
>需要更多记忆.您可以为每个实例存储绑定函数,而不是存储单个函数.
>不适用于properties.
随着列表的不断发展,我还没有添加更多内容.