本文介绍了这是检查属性是否存在的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个更好的办法来检查属性的存在?

Which is a better way to check for the existence of an attribute?

的提供了这样的回答:

Jarret Hardie provided this answer:

if hasattr(a, 'property'):
    a.property

我看到,它也可以做这样的:

I see that it can also be done this way:

if 'property' in a.__dict__:
    a.property

是一个方法通常比别人多采用?

Is one approach typically used more than others?

推荐答案

有没有最好的方式,,因为你永远只是检查,看看是否一个属性存在;它往往是一些较大项目的一部分。有几种正确的方式和一个显着的不正确的方法。

There is no "best" way, because you are never just checking to see if an attribute exists; it is always a part of some larger program. There are several correct ways and one notable incorrect way.

if 'property' in a.__dict__:
    a.property

下面是一个演示,显示这种技术失败:

Here is a demonstration which shows this technique failing:

class A(object):
    @property
    def prop(self):
        return 3

a = A()
print "'prop' in a.__dict__ =", 'prop' in a.__dict__
print "hasattr(a, 'prop') =", hasattr(a, 'prop')
print "a.prop =", a.prop

输出:


'prop' in a.__dict__ = False
hasattr(a, 'prop') = True
a.prop = 3

在大多数情况下,你不想与 __ __字典一塌糊涂。这是做特别的东西,并检查是否一个属性存在相当平凡的一个特殊的属性。

Most of the time, you don't want to mess with __dict__. It's a special attribute for doing special things, and checking to see if an attribute exists is fairly mundane.

在Python中常见的成语是更容易请求原谅比许可,或EAFP的简称。你会看到很多的Python code,它使用这个成语,而不是只检查是否存在属性。

A common idiom in Python is "easier to ask for forgiveness than permission", or EAFP for short. You will see lots of Python code that uses this idiom, and not just for checking attribute existence.

# Cached attribute
try:
    big_object = self.big_object
    # or getattr(self, 'big_object')
except AttributeError:
    # Creating the Big Object takes five days
    # and three hundred pounds of over-ripe melons.
    big_object = CreateBigObject()
    self.big_object = big_object
big_object.do_something()

请注意,这是完全打开,可能不存在的文件相同的成语。

Note that this is exactly the same idiom for opening a file that may not exist.

try:
    f = open('some_file', 'r')
except IOError as ex:
    if ex.errno != errno.ENOENT:
        raise
    # it doesn't exist
else:
    # it does and it's open

另外,对于字符串转换为整数。

Also, for converting strings to integers.

try:
    i = int(s)
except ValueError:
    print "Not an integer! Please try again."
    sys.exit(1)

即使进口的可选模块...

Even importing optional modules...

try:
    import readline
except ImportError:
    pass

的LBYL方式

hasattr 方法,当然也可以。这种技术被称为短期或LBYL三思而后行。

The LBYL way

The hasattr method, of course, works too. This technique is called "look before you leap", or LBYL for short.

# Cached attribute
if not hasattr(self, 'big_object'):
    big_object = CreateBigObject()
    self.big_object = CreateBigObject()
big_object.do_something()

(即 hasattr 内置居然出奇3.2之前的行为在Python版本方面的例外 - 它会捕获异常,它不应该 - 但是这可能是无关紧要的,因为这样的例外是不可能的。在 hasattr 技术也比慢尝试/除,但你不知道把它往往不够关心,差异不是很大。最后, hasattr 不是原子,因此它可能抛出 AttributeError的如果另一个线程删除属性,但是这是一个牵强的场景,你需要围绕主题非常小心,无论如何,我不认为任何这三个差异是值得担忧的。)

(The hasattr builtin actually behaves strangely in Python versions prior to 3.2 with regard to exceptions -- it will catch exceptions that it shouldn't -- but this is probably irrelevant, since such exceptions are unlikely. The hasattr technique is also slower than try/except, but you don't call it often enough to care and the difference isn't very big. Finally, hasattr isn't atomic so it could throw AttributeError if another thread deletes the attribute, but this is a far-fetched scenario and you'll need to be very careful around threads anyway. I don't consider any of these three differences to be worth worrying about.)

使用 hasattr 比简单得多尝试/除,只要所有你需要知道的是,是否属性存在。对我来说最大的问题是,LBYL技术看起来奇怪,因为作为一个Python程序员,我更习惯阅读EAFP技术。如果你把上面的例子,让他们使用 LBYL 的风格,你就会得到code要么是笨拙的,完全不正确,或太难写了。

Using hasattr is much simpler than try/except, as long as all you need to know is whether the attribute exists. The big issue for me is that the LBYL technique looks "strange", since as a Python programmer I'm more used to reading the EAFP technique. If you rewrite the above examples so that they use the LBYL style, you get code that is either clumsy, outright incorrect, or too difficult to write.

# Seems rather fragile...
if re.match('^(:?0|-?[1-9][0-9]*)$', s):
    i = int(s)
else:
    print "Not an integer! Please try again."
    sys.exit(1)

和LBYL有时是彻头彻尾的不正确的:

And LBYL is sometimes outright incorrect:

if os.path.isfile('some_file'):
    # At this point, some other program could
    # delete some_file...
    f = open('some_file', 'r')

如果你想编写一个函数LBYL导入可选模块,是我的客人......这听起来像功能将是一个总的怪物。

If you want to write a LBYL function for importing optional modules, be my guest... it sounds like the function would be a total monster.

如果你只需要一个默认值, GETATTR 的一个较短的版本尝试/除

If you just need a default value, getattr is a shorter version of try/except.

x = getattr(self, 'x', default_value)

如果默认值是昂贵的构造,那么你会像这样结束:

If the default value is expensive to construct, then you'll end up with something like this:

x = getattr(self, 'attr', None)
if x is None:
    x = CreateDefaultValue()
    self.attr = x

或者,如果是一个可能的值,

sentinel = object()

x = getattr(self, 'attr', sentinel)
if x is sentinel:
    x = CreateDefaultValue()
    self.attr = x

结论

在内部, GETATTR hasattr 建宏只是使用尝试/除技术(除了用C语言编写)。因此,他们的行为都重要的地方以同样的方式,并选择合适的一个是由于环境和风格问题。

Conclusion

Internally, the getattr and hasattr builtins just use try/except technique (except written in C). So they all behave the same way where it counts, and picking the right one is due to a matter of circumstances and style.

尝试/除 EAFP code总是会擦一些程序员走错了路,而 hasattr / GETATTR LBYL code会激怒其他程序员。他们都是正确的,而且往往没有真正令人信服的理由选择一个或其他。 (然而,其他程序员很反感,你会认为这是很正常的一个属性是不确定的,有的程序员都吓坏了,它甚至有可能有在Python一个未定义的属性)。

The try/except EAFP code will always rub some programmers the wrong way, and the hasattr/getattr LBYL code will irk other programmers. They're both correct, and there's often no truly compelling reason to pick one or the other. (Yet other programmers are disgusted that you would consider it normal for an attribute to be undefined, and some programmers are horrified that it's even possible to have an undefined attribute in Python.)

这篇关于这是检查属性是否存在的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 07:36