有没有办法遍历并执行Python类中的所有函数?

10 投票
7 回答
21567 浏览
提问于 2025-04-15 21:21

我有

class Foo():
    function bar():
        pass

    function foobar():
        pass

与其像下面这样一个一个地执行每个函数:

x = Foo()
x.bar()
x.foobar()

有没有什么内置的方法可以按照它们在类中写的顺序,循环执行每个函数呢?

7 个回答

5

因为Python把一个类的方法(还有其他属性)存储在一个字典里,而字典本质上是没有顺序的,所以这是不可能的。

如果你不在乎顺序,可以使用这个类的 __dict__

x = Foo()
results = []
for name, method in Foo.__dict__.iteritems():
    if callable(method):
        results.append(method(x))

如果函数需要额外的参数,也没问题——只要把这些参数放在类的实例后面就行。

13
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()

上面那个有趣的 @assignOrder(1) 这一行在 def bar(self) 之前,会导致以下事情发生:

Foo.bar = assignOrder(1)(Foo.bar)

assignOrder(1) 会返回一个函数,这个函数接收另一个函数,修改它(添加一个叫 order 的字段,并把它设置为 1),然后返回这个修改后的函数。这个函数随后会被用在它装饰的那个函数上(这样它的 order 字段就被设置了);最终的结果会替换掉原来的函数。

这其实是一个更高级、更易读、更好维护的说法:

  def bar(self):
    print "bar"
  Foo.bar.order = 1
10

不可以。你可以访问 Foo.__dict__,然后依次调用里面的每个值(如果遇到不能调用的成员就捕获错误),但是调用的顺序是不固定的。

for callable in Foo.__dict__.values():
    try:
        callable()    
    except TypeError:
        pass

这假设里面的函数都不需要参数,就像你举的例子那样。

撰写回答