Is there a way to loop through and execute all of the functions in a Python class?
我有
1 2 3 4 5 6 | class Foo(): function bar(): pass function foobar(): pass |
而不是一个接一个地执行每个函数,如下所示:
1 2 3 | x = Foo() x.bar() x.foobar() |
号
是否有一种内置的方法来循环并按照类中写入函数的顺序执行每个函数?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | def assignOrder(order): @decorator def do_assignment(to_func): to_func.order = order return to_func return do_assignment class Foo(): @assignOrder(1) def bar(self): print"bar" @assignOrder(2) def foo(self): print"foo" #don't decorate functions you don't want called def __init__(self): #don't call this one either! self.egg = 2 x = Foo() functions = sorted( #get a list of fields that have the order set [ getattr(x, field) for field in dir(x) if hasattr(getattr(x, field),"order") ], #sort them by their order key = (lambda field: field.order) ) for func in functions: func() |
在
1 | Foo.bar = assignOrder(1)(Foo.bar) |
。
这是一种更为花哨、更易读、更易于维护的表达方式:
1 2 3 | def bar(self): print"bar" Foo.bar.order = 1 |
不可以,您可以访问
1 2 3 4 5 | for callable in Foo.__dict__.values(): try: callable() except TypeError: pass |
这假定没有任何函数采用参数,如您的示例中所示。
因为Python将类的方法(和其他属性)存储在字典中,而字典基本上是无序的,所以这是不可能的。
如果您不关心订单,请使用类的
1 2 3 4 5 | x = Foo() results = [] for name, method in Foo.__dict__.iteritems(): if callable(method): results.append(method(x)) |
号
如果函数接受了额外的参数,这也可以工作——只需将它们放在类的实例之后。
可能有一个最短的方法(类名是c):
1 2 | for func in filter(lambda x: callable(x), C.__dict__.values()): pass # here func is the next function, you can execute it here |
。
筛选器表达式返回类C的所有函数。
或者在一行中:
1 | [func() for func in filter(lambda x: callable(x), C.__dict__.values())] |
您可以通过某种方式对函数进行排序,例如,通过对函数名称的词典编排顺序,使用稍微复杂一些的表达式。
只要您只对python 3.x感兴趣(从类语句中的空括号中,我猜您可能对它感兴趣),那么实际上有一种简单的方法可以做到这一点而不需要修饰:python3允许您在定义类时提供自己的类似字典的对象。
以下代码来自PEP3115,除了最后几行,我添加了这几行来按顺序打印方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # The custom dictionary class member_table(dict): def __init__(self): self.member_names = [] def __setitem__(self, key, value): # if the key is not already defined, add to the # list of keys. if key not in self: self.member_names.append(key) # Call superclass dict.__setitem__(self, key, value) # The metaclass class OrderedClass(type): # The prepare function @classmethod def __prepare__(metacls, name, bases): # No keywords in this case return member_table() # The metaclass invocation def __new__(cls, name, bases, classdict): # Note that we replace the classdict with a regular # dict before passing it to the superclass, so that we # don't continue to record member names after the class # has been created. result = type.__new__(cls, name, bases, dict(classdict)) result.member_names = classdict.member_names return result class MyClass(metaclass=OrderedClass): # method1 goes in array element 0 def method1(self): pass # method2 goes in array element 1 def method2(self): pass x = MyClass() print([name for name in x.member_names if hasattr(getattr(x, name), '__call__')]) |
。
这起作用并保持了秩序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class F: def f1(self, a): return (a * 1) def f2(self, a): return (a * 2) def f3(self, a): return (a * 3) allFuncs = [f1, f2, f3] def main(): myF = F() a = 10 for f in myF.allFuncs: print('{0}--> {1}'.format(a, f(myF, a))) |
。
输出将是:
1 2 3 | 10--> 10 10--> 20 10--> 30 |
注意:使用这个函数而不是