在Python中检查成员是否存在
在Python中检查成员是否存在
我经常想要检查一个对象是否具有某个成员。一个例子是在函数中创建一个单例。为此,您可以像这样使用hasattr
:
class Foo(object): @classmethod def singleton(self): if not hasattr(self, 'instance'): self.instance = Foo() return self.instance
但您也可以这样做:
class Foo(object): @classmethod def singleton(self): try: return self.instance except AttributeError: self.instance = Foo() return self.instance
这两种方法哪种更好?
编辑:添加了@classmethod
...但请注意,问题不是如何制作一个单例,而是如何检查对象中成员的存在。
编辑:对于这个例子,一个典型的用法是:
s = Foo.singleton()
然后s
是一个Foo
类型的对象,每次都是相同的。通常,该方法会被多次调用。
在Python中,检查成员是否存在有两种不同的方法:方法1是LBYL(look before you leap),方法2是EAFP(easier to ask forgiveness than permission)。
Python开发者通常建议使用EAFP方法,理由是“如果在你测试文件是否存在和尝试创建文件之间的时间内,有其他进程创建了这个文件,该怎么办?”虽然这个理由在这里并不适用,但这是一个普遍的想法。我们不应把异常当作太过异常的情况。
在性能方面,在你的情况下,由于在CPython中建立异常处理器(使用try关键字)非常廉价,而创建异常(使用raise关键字和内部异常创建)相对较昂贵,使用方法2,异常只会被引发一次;之后,你只需使用属性即可。
Python中检查成员是否存在的原因是为了避免在访问某些属性或方法之前出现错误。在上面的代码示例中,使用了两种不同的方法来检查成员是否存在。
第一种方法是使用hasattr()函数来检查成员存在性,具体实现如下:
if not hasattr(self, 'instance'): self.instance = Foo() return self.instance
第二种方法是使用try/except语句来捕捉属性错误异常(AttributeError),具体实现如下:
try: return self.instance except AttributeError: self.instance = Bar() return self.instance
通过对上述代码进行测试,发现使用try/except语句的方法更快。值得注意的是,hasattr()函数在后台使用异常来确定属性是否存在,可能会导致速度稍慢。
在测试中,创建了大量的Foo和Bar对象,并进行了多次循环测试,得到了如下结果:
Objs created. #1 Foo pass in 1.719000 #1 Bar pass in 1.140000 #2 Foo pass in 1.750000 #2 Bar pass in 1.187000 #3 Foo pass in 1.797000 #3 Bar pass in 1.203000
根据测试结果,可以看出使用try/except语句的方法更快。然而,这个结果可能稍微有些误导,因为hasattr()函数在内部使用异常来确定属性的存在。
总结起来,Python中检查成员是否存在的问题可以通过使用hasattr()函数或try/except语句来解决。根据上述测试结果,使用try/except语句的方法更快一些。但是,需要注意的是,hasattr()函数在后台使用异常来确定属性的存在,可能会导致速度稍慢。