简体   繁体   English

是否有内置Python可以从字典或对象中进行不可知的选择?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM