파이썬에서 회원 존재 확인
-
03-07-2019 - |
문제
객체에 멤버가 있는지 정기적으로 확인하고 싶습니다. 예를 들어 함수에서 싱글 톤을 만드는 것입니다. 그 목적을 위해 사용할 수 있습니다 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
, 매번 동일합니다. 그리고 일반적 으로이 방법을 여러 번이라고합니다.
해결책
이것들은 두 가지 다른 방법론입니다.
Pythonistas는 일반적으로 EAFP가 더 좋다고 제안합니다. 이 주장은 여기에는 적용되지 않지만 일반적인 아이디어입니다. 예외는 다음과 같이 취급되어서는 안됩니다 ~도 특별한.
귀하의 경우 성능 측면-예외 관리자를 설정하는 경우 ( try
키워드)는 예외를 생성하면서 Cpython에서 매우 저렴합니다 ( raise
키워드 및 내부 예외 생성))는 비교적 비싸다. 그 후에는 속성을 사용합니다.
다른 팁
방금 시간을 측정하려고 노력했습니다.
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
, 그런 다음 첫 번째 스타일을 사용하십시오.
싱글 톤을 만드는 특정 사례에서는 첫 번째 스타일을 사용하는 경향이 있습니다. 싱글 톤을 만드는 것은 일반적인 사용 사례이기 때문입니다. :-)
그것을 사용하는 방식에 약간의 주제. 싱글 톤은 과대 평가되며 "공유 상태"방법은 예를 들어 파이썬에서 효과적이며 대부분 매우 깨끗합니다.
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
# and whatever else you want in your class -- that's all!
이제마다 당신이 할 때마다 :
obj = Borg()
정보가 동일한 정보를 가지고 있거나 다소 동일한 인스턴스가됩니다.
크리스와 동의해야합니다. 실제로 그렇게해야 할 때까지 최적화하지 마십시오. 나는 존재하는 것이 합리적인 프로그램에서 병목 현상이 될 것이라고 정말로 의심합니다.
나는 보았다 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)