在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
类型的一个对象,每次都是一样的。 而且,通常这种方法会被多次调用。
这些是两种不同的方法:№1是LBYL(看你跳跃之前)和№2是EAFP(比许可更容易要求原谅)。
Pythonistas通常建议EAFP更好,参数的风格是“如果一个进程在测试它的时间和你自己创建它的时间之间创建文件会怎样?”。 这个论点在这里不适用,但它是一般的想法。 例外情况不应被视为例外。
在你的情况下性能明智 - 因为设置异常管理器( try
关键字)在CPython中非常便宜,而创建异常( raise
关键字和内部异常创建)是相对昂贵的 - 使用方法№2将会引发异常只有一次; 之后,您只需使用该属性。
我只是想测量时间:
class Foo(object):
@classmethod
def singleton(self):
if not hasattr(self, 'instance'):
self.instance = Foo()
return self.instance
class Bar(object):
@classmethod
def singleton(self):
try:
return self.instance
except AttributeError:
self.instance = Bar()
return self.instance
from time import time
n = 1000000
foo = [Foo() for i in xrange(0,n)]
bar = [Bar() for i in xrange(0,n)]
print "Objs created."
print
for times in xrange(1,4):
t = time()
for d in foo: d.singleton()
print "#%d Foo pass in %f" % (times, time()-t)
t = time()
for d in bar: d.singleton()
print "#%d Bar pass in %f" % (times, time()-t)
print
在我的机器上:
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
似乎尝试/除了更快。 这对我来说似乎也更易读,无论如何取决于案例,这个测试非常简单,也许你需要更复杂的测试。
这取决于哪种情况是“典型的”,因为例外应该模拟非典型的情况。 因此,如果典型情况是instance
属性应该存在,那么使用第二种代码风格。 如果没有instance
像有instance
一样典型,则使用第一种方式。
在创建单例的具体情况中,我倾向于采用第一种方式,因为创建单例初始时间是典型的用例。 :-)
链接地址: http://www.djcxy.com/p/4919.html