programing

오브젝트 메모리주소에의 액세스

itsource 2022. 9. 28. 23:35
반응형

오브젝트 메모리주소에의 액세스

를 호출할 때object.__repr__()Python의 method는 다음과 같은 결과를 얻을 수 있습니다.

<__main__.Test object at 0x2aba1c0cf890> 

과부하 시 메모리 주소를 얻을 수 있는 방법이 있습니까?__repr__(), 발신 이외의super(Class, obj).__repr__()다시 gexing해서 빼는거야?

Python 매뉴얼에는 다음과 같은 내용이 있습니다.id():

개체의 "아이덴티티"를 반환합니다.이것은 이 오브젝트의 라이프 타임 동안 한결같고 일정함을 보증하는 정수(또는 긴 정수)오버랩되지 않는 수명을 가진 두 개체의 id() 값이 같을 수 있습니다.(실장 메모: 오브젝트의 주소입니다.)

따라서 CPython에서는 이것이 객체의 주소가 됩니다.단, 다른 Python 인터프리터에는 그러한 보증이 없습니다.

C 확장자를 쓰는 경우, Python 인터프리터의 내부에는 오브젝트의 주소에 직접 액세스 하는 것을 포함해 완전한 액세스권이 있습니다.

다음과 같이 기본 repr을 재실장할 수 있습니다.

def __repr__(self):
    return '<%s.%s object at %s>' % (
        self.__class__.__module__,
        self.__class__.__name__,
        hex(id(self))
    )

그냥 사용하다

id(object)

다른 답변에서는 다루지 않는 문제가 몇 가지 있습니다.

첫째, 반환만:

사물의 '변형'이것은 이 오브젝트의 라이프 타임 동안 한결같고 일정함을 보증하는 정수(또는 긴 정수)수명이 겹치지 않는 두 개체의 수명이 같을 수 있습니다.id()가치.


CPython에서는 인터프리터 내의 오브젝트를 나타내는에 대한 포인터가 됩니다.이것은 같은 것입니다.object.__repr__표시된다.그러나 이것은 CPython의 구현 세부 사항일 뿐 일반적인 Python에는 해당되지 않습니다.Jython은 포인터를 취급하지 않고 Java 레퍼런스를 취급한다(JVM은 물론 포인터로 나타낼 수 있지만 GC가 그것들을 이동할 수 있기 때문에 볼 수 없고, 보고 싶지 않을 것이다).PyPy는 다양한 타입을 가지고 있습니다.id그러나 가장 일반적인 것은 호출한 오브젝트 테이블의 인덱스일 뿐입니다.id이건 분명히 포인터가 되지 않을 거예요IronPython에 대해서는 확실하지 않지만, 이 점에 있어서는 CPython이라기보다는 Jython에 가깝다고 생각합니다.따라서 대부분의 Python 구현에서는 그 안에 있는 것을 얻을 수 있는 방법이 없습니다.repr해도 소용없다.


하지만 만약 당신이 CPython에만 관심이 있다면?어쨌든 그건 꽤 흔한 경우야.

음, 먼저, 당신은 알아차릴 수 있습니다.id원하는 경우 정수입니다.*0x2aba1c0cf890숫자 대신 문자열46978822895760직접 포맷해야 합니다.이불 속에서, 내 생각엔object.__repr__궁극적으로는 사용하고 있다printf%pPython에는 없는 포맷입니다만, 이것을 항상 실행할 수 있습니다.

format(id(spam), '#010x' if sys.maxsize.bit_length() <= 32 else '#18x')

* 3.x 에서는,int2.x 에서는,int포인터를 유지할 수 있을 정도의 크기라면(일부 플랫폼에서는 서명된 번호의 문제가 원인이 아닐 수 있음)long그렇지않으면.

출력하는 것 외에 이 포인트로 할 수 있는 것이 있습니까?물론입니다(다시 말씀드리지만, CPython에만 관심이 있다고 가정합니다).

