【问题标题】:Python multilevel getattr with string带有字符串的Python多级getattr
【发布时间】:2022-01-12 12:27:56
【问题描述】:

我有一个函数(这里称为analyze_data),它接受一个对象和一个字符串作为输入,并使用该字符串通过getattr“提取”数据。当数据处于“第一”级别的属性 (data1) 时,这可以正常工作。但是,我不知道当它们处于较低级别时我可以传递给函数以访问数据 (data2)。传递点分字符串(如下图)不起作用。

class a:
    pass

instance1 = a()

# Create 1st data set
instance1.data1 = [1,2,3]

# Create 2nd data set
instance1.subdata = a()
instance1.subdata.data2 = [4,5,6]


def analyze_data(myvar, dataname):
    data = getattr(myvar, dataname)
    # Do something with data, e.g.:
    print(str(data[0]))
    
analyze_data(instance1, 'data1')
analyze_data(instance1, 'subdata.data2')

在不过多更改现有功能analyze_data 的情况下访问data2 的最佳方式是什么?

【问题讨论】:

    标签: python object attributes getattr


    【解决方案1】:

    您应该使用attrgetter 而不是使用getattr,它允许您使用点符号指定。这确实需要对您的功能进行微小的更改,如下所示。

    from operator import attrgetter
    
    def analyze_data(myvar, dataname):
        fn = attrgetter(dataname)
        data = fn(myvar)
        # Do something with data, e.g.:
        print(str(data[0]))
    
    analyze_data(instance1, 'data1')
    1
    
    analyze_data(instance1, 'subdata.data2')
    4
    

    【讨论】:

      【解决方案2】:

      您可以通过分割虚线路径并跟随它来递归到数据中:

      def analyze_data(myvar, dataname):
          for dn in dataname.split('.'):
              myvar = getattr(myvar, dn)
          # Do something with data, e.g.:
          print(str(myvar[0]))
      

      这会不断更新myvar,直到您到达路径的尽头。

      【讨论】:

      • 答案不值得被否决。它明确地演示了解决方案的逻辑。这就是attrgetter 的工作方式。
      • 我试图按照简报而不是“过多”修改函数,而不是使用库或聪明的单线来混淆它。
      【解决方案3】:

      functools.reduce 是另一种选择。

      >>> from functools import reduce
      >>> reduce(getattr, 'subdata.data2'.split('.'), instance1)
      [4, 5, 6]
      

      【讨论】:

        【解决方案4】:

        在不改变功能的情况下实现你想要的一种方法是:

        class a:
        pass
        
        instance1 = a()
        
        # Create 1st data set
        instance1.data1 = [1,2,3]
        
        # Create 2nd data set
        instance1.subdata = a()
        instance1.subdata.data2 = [4,5,6]
        
        
        def analyze_data(myvar, dataname):
            data = getattr(myvar, dataname)
            # Do something with data, e.g.:
            print(str(data[0]))
        
        analyze_data(instance1, 'data1')
        analyze_data(instance1.subdata, 'data2')
        

        【讨论】:

        • 很好的答案!我没有这样做的唯一原因是因为实际上我的analyze_data 更复杂,并且不直接将instance1 作为参数,而是一个实例列表。
        猜你喜欢
        • 2011-03-17
        • 2016-06-01
        • 1970-01-01
        • 2023-03-27
        • 2016-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多