在 Python 中检查成员是否存在
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/204308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking for member existence in Python
提问by PierreBdR
I regularly want to check if an object has a member or not. An example is the creation of a singleton in a function. For that purpose, you can use hasattr
like this:
我经常想检查一个对象是否有成员。一个例子是在函数中创建单例。为此,您可以hasattr
像这样使用:
class Foo(object):
@classmethod
def singleton(self):
if not hasattr(self, 'instance'):
self.instance = Foo()
return self.instance
But you can also do this:
但你也可以这样做:
class Foo(object):
@classmethod
def singleton(self):
try:
return self.instance
except AttributeError:
self.instance = Foo()
return self.instance
Is one method better of the other?
一种方法比另一种更好吗?
Edit:Added the @classmethod
... But note that the question is notabout how to make a singleton but how to check the presence of a member in an object.
编辑:添加了@classmethod
... 但请注意,问题不是关于如何制作单例,而是关于如何检查对象中成员的存在。
Edit:For that example, a typical usage would be:
编辑:对于那个例子,典型的用法是:
s = Foo.singleton()
Then s
is an object of type Foo
, the same each time. And, typically, the method is called many times.
然后s
是一个类型为 的对象,Foo
每次都相同。而且,通常,该方法会被多次调用。
采纳答案by tzot
These are two different methodologies: №1 is LBYL (look before you leap) and №2 is EAFP (easier to ask forgiveness than permission).
这是两种不同的方法:№1 是 LBYL(跳之前先看看),№2 是 EAFP(请求宽恕比许可更容易)。
Pythonistas typically suggest that EAFP is better, with arguments in style of "what if a process creates the file between the time you test for it and the time you try to create it yourself?". This argument does not apply here, but it's the general idea. Exceptions should not be treated as tooexceptional.
Pythonistas 通常建议 EAFP 更好,其论点的风格是“如果一个进程在您测试它的时间和您尝试自己创建它的时间之间创建文件怎么办?”。这个论点在这里并不适用,但它是一般的想法。异常不应被视为过于异常。
Performance-wise in your case —since setting up exception managers (the try
keyword) is very cheap in CPython while creating an exception (the raise
keyword and internal exception creation) is what is relatively expensive— using method №2 the exception would be raised only once; afterwards, you just use the property.
在您的情况下,性能方面 - 因为在 CPython 中设置异常管理器(try
关键字)非常便宜,而创建异常(raise
关键字和内部异常创建)是相对昂贵的 - 使用方法 №2,异常只会引发一次; 之后,您只需使用该属性。
回答by Andrea Ambu
I just tried to measure times:
我只是试图测量时间:
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
On my machine:
在我的机器上:
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
It seems that try/except is faster. It seems also more readable to me, anyway depends on the case, this test was very simple maybe you'd need a more complex one.
似乎 try/except 更快。它对我来说似乎也更具可读性,无论如何取决于具体情况,这个测试非常简单,也许您需要一个更复杂的测试。
回答by Chris Jester-Young
It depends on which case is "typical", because exceptions should model, well, atypical conditions. So, if the typical case is that the instance
attribute should exist, then use the second code style. If not having instance
is as typical as having instance
, then use the first style.
这取决于哪种情况是“典型的”,因为异常应该模拟非典型情况。因此,如果典型情况是该instance
属性应该存在,则使用第二种代码样式。如果不具有instance
与具有一样典型instance
,则使用第一种样式。
In the specific case of creating a singleton, I'm inclined to go with the first style, because creating a singleton the initial time is a typical use case. :-)
在创建单例的特定情况下,我倾向于采用第一种风格,因为在初始时间创建单例是一个典型的用例。:-)
回答by gx.
A little off-topic in the way of using it. Singletons are overrated, and a "shared-state" method is as effective, and mostly, very clean in python, for example:
使用它的方式有点偏离主题。单例被高估了,“共享状态”方法在 python 中同样有效,而且大多数情况下非常干净,例如:
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
# and whatever else you want in your class -- that's all!
Now every time you do:
现在每次你这样做:
obj = Borg()
it will have the same information, or, be somewhat the same instance.
它将具有相同的信息,或者在某种程度上是相同的实例。
回答by Brian
I have to agree with Chris. Remember, don't optimize until you actually need to do so. I really doubt checking for existence is going to be a bottleneck in any reasonable program.
我必须同意克里斯。请记住,在您确实需要这样做之前不要进行优化。我真的怀疑检查存在是否会成为任何合理程序的瓶颈。
I did see http://code.activestate.com/recipes/52558/as a way to do this, too. Uncommented copy of that code ("spam" is just a random method the class interface has):
我确实看到http://code.activestate.com/recipes/52558/也是这样做的一种方式。该代码的未注释副本(“垃圾邮件”只是类接口具有的随机方法):
class Singleton:
class __impl:
def spam(self):
return id(self)
__instance = None
def __init__(self):
if Singleton.__instance is None:
Singleton.__instance = Singleton.__impl()
self.__dict__['_Singleton__instance'] = Singleton.__instance
def __getattr__(self, attr):
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
return setattr(self.__instance, attr, value)