[英]Is there a Python built-in that can select agnostically from either a dictionary or an object?
I'm looking for a function f(x,selector)
that acts like x.get(selector)
when x
is a dictionary and getattr(x, selector)
when x
is a class instance. 我在寻找一个函数
f(x,selector)
,其作用类似于x.get(selector)
时, x
是一本字典和getattr(x, selector)
当x
是一个类的实例。 Easy enough to write, but is there one built in? 很容易写,但是有内置的吗?
No, there is no built-in. 不,没有内置。
Just could just exception handling: 可能只是异常处理:
def f(x, selector):
try:
# Assume dictionary and has .get() method
return x.get(selector)
except AttributeError:
# Assumption incorrect, no .get() method present
return getattr(x, selector)
or swap the two lines if you want attributes to be checked for first. 或交换两行(如果要先检查属性)。
Another variant, supporting a default: 支持默认值的另一个变体:
_sentinel = object()
def f(x, selector, default=_sentinel):
try:
# Assume mapping access is supported
result = x[selector]
except KeyError:
# key missing, fall through to default handling
pass
except TypeError:
# Assumption incorrect, not a mapping, fall back to attributes
result = getattr(x, selector, default)
if result is _sentinel:
raise KeyError(selector)
return default
but you could also collapse the KeyError
handling into the second TypeError
handler and fall back to getattr()
first. 但是您也可以将
KeyError
处理折叠到第二个TypeError
处理函数中,然后先回退到getattr()
。
Take into account however that you are trying to mix two namespaces here; 但是请考虑到您要在此处混合使用两个名称空间。 keys and attributes can collide, and attribute literals are more limited than keys, etc. Most Python code doesn't try to mix the two, which is why there is no built-in for this task.
键和属性可能会发生冲突,并且属性文字比键更受限制,等等。大多数Python代码不会尝试将两者混合使用,这就是为什么此任务没有内置的原因 。
Another way is to check type of object 另一种方法是检查对象的类型
def f(x, selector):
if isinstance(x, dict):
return x.get(selector)
return getattr(x, selector)
In [297]: class Foo:
.....: def __init__(self):
.....: self.bar=5
.....:
In [298]: def f(x, selector):
.....: if hasattr(x, 'get'):
.....: g = operator.itemgetter(selector)
.....: else: # x is an object
.....: g = operator.attrgetter(selector)
.....: return g(x)
.....:
In [299]: x = Foo()
In [300]: f(x, 'bar')
Out[300]: 5
In [301]: d = {char:i for i,char in enumerate('asdf')}
In [302]: f(d, 'a')
Out[302]: 0
In [303]: d
Out[303]: {'a': 0, 's': 1, 'd': 2, 'f': 3}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.