在我的代码中,我有一个类,其中一个方法负责过滤一些数据。为了允许后代的自定义,我想将过滤函数定义为类属性,如下所示:
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
filter_func = my_filter_func
def filter_data(self, data):
return filter(self.filter_func, data)
class FilterClassDescendant(FilterClass):
filter_func = my_filter_func2
但是,这样的代码会导致TypeError,因为filter_func接收“self”作为第一个参数。 处理此类用例的pythonic方法是什么?也许,我应该将我的“filter_func”定义为常规类方法?
答案 0 :(得分:4)
您可以将其添加为普通旧属性吗?
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
def __init__(self):
self.filter_func = my_filter_func
def filter_data(self, data):
return filter(self.filter_func, data)
或者,强迫它成为静态方法:
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
filter_func = staticmethod(my_filter_func)
def filter_data(self, data):
return filter(self.filter_func, data)
答案 1 :(得分:2)
Python里面有很多魔力。其中一个魔法与将函数转换为UnboundMethod对象(分配给类,而不是类'实例)有关。
当你分配一个函数时(我不确定它是否适用于任何可调用函数或只是函数),Python会将它转换为UnboundMethod对象(即可以使用实例调用的对象)。
在正常情况下,您可以正常调用UnboundMethod:
def myfunction(a, b):
return a + b
class A(object):
a = myfunction
A.a(1, 2)
#prints 3
这不会失败。但是,当您尝试从实例中调用它时,会出现不同的情况:
A().a(1, 2)
这将失败,因为当实例获得(例如,内部getattr
)属性为UnboundMethod时,它会返回此类方法的副本,并填充im_self
成员(im_self
并且im_func
是UnboundMethod的成员。您打算调用的函数位于im_func
成员中。当您调用此方法时,您实际上会使用im_func
中的值实际调用im_self
。因此,该函数需要一个额外的参数(第一个参数,它代表自己)。
为了避免这种魔力,Python有两个可能的装饰器:
@staticmethod
。在这种情况下,您将具有未转换为UnboundMethod的功能。但是,除了作为全局引用之外,您将无法访问调用类。@classmethod
。示例:
class A(object):
a = staticmethod(lambda a, b: a + b)
A.a(1, 2)
A().a(1, 2)
两者都有效。
另一个例子:
def add_print(cls, a, b):
print cls.__name__
return a + b
class A(object):
ap = classmethod(add_print)
class B(A):
pass
A.ap(1, 2)
B.ap(1, 2)
A().ap(1, 2)
B().ap(1, 2)
由yourseld检查并享受魔力。