Python 带字符串的多级getattr

Python multilevel getattr with string

我有一个函数(这里称为 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 的最佳方法是什么?

您应该使用 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

您可以通过拆分虚线路径并遵循它来递归到数据中:

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 直到您到达路径的尽头。

functools.reduce 是另一种选择。

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

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

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