有没有办法循环并执行 Python 类中的所有函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2597827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 01:02:27  来源:igfitidea点击:

Is there a way to loop through and execute all of the functions in a Python class?

pythonreflectionclass

提问by curious

I have

我有

class Foo():
    function bar():
        pass

    function foobar():
        pass

Rather than executing each function one by one as follows:

而不是像下面这样一个一个地执行每个函数:

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

is there a built-in way to loop through and execute each function in the sequence in which they are written in the class?

是否有内置的方法来循环并按照它们在类中编写的顺序执行每个函数?

采纳答案by Matthew Flaschen

No. You can access Foo.__dict__, and call each value in turn (catching errors for non-callable members), but the order is not preserved.

不可以。您可以访问Foo.__dict__, 并依次调用每个值(捕获不可调用成员的错误),但不会保留顺序。

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

This assumes none of the functions take parameters, as in your example.

这假设没有任何函数采用参数,如您的示例所示。

回答by badp

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

That funny @assignOrder(1)line above def bar(self)triggers this to happen:

@assignOrder(1)上面那条有趣的线def bar(self)触发了这种情况的发生:

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

assignOrder(1)returns a function that takes another function, changes it (adding the field orderand setting it to 1) and returns it. This function is then called on the function it decorates (its orderfield gets thus set); the result replaces the original function.

assignOrder(1)返回一个接受另一个函数的函数,更改它(添加字段order并将其设置为1)并返回它。然后在它装饰的函数上调用这个函数(它的order字段如此设置);结果替换了原来的函数。

It's a fancier, more readable and more maintainable way of saying:

这是一种更高级、更易读、更易于维护的说法:

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

回答by Daniel G

Since Python stores the methods (and other attributes) of a class in a dictionary, which is fundamentally unordered, this is impossible.

由于 Python 将类的方法(和其他属性)存储在字典中,而字典基本上是无序的,因此这是不可能的。

If you don't care about order, use the class's __dict__:

如果您不关心顺序,请使用类的__dict__

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

This also works if the function takes extra parameters - just put them after the instance of the class.

如果函数采用额外的参数,这也有效 - 只需将它们放在类的实例之后。

回答by Duncan

So long as you're only interested in Python 3.x (and from the empty parentheses in your class statement I'll guess you might be), then there is actually a simple way to do this without decorators: Python 3 allows you to provide your own dictionary like object to use while the class is defined.

只要你只对 Python 3.x 感兴趣(并且从你的 class 语句中的空括号我猜你可能是),那么实际上有一种简单的方法可以在没有装饰器的情况下做到这一点:Python 3 允许你提供您自己的字典,例如在定义类时使用的对象。

The following code is from PEP3115 except for the last couple of lines which I added to print out the methods in order:

以下代码来自 PEP3115,除了我添加的最后几行以按顺序打印出方法:

# 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__')])

回答by sergzach

There is probably one of the shortest methods (the class name is C):

可能有最短的方法之一(类名是C):

for func in filter(lambda x: callable(x), C.__dict__.values()):
    pass # here func is the next function, you can execute it here

The filterexpression returns all functions of the class C.

过滤器表达式返回类C的所有功能。

OR in one line:

或在一行中:

[func() for func in filter(lambda x: callable(x), C.__dict__.values())]

You can order somehow the functions, for example, by lexicographical order of their names by little more complex expression.

您可以以某种方式对函数进行排序,例如,通过更复杂的表达式按其名称的字典顺序。

回答by Azim

This works and preserves the order:

这有效并保留了顺序:

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

The output would be:

输出将是:

10--> 10
10--> 20
10--> 30

Note:The advantage of using this instead of F.__dict__.values()is that here you can have a list of those functions that you prefer to be called, and not necessarily all of them.

注意:使用 this 代替的好处F.__dict__.values()是,您可以在此处列出您喜欢调用的函数列表,而不一定是所有函数。