您正在寻找一种动态构造一堆方法的方法。这通常不是一个好主意,但有时确实如此。 (例如,考虑像 PyObjC 和 pythoncom 之类的库,它们为 ObjC 和 COM 类构建动态代理,直到运行时你才知道。你还能怎么做?)
所以,你绝对应该考虑一下你是否真的想要和需要这个——但是,如果你这样做了,有两种基本方法。
动态构建静态类
如果您只是想包装foo 对象的集合,您可以在循环中创建所有方法。方法没什么太神奇的。您只需将它们定义为与任何其他函数相同,然后将它们分配给类。
唯一棘手的一点是你不能只写bar.f1 = …,因为f1 只能作为字符串使用。所以我们必须使用setattr来做到这一点:
class bar:
# your existing stuff
for name in 'f1 f2 f3 f4 f5 f6 f7 f8'.split():
foometh = getattr(foo, name)
def f(self):
for foo in self.myfoos:
foometh(foo)
f.__name__ = name
setattr(bar, name, f)
如果有某种规则指定您要转发哪些方法,而不是一堆方法名称的列表,您可以这样做:
for name, foometh in inspect.getmembers(foo):
if name.startswith('_') or not isinstance(foometh, types.FunctionType)) or <rest of your rule>:
continue
def f(self):
# from here it's the same as above
静态构建动态类
如果您试图总结任何符合某些基本条件的东西,而不是某些特定类的特定方法列表,您将不知道要总结什么,或者你想如何包装它,直到有人试图调用这些方法。因此,您必须抓住查找未知方法的尝试,并即时构建包装器。为此,我们覆盖__getattr__:
class bar:
# your existing stuff
def __getattr__(self, attr):
if attr.startswith('_') or <other rules here>:
raise AttributeError
def f():
for foo in self.myfoos:
foometh(foo)
f.__name__ = attr
return f
如果您不仔细观察,此版本返回的函数类似于绑定方法,而不是可以自省的实际绑定方法。如果您想要后者,请显式绑定一个方法,将self 作为参数添加到f,然后在f 上调用__get__ 并返回结果。 (如果你不知道这意味着什么,你就不想写这部分……)