这是一个建议:
# creating data to use ...
class State:
"""Dummy class for State, the `name` member and the `__repr__` are for visualization purposes"""
def __init__(self, name):
self.name = name
def __repr__(self) -> str:
return self.name
# creating fake data (according to the structure you provided, though)
s1, s2, s3, s4 = State("S1"), State("S2"), State("S3"), State("S4")
s1.foo = 1; s1.bar = State(""); s1.bar.baz = 3; s1.value = 0
s2.foo = 1; s2.bar = State(""); s2.bar.qux = 4; s2.value = 0
s3.foo = 2; s3.bar = State(""); s3.bar.baz = 3; s3.value = 0
s4.foo = 2; s4.bar = State(""); s4.bar.qux = 4; s4.value = 0
states = [s1, s2, s3, s4]
# now solving the problem ...
def recursively_has_attr(obj, attrs: str) -> bool:
"""Iterate over an object members to check whether is has an 'a.b.c' attribute."""
for attr_name in attrs.split("."):
if hasattr(obj, attr_name):
obj = getattr(obj, attr_name)
else:
return False
else:
return True
# we are going to create customized versions of the function `recursively_has_attr`
# by pre-filling its `attrs` parameters, using `functools.partial`
from functools import partial
matching_foo = partial(recursively_has_attr, attrs="foo")
matching_bar_baz = partial(recursively_has_attr, attrs="bar.baz")
matching_bar_qux = partial(recursively_has_attr, attrs="bar.qux")
matching_bar_zod = partial(recursively_has_attr, attrs="bar.zod")
print(f"matching foo : {tuple(filter(matching_foo, states))}")
print(f"matching bar.baz : {tuple(filter(matching_bar_baz, states))}")
print(f"matching bar.qux : {tuple(filter(matching_bar_qux, states))}")
print(f"matching bar.zod : {tuple(filter(matching_bar_zod, states))}")
user_supplied_attrs = input("Enter the attribute you want to search : ")
filtering_function = partial(recursively_has_attr, attrs=user_supplied_attrs)
print(f"matching {user_supplied_attrs!r} : {tuple(filter(filtering_function, states))}")
产生:
matching foo : (S1, S2, S3, S4)
matching bar.baz : (S1, S3)
matching bar.qux : (S2, S4)
matching bar.zod : ()
Enter the attribute you want to search : bar
matching 'bar' : (S1, S2, S3, S4)
这行得通,其他方法也可以。
至于高效,真的是要求吗?
如果是,efficient 是什么意思?二是内存方面、速度方面、代码行方面、复杂性方面?
如果你想要非常好的性能,你会考虑使用低级语言吗? Cython 拥有“真正的”数组?
在你的数据上测试我的方法,如果还不够,请发布一个目标明确的问题:)