2012-03-10 7 views
13

이 같은 상황을 피하기 위해 기원과 속성의 생성을 피 :이 보이는 동안파이썬 객체 - 알 수없는 이름

class StrictObject(object): 
    def __setattr__(self, item, value): 
     if item in dir(self): 
      object.__setattr__(self, item, value) 
     else: 
      raise AttributeError("Attribute " + item + " does not exist.") 

:

>>> class Point: 
x = 0 
y = 0 
>>> a = Point() 
>>> a.X = 4 #whoops, typo creates new attribute capital x 

는 내가 슈퍼 클래스로 사용되는 다음과 같은 객체를 생성 , 파이썬 documentation says of dir()를 해결하려면 다음

참고 :을하기 때문에은 주로 대화 형 프롬프트에서 사용하기 편리하도록 제공되며 엄격하게 정의되거나 일관되게 정의 된 이름 집합을 제공하기보다는 흥미로운 이름 집합을 제공하려고 시도하며 자세한 동작은 릴리스간에 변경 될 수 있습니다. 예를 들어, 인수가 클래스 인 경우 메타 클래스 속성은 결과 목록에 없습니다.

개체에 특성이 있는지 확인하는 더 좋은 방법이 있습니까?

답변

16

훨씬 더 좋은 방법입니다.

가장 일반적인 방법은 "모두 동의하는 성인입니다"입니다. 즉, 검사를하지 않고 사용자에게 맡깁니다. 코드를 검사 할 때 코드의 유연성이 떨어집니다.

당신이 정말로 이렇게 할 경우에, 거기에 파이썬 3.x를 기본적으로 __slots__, 그리고 새로운 스타일의 파이썬 2.x에서의 클래스 : 기본적으로

, 모두 세의 인스턴스와 새로운 스타일의 클래스에는 속성 저장을위한 사전이 있습니다. 이는 인스턴스 변수가 거의없는 객체의 공간을 낭비합니다. 공간 소비는 많은 수의 인스턴스를 만들 때 심각해질 수 있습니다.

새 스타일 클래스 정의에 __slots__을 정의하면 기본값을 재정의 할 수 있습니다. __slots__ 선언은 일련의 인스턴스 변수를 사용하고 각 인스턴스에 각 변수에 대한 값을 보유하기에 충분한 공간을 예약합니다. 각 인스턴스에 대해 __dict__이 생성되지 않으므로 공간이 절약됩니다.

__dict__ 변수가 없으면 __slots__ 정의에 나열되지 않은 새 변수를 인스턴스에 할당 할 수 없습니다. 나열되지 않은 변수 이름에 할당하려는 시도는 AttributeError이됩니다. 새로운 변수의 동적 할당이 필요한 경우 선언의 문자열 시퀀스에 '__dict__'을 추가하십시오. 예를 들어

:

class Point(object): 
    __slots__ = ("x", "y") 

point = Point() 
point.x = 5 # OK 
point.y = 1 # OK 
point.X = 4 # AttributeError is raised 

그리고 마지막으로, 적절한 방법은 객체가 dir를 사용하지 않는 특정 속성이 있는지 확인하기 위해,하지만 내장 함수 hasattr(object, name)을 사용합니다.

+0

'__slots__ '은 내부 최적화도 허용하는 것으로 보입니다. –

+0

'__slots__'에 대한 또 다른 깔끔한 사용 – smci

2

이러한 오류를 방지하는 코드를 작성하는 것은 좋지 않다고 생각합니다. 이러한 "정적"검사는 IDE의 작업이어야합니다. Pylint__init__ 외부의 속성 할당에 대해 경고하여 오타를 방지합니다. 또한 많은 다른 문제와 잠재적 인 문제를 보여 주며 PyDev에서 쉽게 사용할 수 있습니다.

+0

+1 Pylint에 대한 유용한 정보. –

2

그런 상황에서 파이썬 표준 라이브러리가 제공 할 수있는 것을 찾아야합니다. 명명 된 튜플을 고려 했습니까?

from collections import namedtuple 

Point = namedtuple("Point", "x, y") 

a = Point(1,3) 

print a.x, a.y 

포인트가 이제는 변경 될 수 없기 때문에 문제가 발생하지 않을 수 있지만 드로우 백은 당연합니다. a에 +1을 추가하기 만하지만 완전히 새로운 인스턴스를 만들어야합니다.

+0

+1 유용한 정보 : namedtuple에 대해 알지 못했습니다. –

관련 문제