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')
我有一个函数(这里称为 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')