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

时间:2014-10-30 16:53:22

标签: python object dictionary selector

我正在寻找一个函数f(x,selector),当x.get(selector)是字典时就像x一样,而当getattr(x, selector)是一个类实例时,x就像{{1}}一样。写得容易,但内置了吗?

3 个答案:

答案 0 :(得分:3)

不,没有内置功能。<​​/ p>

只是异常处理:

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)
如果要首先检查属性,请

或交换两行。

另一种变体,支持默认值:

_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

但您也可以将KeyError处理方式折叠为第二个TypeError处理程序,然后再回到getattr()

但是考虑到你在尝试混合两个命名空间;键和属性可能会发生冲突,属性文字比键等更受限制。大多数Python代码都没有尝试将两者混合,这是为什么没有内置的任务

答案 1 :(得分:2)

另一种方法是检查对象的类型

def f(x, selector):
    if isinstance(x, dict):
       return x.get(selector)
    return getattr(x, selector)

答案 2 :(得分:0)

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}