简洁的getattr()方法,如果不是Python中的None,则使用它

时间:2010-03-11 20:50:42

标签: python

我发现自己经常做以下事情:

attr = getattr(obj, 'attr', None)
if attr is not None:
    attr()
    # Do something, either attr(), or func(attr), or whatever
else:
    # Do something else

有更多的pythonic写作方式吗?这是否更好? (至少没有表现,IMO。)

try:
    obj.attr() # or whatever
except AttributeError:
    # Do something else

7 个答案:

答案 0 :(得分:36)

由于您正在呼叫attr,您可以这样做:

def default_action():
    # do something else

action = getattr(obj, 'attr', default_action)

action()

答案 1 :(得分:12)

与Joe的答案相似,但更短:

getattr(obj, 'attr', lambda: None)()

答案 2 :(得分:7)

还有另一个很好的习语:

if hasattr(obj, 'attr'):
    ...something...
else:
    ...something else...

从您发布的两个选项中我更喜欢第一个选项。在访问成员时抛出异常的概念似乎并不是例外意图用来做的事情。

答案 3 :(得分:7)

try / except替代方案,在您编写代码时,可能会意外导致AttributeErrorattr()正在调用的任何问题而导致try被捕获。如果您想使用except / try: attr = obj.attr except AttributeError: dosome(thingelse) else: attr() 进行编码,如果该属性很少丢失,这是合理且表现良好的,请使用:

{{1}}

这将导致“意外捕获”如上所述。关于哪种方法更可取,我通常采用例外捕捉方法 - “EAFP”,“比宽容更容易请求宽恕”(通常归功于海军上将Grace Hopper,COBOL和CODASYL背后的驱动力)绝对适用很好的Python; - )。

答案 4 :(得分:1)

使用try / except通常被认为更加pythonic。如果obj具有该属性,它也更有效,因为它消除了测试 - 如果不抛出异常,try块没有开销。另一方面,如果obj没有该属性,则效率较低,因为它将具有抛出和捕获异常的开销。

答案 5 :(得分:1)

啊,这取决于确切的代码。你的两个工具:

  • hasattr(obj,'attr')当且仅当obj.attr存在时才返回True。
  • getattr(obj,'attr',other_value)返回obj.attr(如果存在),否则为other_value
  • 当性能低于可读性时,尝试a = obj.attr /除failure()/ else do_something(a)。

以下是最常见的情况:

 the_name = getattr(user, 'name', '<Unknown User>')
 user.name = getattr(user, 'name', '<Unknown User>')
 if not hasattr(name, 'user'):
    try_asking_again()
 name = user.name if hasattr(user, 'name') else do_expensive_name_lookup(user)

要更好地了解整个过程,请查看以下代码段:

class Thing():
    def __init__(self):
        self.a = 'A'

    def __getattr__(self, attr):
        if attr == "b":
            return "B"
        else:
            raise AttributeError("Thing instance has no attribute '" + attr + "'")

item = Thing()
print "hasattr(a) is " + str(hasattr(item, "a"))
print "a is " + item.a
print "hasattr(b) is " + str(hasattr(item, "b"))
print "b is " + item.b
out = "c is " + item.c if hasattr(item, "c") else "No C"
print out
print "and c is also " + getattr(item, "c", "Not Assigned")
print "c throws an Attribute exception " + item.c

有这个输出:

hasattr(a) is True
a is A
hasattr(b) is True
b is B
No C
and c is also Not Assigned
Traceback (most recent call last):
  File "attr_snippet.py", line 23, in <module>
    print "c throws an Attribute exception " + item.c
  File "attr_snippet.py", line 9, in __getattr__
    raise AttributeError("Thing instance has no attribute '" + attr + "'")
AttributeError: Thing instance has no attribute 'c'

答案 6 :(得分:0)

一个班轮:

object.attr() if hasattr(object, 'attr') else None

文档说明

hasattr(object, name: str)

<块引用>

参数是一个对象和一个字符串。如果字符串是对象属性之一的名称,则结果为 True,否则为 False。 (这是通过调用 getattr(object, name) 并查看它是否引发 AttributeError 来实现的。)