关于python:如何返回属性的默认值?

How can I return a default value for an attribute?

本问题已经有最佳答案,请猛点这里访问。

我有一个对象myobject,它可能返回None。如果返回None,则不会返回属性id

1
a = myobject.id

因此,当myObject为None时,上面的stament会产生AttributeError

1
AttributeError: 'NoneType' object has no attribute 'id'

如果myobject不是,那么我希望a等于None。如何在一行语句中避免此异常,例如:

1
a = default(myobject.id, None)

您应该使用getattr包装器,而不是直接检索id的值。

1
a = getattr(myobject, 'id', None)

这就像是说"我想从对象myobject中检索属性id,但是如果对象myobject中没有属性id,那么返回None",但是它是有效的。

有些对象还支持以下形式的getattr访问:

1
a = myobject.getattr('id', None)

根据操作要求,"Deep GetAttr":

1
2
3
4
5
def deepgetattr(obj, attr):
   """Recurses through an attribute chain to get the ultimate value."""
    return reduce(getattr, attr.split('.'), obj)
# usage:
print deepgetattr(universe, 'galaxy.solarsystem.planet.name')

简单说明:

reduce就像一个就地递归函数。在这种情况下,它的作用是从EDOCX1(universe)开始,然后使用getattr递归地加深您试图访问的每个属性,因此在您的问题中,它是这样的:

a = getattr(getattr(myobject, 'id', None), 'number', None)


最简单的方法是使用三元运算符:

1
a = myobject.id if myobject is not None else None

如果中间值为真,则三元运算符返回第一个表达式,否则返回后一个表达式。

请注意,您也可以用另一种方式进行此操作,使用异常:

1
2
3
4
try:
    a = myobject.id
except AttributeError:
    a = None

这符合Python的理想,即请求宽恕比许可更容易——什么是最好的将取决于情况。


在我的对象类中,可以放置重写

1
2
3
4
5
6
7
class Foo(object):
   def __getattribute__(self, name):
      if not name in self;
        return None;
      else:
        # Default behaviour
        return object.__getattribute__(self, name)

Help on built-in function getattr in module builtins:

1
2
getattr(...)
    getattr(object, name[, default]) -> value

Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.

以下内容应该有效:

1
a = getattr(myobject, 'id', None)

如果你想解决myobject类定义中的问题(如黑钻石的答案),你可以简单地定义__getattr__返回None

1
2
3
class Myobject:
    def __getattr__(self, name):
        return None

这是因为只有在尝试访问不存在的属性时才调用__getattr__,而不管属性的名称如何,总是首先调用__getattribute__。(另请参见本帖。)

尝试:

1
2
3
4
myobject = Myobject()
print myobject.id
myobject.id = 7
print myobject.id

1
a=myobect.id if myobject else None


1
2
3
4
try:
    a = myobject.id
except AttributeError:
    a = None

也会起作用,而且更清楚,IMO