我遍历了一个列表,并希望对每个项调用一个函数,但是这个函数应该是可替换的。你知道吗
例如,我有以下脚本:
class Parent(object):
def a(self, text):
raise NotImplementedError("called Parent.a")
def b(self, text):
raise NotImplementedError("called Parent.b")
class ChildA(Parent):
def a(self, text):
return "A.a: {}".format(text)
def b(self, text):
return "A.b: {}".format(text)
class ChildB(Parent):
def a(self, text):
return "B.a: {}".format(text)
def b(self, text):
return "B.b: {}".format(text)
# the separation is ONLY so that the first exec_all doesn't fail
# in my production code it's a list of mixed instances
children = [
ChildA(), # obviously here might be several different ChildA instances
]
childrenMixed = children + [
ChildB(), # obviously here might be several different ChildB instances
]
def exec_all(method, children):
for child in children:
try:
print(method(child, "Hello world"))
except Exception as e:
print("Unable to call method for child '{}': {}".format(child, e.message))
exec_all(ChildA.a, children) # works
exec_all(ChildA.b, children) # works
exec_all(ChildA.a, childrenMixed) # TypeError
exec_all(ChildA.b, childrenMixed) # TypeError
exec_all(Parent.a, childrenMixed) # NotImplementError
exec_all(Parent.b, childrenMixed) # NotImplementError
前两个exec_all
工作正常,但后两个不工作,因为它试图调用ChildA.a
,而ChildB
中不存在。最后两个提高NotImplementedError
。你知道吗
应该是这样的:
A.a: Hello world # 1st exec_all
A.b: Hello world # 2nd exec_all
A.a: Hello world # 3rd exec_all
B.a: Hello world # but TypeError
A.b: Hello world # 4th exec_all
B.b: Hello world # but TypeError
A.a: Hello world # 5th exec_all
B.a: Hello world # but NotImplementError
A.b: Hello world # 6th exec_all
B.b: Hello world # but NotImplementError
那么如何支持Parent
的多个子类呢?你知道吗
你想要这样的东西吗?你知道吗
或:
传递方法名,而不是方法。使用^{} 获取方法:
收益率
在Python2中,
ChildA.a
是一种未绑定的方法。与Python3不同,unbound方法检查第一个参数是否是本例中正确类的实例ChildA
。这就是为什么打电话来引发
TypeError
:在Python3中,这样的调用是可以的,不过如果您这样做的话,最好是让所有这些方法都成为普通函数,而不是方法。你知道吗
听起来您确实希望在发布函数调用时保留其形式:
如果我们将此作为一个固定的需求,那么您可以通过定义
exec_all
获得所需的行为,如下所示:但是故意传递错误的方法并不是一个好的设计。如果希望调用
ChildB.a
,则不应传递ChildA.a
。Python并没有使这变得简单,因为这不是OOP的工作方式。 传递正确的方法或将方法名作为字符串传递(如上所示)都是更好的选择。你知道吗相关问题 更多 >
编程相关推荐