2 回答

TA贡献1865条经验 获得超7个赞
好问题!您可以使用描述符轻松地完成查找。
描述符是实现描述符协议的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)
<bound method func of <object object at 0x000000000046E100>>
访问函数属性后,将__get__调用它,这就是获取函数绑定的方式。
有关更多信息,我强烈建议阅读Python手册和上面链接的“操作方法”。描述符是Python最强大的功能之一,甚至鲜为人知。
为什么不设置实例化功能?
还是为什么不设置self.func = self._func
在里面__init__
?
将函数设置为实例化会带来很多问题:
self.func = self._func
导致循环引用。实例存储在由返回的函数对象中self._func
。另一方面,这是在分配期间存储在实例上的。最终结果是该实例引用了自己,并且将以慢得多,更沉重的方式进行清理。与您的类进行交互的其他代码可能会尝试将该函数直接带出该类,并使用
__get__()
,这是通常的预期方法来对其进行绑定。他们将收到错误的功能。将无法使用
__slots__
。尽管使用描述符需要了解机制,但将其设置
__init__
为不干净,需要将多个功能设置为__init__
。占用更多内存。您不必为每个实例存储一个绑定函数,而不必存储一个函数。
将无法使用属性。
随着列表的不断进行,我没有添加更多内容。

TA贡献1951条经验 获得超3个赞
这是一个有点棘手的解决方案:
class Thing(object):
@staticmethod
def get_other_thing():
return 1
def __getattribute__(self, name):
if name == 'get_other_thing':
return lambda: 2
return super(Thing, self).__getattribute__(name)
print Thing.get_other_thing() # 1
print Thing().get_other_thing() # 2
如果我们在上课,则执行staticmethod。如果我们在实例上,__getattribute__首先要执行,那么我们就不能返回Thing.get_other_thing其他函数(lambda在我的情况下)
添加回答
举报