개체 클래스의 속성을 설정할 수 없습니다.
그래서 저는 이 질문에 답하는 동안 파이썬을 가지고 놀았는데 이것이 유효하지 않다는 것을 발견했습니다.
o = object()
o.attr = 'hello'
때문에 AttributeError: 'object' object has no attribute 'attr'
. 그러나 객체에서 상속 된 모든 클래스는 유효합니다.
class Sub(object):
pass
s = Sub()
s.attr = 'hello'
인쇄시 s.attr
예상대로 'hello'가 표시됩니다. 왜 그렇습니까? 파이썬 언어 사양에서 바닐라 객체에 속성을 할당 할 수 없다고 지정하는 것은 무엇입니까?
임의의 속성 할당을 지원하려면 __dict__
객체에 임의의 속성을 저장할 수있는 객체와 관련된 dict가 필요합니다 . 그렇지 않으면 새 속성 을 넣을 곳이 없습니다 .
의 인스턴스는 object
않습니다 하지 주위 나른다 __dict__
- 그것은 한 경우, 끔찍한 순환 의존 문제 (전 이후 dict
, 대부분의 다른 모든 같은에서 상속 object
,이 안장 것이다 ;-) 모든 오버 헤드를 의미하는하는 DICT 파이썬의 객체를 의 많은 현재 가지고 또는 딕셔너리를 필요로하지 않는 개체 당 바이트 (기본적으로,이없는 모든 개체를 임의로 할당 속성이 있거나 딕셔너리 필요하지 않습니다).
예를 들어, 훌륭한 pympler
프로젝트 ( 여기 에서 svn을 통해 얻을 수 있음)를 사용하여 몇 가지 측정을 수행 할 수 있습니다 ... :
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
모든 int
것이 16 바이트 대신 144 바이트를 차지하는 것을 원하지 않습니까?-)
이제 클래스를 만들면 (무엇이든 상 속됨) 상황이 변경됩니다 ... :
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
...가 __dict__
되어 지금 추가 (플러스, 조금 더 오버 헤드) - 소위 dint
인스턴스가 임의의 속성을 가질 수있다, 그러나 당신은 그 유연성을 꽤 공간 비용을 지불해야합니다.
그래서 당신이 하나의 추가 속성으로 int
s 를 원한다면 어떻게 될까요? 드물게 필요하지만 Python은 목적을위한 특별한 메커니즘을 제공합니다.foobar
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
...하지 꽤 같은 작은으로 int
당신을 마음! (또는 두 개의 int
, 하나 self
와 하나는 self.foobar
다시 할당 될 수 있음),하지만 확실히 dint
.
클래스는이 때 __slots__
특별한 속성 (문자열의 순서), 다음 class
문 (더 정확하게, 기본 메타 클래스를 type
않습니다) 하지 와 그 클래스의 모든 인스턴스를 장착 __dict__
(임의의 속성을 가지고 있으므로 능력), 단지 유한를 , 주어진 이름을 가진 엄격한 "슬롯"세트 (기본적으로 각 객체에 대한 하나의 참조를 보유 할 수있는 장소).
유연성을 잃어버린 대가로 인스턴스 당 많은 바이트를 얻습니다 (아마도 수많은 인스턴스가 질주하는 경우에만 의미가 있지만 그에 대한 사용 사례 가 있습니다).
다른 답변자들이 말했듯 object
이에는 __dict__
. 또는을 포함한 모든 유형 object
의 기본 클래스입니다 . 따라서 제공되는 것이 무엇이든 그들에게도 부담이 될 것입니다. 선택 사항 처럼 단순한 것조차도 각 값에 대한 추가 포인터가 필요합니다. 이것은 매우 제한된 유틸리티를 위해 시스템의 각 개체에 대해 추가 4-8 바이트의 메모리를 낭비하게됩니다.int
str
object
__dict__
더미 클래스의 인스턴스를 수행하는 대신 Python 3.3 이상에서 types.SimpleNamespace
이를 사용할 수 있습니다 .
단순히 최적화 때문입니다.
사전은 비교적 큽니다.
>>> import sys
>>> sys.getsizeof((lambda:1).__dict__)
140
C로 정의 된 대부분의 (아마 모든) 클래스에는 최적화를위한 사전이 없습니다.
If you look at the source code you will see that there are many checks to see if the object has a dict or not.
So, investigating my own question, I discovered this about the Python language: you can inherit from things like int, and you see the same behaviour:
>>> class MyInt(int):
pass
>>> x = MyInt()
>>> print x
0
>>> x.hello = 4
>>> print x.hello
4
>>> x = x + 1
>>> print x
1
>>> print x.hello
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: 'int' object has no attribute 'hello'
I assume the error at the end is because the add function returns an int, so I'd have to override functions like __add__
and such in order to retain my custom attributes. But this all now makes sense to me (I think), when I think of "object" like "int".
It's because object is a "type", not a class. In general, all classes that are defined in C extensions (like all the built in datatypes, and stuff like numpy arrays) do not allow addition of arbitrary attributes.
This is (IMO) one of the fundamental limitations with Python - you can't re-open classes. I believe the actual problem, though, is caused by the fact that classes implemented in C can't be modified at runtime... subclasses can, but not the base classes.
참고URL : https://stackoverflow.com/questions/1529002/cant-set-attributes-of-object-class
'Development Tip' 카테고리의 다른 글
JavaScript에 해당하는 C # String.Format ()이 있습니까? (0) | 2020.10.16 |
---|---|
웹 서비스의 URL에서 wsdl 파일을 가져 오는 방법 (0) | 2020.10.16 |
텍스트 편집을 위해 왼쪽 및 오른쪽 화살표 키의 속도를 높이는 방법은 무엇입니까? (0) | 2020.10.16 |
Line break (like ) using only css (0) | 2020.10.16 |
IDE 용 매직 (_call 및 _callStatic) 메서드를 문서화하는 방법 (0) | 2020.10.16 |