代码之家  ›  专栏  ›  技术社区  ›  Imran

hasattr()vs try except块处理不存在的属性

  •  74
  • Imran  · 技术社区  · 17 年前
    if hasattr(obj, 'attribute'):
        # do somthing
    

    vs

    try:
        # access obj.attribute
    except AttributeError, e:
        # deal with AttributeError
    

    应该选择哪一种?为什么?

    12 回复  |  直到 17 年前
        1
  •  91
  •   Pierre.Vriens Krzysztof J    10 年前

    有没有能说明性能差异的长凳?

    是你的朋友

    $ python -mtimeit -s 'class C(object): a = 4
    c = C()' 'hasattr(c, "nonexistent")'
    1000000 loops, best of 3: 1.87 usec per loop
    $ python -mtimeit -s 'class C(object): a = 4
    c = C()' 'hasattr(c, "a")'
    1000000 loops, best of 3: 0.446 usec per loop
    $ python -mtimeit -s 'class C(object): a = 4
    c = C()' 'try:
     c.a
    except:
     pass'
    1000000 loops, best of 3: 0.247 usec per loop
    $ python -mtimeit -s 'class C(object): a = 4
    c = C()' 'try:
     c.nonexistent
    except:
     pass'
    100000 loops, best of 3: 3.13 usec per loop
    $
    
           |positive|negative
    hasattr|  0.446 |  1.87 
    try    |  0.247 |  3.13
    
        2
  •  85
  •   Alex Martelli    17 年前

    hasattr 在内部快速执行与客户相同的任务 try/except

        3
  •  29
  •   Community Mohan Dere    9 年前

    还有第三种选择,通常更好:

    attr = getattr(obj, 'attribute', None)
    if attr is not None:
         print attr
    

    优势:

    1. getattr exception-swallowing behavior pointed out by Martin Geiser -在旧蟒蛇中, hasattr 甚至会吞下一个 KeyboardInterrupt .

    2. 该属性以原子方式读取,并且不受其他线程更改对象的影响。(不过,如果这是一个主要问题,您可能需要考虑在访问对象之前锁定对象。)

    3. 它比我的短 try/finally 而且通常比 .

    4. 宽阔的 except AttributeError 积木可以接住其他的 AttributeErrors

    5. 访问属性比访问局部变量慢(特别是当它不是普通实例属性时)。(不过,老实说,Python中的微优化通常是一件傻事。)

    需要注意的一件事是,如果你关心 obj.attribute 设置为“无”,则需要使用不同的sentinel值。

        4
  •  19
  •   Martin Geisler    13 年前

    我几乎总是使用 hasattr :这是大多数情况下的正确选择。

    有问题的情况是当一个类重写 __getattr__ : 哈萨特 捕获所有异常 而不是仅仅抓住 AttributeError 如你所料。换句话说,下面的代码将被打印出来 b: False 即使看一场比赛更合适 ValueError 例外情况:

    class X(object):
        def __getattr__(self, attr):
            if attr == 'a':
                return 123
            if attr == 'b':
                raise ValueError('important error from your database')
            raise AttributeError
    
    x = X()
    print 'a:', hasattr(x, 'a')
    print 'b:', hasattr(x, 'b')
    print 'c:', hasattr(x, 'c')
    

    这一重大错误就这样消失了。这是 fixed in Python 3.2 ( issue9666 )在哪里 哈萨特 现在只接住 属性错误 .

    _notset = object()
    
    def safehasattr(thing, attr):
        return getattr(thing, attr, _notset) is not _notset
    

    getattr 处理这种情况,然后它可以提出适当的例外情况。

        5
  •  13
  •   Roee Adler    17 年前

    我认为这取决于函数是否可以接受没有属性的对象 有意 ,例如,如果函数有两个调用者,一个提供具有属性的对象,另一个提供不具有属性的对象。

    如果您得到的对象没有属性的唯一情况是由于某些错误,我建议使用异常机制,尽管它可能会慢一些,因为我相信它是一种更干净的设计。

        6
  •  5
  •   UncleZeiv    17 年前

    如果没有该属性,则为 不 在错误条件下,异常处理变量有一个问题:它还将捕获可能出现的AttributeError 内部 访问obj.attribute时(例如,因为属性是一个属性,所以访问它会调用一些代码)。

        7
  •  5
  •   Community Mohan Dere    6 年前

    Writing faster Python 三思而后行

    如果该属性确实缺失,那么乞求原谅将被删除 要比请求权限慢。所以根据经验,你可以 如果知道很可能 属性将丢失或其他您可以预测的问题。 否则,如果您希望代码在大多数情况下都是可读的 密码

    3许可还是宽恕?

    # CASE 1 -- Attribute Exists
    class Foo(object):
        hello = 'world'
    foo = Foo()
    
    if hasatter(foo, 'hello'):
        foo.hello
    ## 149ns ##
    
    try:
        foo.hello
    except AttributeError:
        pass
    ## 43.1 ns ##
    ## 3.5 times faster
    
    
    # CASE 2 -- Attribute Absent
    class Bar(object):
        pass
    bar = Bar()
    
    if hasattr(bar, 'hello'):
        bar.hello
    ## 428 ns ##
    
    try:
        bar.hello
    except AttributeError :
        pass
    ## 536 ns ##
    ## 25% slower
    
        8
  •  4
  •   n8gray    17 年前

    hasattr . 然而,如果你正在做 几个 try 块可以节省您一些打字时间。

        9
  •  3
  •   Douglas Leeder    17 年前

    我建议选择2。如果其他线程正在添加或删除该属性,则选项1具有竞争条件。

    python还有一个 Idiom EAFP(“请求原谅比允许更容易”)比LBYL(“三思而后行”)好。

        10
  •  2
  •   cjs    17 年前

    从实用的角度来看,在大多数语言中,使用条件语句总是比处理异常快得多。

    如果您想要处理当前函数之外某个地方不存在的属性的情况,那么使用异常是更好的方法。您可能希望使用异常而不是条件的一个指示符是,条件仅设置一个标志并中止当前操作,其他地方的某些东西会检查该标志并基于该标志采取操作。

    也就是说,正如Rax Olgud指出的那样,与他人的交流是代码的一个重要属性,而您想说的“这是一个例外情况”而不是“这是我期望发生的事情”可能更重要。

        11
  •  0
  •   Unknown    17 年前

    越短越好。例外情况应该是例外情况。

        12
  •  0
  •   Levite    13 年前

    至少当它取决于程序中正在发生的事情时,忽略可读性等人的部分(这实际上在大多数情况下比性能更重要(至少在这种情况下——有这样的性能跨度),正如Roee Adler和其他人指出的那样)。

    但是从这个角度来看,, 这就变成了一个选择的问题

    try: getattr(obj, attr)
    except: ...
    

    和

    try: obj.attr
    except: ...
    

    hasattr 仅使用第一个案例来确定结果。 思想食粮;-)

    推荐文章