【问题标题】:Is there a way to run a method for all instances of a class in python?有没有办法为python中一个类的所有实例运行一个方法?
【发布时间】:2013-11-16 16:13:53
【问题描述】:

示例代码:

>>> class MyClass(object):
        def __init__(self, x, y):
            self.x = x
            self.y = y
        def power(self):
            print(self.x**self.y)
        def divide(self):
            print(self.x/self.y)

>>> foo = MyClass(2, 3)
>>> bar = MyClass(4, 7)
>>> 
>>> foo.power()
8
>>> bar.divide()
0.5714285714285714

每当我以前在 Python 中使用类时,我只是分别为每个实例运行该方法(见上文)。我只是想知道是否有一种方法可以一次为该类的所有实例运行相同的方法,因为如果您有 20 个左右的实例,它可能会有点烦人。我正在考虑这样的事情:

>>> allinstances.power()
8
16384

有没有办法做到这一点?

【问题讨论】:

    标签: python class methods


    【解决方案1】:
    class MyClass(object):
    
        instancelist = []
    
        def __init__(self, x, y):
            self.x = x
            self.y = y
            MyClass.instancelist.append(self)
    
        def power(self):
            print(self.x ** self.y)
    
        def divide(self):
            print(self.x / self.y)
    
    
    foo = MyClass(2, 3)
    bar = MyClass(4, 7)
    
    [instance.power() for instance in MyClass.instancelist]
    

    将输出:

    8
    16384
    

    这样您就不需要在类定义之外存储任何全局变量或占位符。

    【讨论】:

      【解决方案2】:

      从你的问题来看,我相信你也会想要一点活力。像下面这样的东西可能会有所帮助:

      我添加了一个名为printBoth() 的函数用于演示。

      注意:以下是 Python 2.x 代码

      class MyClass(object):
          def __init__(self, x, y):
              self.x = x
              self.y = y
          def power(self):
              print "power",self.x**self.y
          def divide(self):
              print "divide", self.x/self.y
          def printBoth(self):
              print "x: ", self.x
              print "y: ", self.y
      
      class Test:
          def __init__(self, items):
              self.items = items
          def __getattr__(self, key):
              def fn():
                  return [getattr(x,key)() for x in self.items]
              return fn
      
      foo = MyClass(2, 3)
      bar = MyClass(4, 7)
      
      t = Test([foo,bar])
      
      t.power()
      t.divide()
      t.printBoth()
      

      输出:

      power 8
      power 16384
      divide 0
      divide 0
      x:  2
      y:  3
      x:  4
      y:  7
      

      注意:代码可能会在很多情况下中断,您需要在实际实现中进行额外的检查。


      重要的部分在这里:

      def __getattr__(self, key):
          def fn():
              return [getattr(x,key)() for x in self.items]
          return fn
      

      Test 实例上的任何函数调用都会调用上述函数。返回的是不带参数的函数。该函数在所有实例上运行,并在self.items 上的每个item 上调用相同的函数(这是您要在其上调用函数的所有实例的列表)。结果以列表形式返回。

      【讨论】:

        【解决方案3】:

        通常不会。但是,您可以让您的班级能够做到这一点:

        GLOBAL_MYCLASS_LIST = []
        
        class MyClass(object):
        
            def __init__(self, x, y):
                GLOBAL_MYCLASS_LIST.append(self)
                self.x = x
                self.y = y
        
            def power(self):
                print(self.x**self.y)
        
            def divide(self):
                print(self.x/self.y)
        
        a = MyClass(2, 3)
        b = MyClass(4, 7)
        all_powers = [i.power() for i in GLOBAL_MYCLASS_LIST]
        

        当然,您也可以在不将其放入类中的情况下执行此操作,这对于您可能拥有不同组 MyClasses 的大多数情况来说可能更简洁:

        myclass_list = []
        
        class MyClass(object):
        
            def __init__(self, x, y):
                self.x = x
                self.y = y
        
            def power(self):
                print(self.x**self.y)
        
            def divide(self):
                print(self.x/self.y)
        
        myclass_list.append(MyClass(2, 3))
        myclass_list.append(MyClass(4, 7))
        all_powers = [i.power() for i in myclass_list]
        

        【讨论】:

          【解决方案4】:

          当然。在创建实例时将它们放在一个列表中,然后遍历该列表并在每个实例上调用该方法。此外,您应该更改您的方法以返回而不是打印它们的结果,因为这更加灵活。这样您就可以将结果存储在列表中,将它们写入文件,使用它们进行进一步计算,打印它们。

          instances = [MyClass(2, 3), MyClass(4, 7)]
          results   = [x.power() for x in instances]
          

          【讨论】:

            【解决方案5】:

            只需使用循环:

            foo = MyClass(2, 3)
            bar = MyClass(4, 7)
            for i in [foo, bar]:
               i.power()
            

            如果您不确定所有实例都有该方法,请使用hasattr 检查:

            for i in list_of_instances:
               if hasattr(i, 'power'):
                   i.power()
            

            【讨论】:

              【解决方案6】:

              我认为所有答案都是有效的,具体取决于用例。我会争辩说,如果在你的应用程序/程序的单独部分中使用这个类,你就不想依赖之前声明的 GLOBAL_MYCLASS_LIST (正如@amber 所建议的那样)。您需要确保此变量存在并将其声明为 Class Variable 并将 compute_all 作为 Class method or even as a static method@staticmethod 装饰器(我认为这与特定用例不太相关。

              再次强调,这是一个非常具体的用例,并不常见。所以你应该在这样做之前考虑你的设计,而不是使用其他答案中提供的更直接的pythonic方式。

              我还想向您推荐这个关于 python 类的 Pycon lecture 的精彩视频,它很好地解释了这一点(甲板是 here。)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-03-21
                • 2020-11-02
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多