我设计了一门课。它非常标准,有一些方法属性。
class foo:
def f1(self):
print 'f1'
def f2(self):
print 'f2'
....
def fn(self):
print 'fn'现在,我想创建一个包含一组foo实例的类。
class bar:
self.myfoos=[foo(),foo(),foo()]然后,我想在所有foo实例上对f1..fn方法进行分类。我可以做:
class bar:
...
def f1():
for foo_ in self.myfoos:
foo_.f1()然而,我的f1..fn列表很长,所以我如何才能以一种简洁的方式获得这种行为呢?也许完全采用替代设计?
发布于 2018-05-25 23:36:16
您只需实现__getattr__并将该调用委托给foos列表。我相信有一种更优雅的方法可以做到这一点:
class foo:
def f1(self):
print('f1')
def f2(self):
print('f2')
class bar:
def __init__(self):
self.foos = [foo() for _ in range(3)]
def __getattr__(self, fn):
def fns(*args, **kwargs):
for f in self.foos:
getattr(f, fn)(*args, **kwargs)
return fns
In []:
b = bar()
b.f1()
Out[]
f1
f1
f1
In []:
b.f2()
Out[]:
f2
f2
f2发布于 2018-05-25 23:01:46
您正在寻找一种动态构造一组方法的方法。这通常不是一个好主意--但有时是这样。(例如,考虑像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__并返回结果,显式绑定方法。(如果你不知道这意味着什么,你不想写这部分…)
https://stackoverflow.com/questions/50537673
复制相似问题