如果我使用函数修补类的方法,该函数的行为就像一个方法,self
作为第一个args
传递。
class Spam:
pass
def eggs( *args ):
return args
Spam.eggs = eggs
spam = Spam()
print( spam.eggs() ) # ---> (<Spam>, )
# all good!
但是,如果我使用对象(使用.__call__
)实例进行修补,则self
不再作为参数传递:
class Spam:
pass
class Beans:
def __call__( *args ):
return args
Spam.beans = Beans()
spam = Spam()
print( spam.beans() ) # ---> (<Beans>, )
# - not good, I'd expect this to be
# (<Beans>, <Spam>, )
Spam
self
?Spam
self
?基本原理:出于缓存返回值的目的,我想修改我的类的函数(实际上使用装饰器而不是monkeypatching - 但这超出了这个问题的范围)。我不想用函数替换我的类的方法,而是想使用类对象,因为它允许我保留对象中的状态而不是尝试使用lambda
s修复所有闭包,从而产生更好的代码。
那是因为它是作为方法调用的函数对象,只是定义__call__
使类成为“可调用”,而不是函数对象(参见https://docs.python.org/3/reference/datamodel.html)。
要修复它,您可以使该类成为描述符:
class Spam:
pass
class Beans:
def __call__( *args ):
return args
def __get__(self, instance, owner):
from functools import partial
return partial(self.__call__, instance)
Spam.beans = Beans()
spam = Spam()
print(spam.beans())
得到
(<__main__.Beans object at 0x00000179F17664E0>, <__main__.Spam object at 0x00000179F1757F98>)