모든 C API 함수는 Pointer를 사용하여PyObject또는 관련 유형입니다.이러한 관련 유형은 전화만 주시면 됩니다.PyFoo_Check확실히 하기 위해서Foo오브젝트, 다음으로 캐스팅(PyFoo *)pC 확장자를 쓰고 있다면id바로 네게 필요한 거야

만약 당신이 순수한 파이썬 코드를 쓰고 있다면?에서와 같은 함수를 호출할 수 있습니다.ctypes.


마지막으로, 몇 가지 다른 답변이 제기되었습니다.그건 여기서 관련이 없어요.이것은 다음 시간에만 유효합니다.ctypes같은 물건c_int32(또한 메모리 메모리 같은 오브젝트도 몇 개 있을 수 있습니다.numpy게다가 거기에 있어도, 그 주소의 주소는 표시되지 않습니다.c_int32C-level의 주소를 제공합니다.int32그거는c_int32마무리.

말하자면, 대부분의 경우, 만약 당신이 정말로 무언가의 주소가 필요하다고 생각한다면, 당신은 애초에 네이티브 Python 오브젝트를 원하지 않았다.ctypes물건.

토르스텐에 대한 답변으로는,addressof()일반적인 python 오브젝트.더 나아가,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

이러한 목적에 적합한 것을 입수할 수 있는 것은, 다음과 같습니다.

id(self)

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 구현의 실제 주소를 반환해야 합니다.

  • ctype이 지원됩니다.
  • 메모리 포인터는 유효한 개념입니다.

편집: ctype의 인터프리터에 대한 정보를 추가했습니다.

오래된 질문인 건 알지만 요즘도 파이썬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>'

내장str'' 유형의 '파티션' 메서드를 사용하면 개체의 메모리 주소/장소를 얻을 수 있습니다.

다음으로 오브젝트의 메모리주소를 취득하기 위해서 사용하는 예를 나타냅니다.

Python 3.8.3 (default, May 27 2020, 02:08:17)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> object.__repr__(1)
'<int object at 0x7ca70923f0>'
>>> hex(int(object.__repr__(1).partition('object at ')[2].strip('>'), 16))
0x7ca70923f0
>>>

여기에서는 빌트인을 사용하고 있습니다.object'class'__repr__다음과 같은 오브젝트/아이템이 있는 메서드1문자열을 반환하기 위한 인수로서 그 문자열을 분할하고 있습니다.이 문자열은 내가 지정한 문자열 앞에, 내가 지정한 문자열 뒤에, 그리고 내가 지정한 문자열 뒤에, 메모리 위치가 ' 뒤에 위치할 때 반환됩니다.object at「메모리 주소는, 그 부분으로부터 분할되어 있기 때문에 취득할 수 있습니다.

그리고 메모리 주소가 반환된 튜플의 세 번째 항목으로 반환되었기 때문에 인덱스로 액세스할 수 있습니다.2태플에서.그런데 제가 받은 문자열의 접미사로 오른쪽 각 괄호가 들어가 있어서 '를 사용합니다.strip'는 각 괄호 없이 반환되는 기능을 합니다.그런 다음 결과 문자열을 밑수가 16인 정수로 변환한 다음 16진수로 변환했습니다.

는 사실이지만id(object)기본 CPython 구현에서 객체의 주소를 가져옵니다. 이것은 일반적으로 쓸모가 없습니다.순수한 Python 코드의 주소로는 아무것도 할 수 없습니다.

주소를 실제로 사용할 수 있는 것은 C 확장 라이브러리의 경우뿐입니다.이 경우 Python 객체는 항상 C 포인터로 전달되기 때문에 객체의 주소를 얻는 것은 간단하다.

이 경우,__repr__과부하가 되어 있습니다.__str__변수의 메모리주소를 표시합니다.

다음으로 StackOverflow에서의 Moshe Zadka에 의한 대에 대한 자세한 내용을 나타냅니다.

언급URL : https://stackoverflow.com/questions/121396/accessing-object-memory-address

반응형