답변:
파이썬 매뉴얼 에 대해 할 말이이있다 id()
:
객체의 "정체성"을 반환합니다. 이는 수명 동안이 객체에 대해 고유하고 일정하게 보장되는 정수 (또는 긴 정수)입니다. (구현 정보 : 이것은 객체의 주소입니다.)
CPython에서는 이것이 객체의 주소가 될 것입니다. 그러나 다른 파이썬 인터프리터에 대해서는 그러한 보장이 없습니다.
C 확장을 작성하는 경우 객체 주소에 직접 액세스하는 것을 포함하여 Python 인터프리터의 내부에 대한 모든 액세스 권한이 있습니다.
lifetime
의미는 무엇입니까 (그리고 일생 동안 의미하는 것은 무엇 overlap/not overlap
입니까)?
이 방법으로 기본 repr을 다시 구현할 수 있습니다.
def __repr__(self):
return '<%s.%s object at %s>' % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self))
)
return object.__repr__(self)
object.__repr__(obj)
__repr__ = object.__repr__
, 이것이 작동하지 않는 다양한 상황이 있기 때문에 거의 바보 같은 증거 __getattribute__
는 아닙니다. 메모리 위치 또한 z 채우기가 없으므로 시스템이 64 비트인지 확인하고 필요에 따라 0을 추가해야합니다.
그냥 사용
id(object)
id()
@JLT
여기에 다른 답변으로는 다루지 않는 몇 가지 문제가 있습니다.
먼저 다음 id
만 반환합니다.
객체의 "정체성". 이것은 수명 동안이 개체에 대해 고유하고 일정하게 보장되는 정수 (또는 긴 정수)입니다. 겹치지 않는 수명을 가진 두 개체의
id()
값 이 동일 할 수 있습니다 .
CPython에서 이것은 PyObject
인터프리터의 객체를 나타내는 포인터에 대한 포인터 이며 이는 object.__repr__
표시 되는 것과 동일 합니다. 그러나 이것은 CPython의 구현 세부 사항 일뿐, 일반적으로 Python에서는 사실이 아닙니다. 자이 썬은 포인터를 다루지 않고 자바 참조를 처리한다 (물론 JVM은 포인터로 표현할 수 있지만 GC는 포인터를 움직일 수 있기 때문에 원하지 않는다). PyPy는 서로 다른 유형이 서로 다른 종류를 가질 수 id
있지만 가장 일반적인 것은 호출 한 객체 테이블에 대한 색인 일뿐입니다id
on, 이것은 분명히 포인터가 될 수 없습니다. IronPython에 대해서는 잘 모르겠지만 CPython과 비교하여 Jython과 더 비슷하다고 생각합니다. 따라서 대부분의 Python 구현에서는 그 안에 표시된 것을 얻을 수있는 방법이 repr
없으며 사용하지 않으면 사용할 수 없습니다.
그러나 CPython에만 관심이 있다면 어떨까요? 결국 꽤 일반적인 경우입니다.
먼저, 그것이 id
정수라는 것을 알 수 있습니다 . * 0x2aba1c0cf890
숫자 대신 해당 문자열 을 원한다면 46978822895760
직접 형식을 지정해야합니다. 덮개 아래에서 object.__repr__
궁극적으로 printf
의 %p
형식을 사용하고 있다고 생각합니다. 이 형식은 Python에는 없지만 ... 항상 이렇게 할 수 있습니다.
format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')
* 3.x에서는 int
입니다. 2.x에서는 int
포인터를 잡기에 충분할 정도로 큰 경우입니다. 이는 일부 플랫폼의 부호있는 숫자 문제가 아닐 수도 있습니다 long
.
인쇄하는 것 외에이 포인터로 할 수있는 일이 있습니까? 물론 (CPython에만 관심이 있다고 가정).
모든 C API 함수 PyObject
는 관련 유형 또는 관련 유형에 대한 포인터를 사용합니다 . 이러한 관련 유형의 경우 호출 PyFoo_Check
하여 그것이 실제로 Foo
객체 인지 확인한 다음로 캐스팅 할 수 (PyFoo *)p
있습니다. 따라서 C 확장을 작성하는 경우 id
꼭 필요한 것입니다.
순수한 파이썬 코드를 작성한다면 어떨까요? pythonapi
from 와 동일한 함수를 호출 할 수 있습니다 ctypes
.
마지막으로, 다른 답변들 중 몇 가지가 나타났습니다 ctypes.addressof
. 여기에는 관련이 없습니다. 이것은 ctypes
같은 객체 c_int32
(및 아마도 제공하는 것과 같은 메모리 버퍼와 같은 객체) 에서만 작동합니다 numpy
. 그리고, 심지어 거기, 당신에게의 주소를 제공하지 않는 c_int32
당신에게 C 레벨의 주소를주고, 값이 int32
(가) 것을 c_int32
래핑합니다.
사실, 무언가의 주소가 필요하다고 생각되면 처음에는 네이티브 Python 객체를 원하지 않았고 객체를 원했습니다 ctypes
.
id
에서 변경 가능한 값을 유지하기 위해 그것들을 사용하는 것을 포함하여 , 다른 용도 는 포인터가되는 것에 의존 하거나 어떤 식 으로든 관련되지 않습니다 . 이것이 바로 그러한 코드가 CPython에서만 작동하는 대신 모든 Python 구현에서 작동하는 이유입니다. seen
cache
id
repr
id
했지만, 여전히 자바에서도 객체의 주소를 얻을 수 있다는 것을 의미한다. (C) Python에는 이상한 방법으로 보이지 않는다. 왜냐하면 실제로 객체를 움직이지 않는 안정적인 gc를 가지고 있기 때문에 주소는 동일하게 유지되기 때문이다.
id
않습니다. 주소에 관계없이 객체 를 사용하려고합니다 . 예를 들어 PyPy id
에서 CPython의 키만큼 유용하지만 일반적으로 구현에서 숨겨진 테이블에 대한 인덱스 일 뿐이지 만 (Java와 같이) 객체를 이동할 수 있기 때문에 포인터가 쓸모가 없습니다. 기억.
id
으로 객체의 객체가 메모리에서 객체의 위치에 대한 포인터 임을 명시 적으로 문서화 합니다. 따라서 CPython 특정 코드에서 포인터 값 (응답에 설명 된 것처럼 거의 수행하지 않는)을 사용하는 경우 문서화되고 작동하도록 보장하는 방법이 있습니다.
Torsten에 대한 응답으로 addressof()
일반 파이썬 객체 를 호출 할 수 없었습니다 . 또한 id(a) != addressof(a)
. 이것은 CPython에 있으며 다른 것에 대해서는 모른다.
>>> from ctypes import c_int, addressof
>>> a = 69
>>> addressof(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: invalid type
>>> b = c_int(69)
>>> addressof(b)
4300673472
>>> id(b)
4300673392
ctypes을 사용 하면 같은 것을 얻을 수 있습니다.
>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L
선적 서류 비치:
addressof(C instance) -> integer
C 인스턴스 내부 버퍼의 주소를 반환
CPython에서는 현재 id(a) == ctypes.addressof(a)
이지만 ctypes.addressof
각 Python 구현에 대한 실제 주소를 반환해야합니다.
편집 : ctypes의 인터프리터 독립성에 대한 정보 추가
TypeError: invalid type
는 Python 3.4로 시도 할 때 발생합니다.
나는 이것이 오래된 질문이라는 것을 알고 있지만 요즘 파이썬 3에서 프로그래밍하고 있다면 실제로 문자열 인 경우 실제로 이것을 수행하는 쉬운 방법이 있다는 것을 알았습니다.
>>> spam.upper
<built-in method upper of str object at 0x1042e4830>
>>> spam.upper()
'YO I NEED HELP!'
>>> id(spam)
4365109296
문자열 변환은 메모리의 위치에 영향을 미치지 않습니다.
>>> spam = {437 : 'passphrase'}
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
>>> str(spam)
"{437: 'passphrase'}"
>>> object.__repr__(spam)
'<dict object at 0x1043313f0>'
id(object)
기본 CPython 구현에서 객체의 주소 를 얻는 것이 사실이지만 , 이것은 일반적으로 쓸모가 없습니다 . 순수한 파이썬 코드의 주소로 는 아무것도 할 수 없습니다 .
실제로 주소를 사용할 수있는 유일한 시간은 C 확장 라이브러리에서 온 것입니다.이 경우 Python 객체는 항상 C 포인터로 전달되므로 객체의 주소를 얻는 것이 쉽지 않습니다.
ctypes
표준 라이브러리에서 내장 툴킷 을 사용하지 않는 한 . 어떤 경우에 당신은 주소로 모든 종류의 일을 할 수 있습니다 :)