在一个包中,我已经隔离了一组在类中完全起作用的函数/变量。由于这些函数不需要特定的上下文,因此它们成为了类方法。它们可能使用一些外部函数,这里由save_c
函数表示。但我无法使用以下代码:
def save_c(v):
print("c :" + v)
class Writer(object):
@classmethod
def save(cls, t, v):
cls.writers[t](v)
@classmethod
def save_a(cls, v):
print("a :" + v)
@classmethod
def save_b(cls, v):
print("b :" + v)
writers = [save_a, save_b, save_c]
if __name__ == "__main__":
Writer.save(1, [1, 2, 3])
以前的代码导致以下错误:
TypeError: 'classmethod' object is not callable
有人知道我想要做什么是可以到达的吗?或者我是否有义务使用常规方法并在任何需要的地方实现作家?
答案 0 :(得分:1)
听起来您打算使用@staticmethod
而不是@classmethod
。
有关详细信息,请参阅What is the difference between @staticmethod and @classmethod in Python?
答案 1 :(得分:1)
实际上,内部writers
属性必须引用类方法的__func__
属性。是的,我们需要使用staticmethod
装饰器而不是classmethod
装饰器,以便尊重用于外部调用的相同签名。以下代码效果很好:
def save_c(v):
print("c :" + v)
class Writer(object):
@staticmethod
def save(t, v):
Writer.writers[t](str(v))
@staticmethod
def save_a(v):
print("a :" + v)
@staticmethod
def save_b(v):
print("b :" + v)
writers = [save_a.__func__, save_b.__func__, save_c]
if __name__ == "__main__":
Writer.save(0, [1, 2, 3])
Writer.save(1, [1, 2, 3])
Writer.save(2, [1, 2, 3])
答案 2 :(得分:1)
你也可以通过添加一个更聪明的包装类来实现它的工作。
由于您在评论中提到您需要调用其中一个writers
多个地方,我已经更新了我的答案,通过添加嵌套包装类来解决这个问题。在一个地方调用各种可调用类型的逻辑。这是使用OOP应用DRY原则的典型示例。
def save_c(v):
print("c :" + v)
class Writer(object):
@classmethod
def save(cls, t, v):
cls.writers[t](cls, v)
@classmethod
def save_a(cls, v):
print("a :" + v)
@staticmethod
def save_b(v):
print("b :" + v)
def _wrapper(writer):
if isinstance(writer, classmethod):
return type('ClassmethodWrapper', (object,), {'__call__':
lambda self, cls, v: writer.__func__(cls, str(v))})()
elif isinstance(writer, staticmethod):
return type('StaticmethodWrapper', (object,), {'__call__':
lambda self, cls, v: writer.__func__(str(v))})()
else:
return type('VanillaWrapper', (object,), {'__call__':
lambda self, cls, v: writer(str(v))})()
writers = list(map(_wrapper, (save_a, save_b, save_c)))
if __name__ == "__main__":
Writer.save(0, [1, 2, 3]) # -> a :[1, 2, 3]
Writer.save(1, [4, 5, 6]) # -> b :[4, 5, 6]
Writer.save(2, [7, 8, 9]) # -> c :[7, 8, 9]