سؤال

عندما تتصل ب object.__repr__() الطريقة في بايثون تحصل على شيء مثل هذا مرة أخرى:

<__main__.Test object at 0x2aba1c0cf890> 

هل هناك أي طريقة للحصول على عنوان الذاكرة في حالة التحميل الزائد __repr__(), ، أخرى ثم الاتصال super(Class, obj).__repr__() وإعادة صياغة ذلك؟

هل كانت مفيدة؟

المحلول

ال دليل بايثون لديه هذا ليقوله عنه id():

إرجاع "هوية" الكائن.هذا عدد صحيح (أو عدد صحيح طويل) مضمون ليكون فريدًا وثابتًا لهذا الكائن خلال حياته.قد يكون للكائنات ذات العمر غير المتداخل نفس قيمة المعرف ().(ملاحظة التنفيذ:هذا هو عنوان الكائن.)

لذلك في CPython، سيكون هذا هو عنوان الكائن.ومع ذلك، لا يوجد مثل هذا الضمان لأي مترجم بايثون آخر.

لاحظ أنه إذا كنت تكتب ملحق C، فلديك حق الوصول الكامل إلى الأجزاء الداخلية لمترجم Python، بما في ذلك الوصول إلى عناوين الكائنات مباشرة.

نصائح أخرى

يمكنك إعادة تنفيذ التكرار الافتراضي بهذه الطريقة:

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

مجرد استخدام

id(object)

هناك بعض المشكلات هنا التي لم يتم تناولها في أي من الإجابات الأخرى.

أولاً، id يعود فقط:

"هوية" الكائن.هذا عدد صحيح (أو عدد صحيح طويل) والذي يضمن أن يكون فريدًا وثابتًا لهذا الكائن خلال حياته.قد يكون لكائنين لهما عمر غير متداخل نفس الشيء id() قيمة.


في CPython، يكون هذا هو المؤشر إلى ملف PyObject الذي يمثل الكائن في المترجم، وهو نفس الشيء object.__repr__ يعرض.ولكن هذا مجرد تفاصيل تنفيذ لـ CPython، وليس شيئًا ينطبق على Python بشكل عام.لا تتعامل Jython مع المؤشرات، بل تتعامل في مراجع Java (والتي ربما يمثلها JVM بالطبع كمؤشرات، لكن لا يمكنك رؤيتها - ولن ترغب في ذلك، لأنه يُسمح لـ GC بتحريكها).يتيح PyPy للأنواع المختلفة الحصول على أنواع مختلفة من id, ، ولكن الأكثر عمومية هو مجرد فهرس في جدول الكائنات التي قمت باستدعائها id on، والذي من الواضح أنه لن يكون مؤشرًا.لست متأكدًا من IronPython، لكنني أظن أنه يشبه Jython أكثر من CPython في هذا الصدد.لذلك، في معظم تطبيقات بايثون، لا توجد طريقة للحصول على ما يظهر في ذلك 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 تأخذ الوظائف مؤشرًا إلى a PyObject أو نوع ذي صلة.بالنسبة لتلك الأنواع ذات الصلة، يمكنك فقط الاتصال PyFoo_Check للتأكد من أنه حقا Foo كائن، ثم يلقي مع (PyFoo *)p.لذلك، إذا كنت تكتب ملحق C، فإن id هو بالضبط ما تحتاجه.

ماذا لو كنت تكتب كود بايثون خالصًا؟يمكنك استدعاء نفس الوظائف بالضبط مع pythonapi من ctypes.


وأخيرا، تم طرح عدد قليل من الإجابات الأخرى ctypes.addressof.هذا ليس له صلة هنا.هذا يعمل فقط ل ctypes كائنات مثل c_int32 (وربما بعض الكائنات التي تشبه المخزن المؤقت للذاكرة، مثل تلك التي يوفرها numpy).وحتى هناك، فإنه لا يعطيك عنوان c_int32 القيمة، إنها تمنحك عنوان المستوى C int32 أن c_int32 يختتم.

ومع ذلك، في أغلب الأحيان، إذا كنت تعتقد حقًا أنك بحاجة إلى عنوان شيء ما، فأنت لم تكن تريد كائن Python أصليًا في المقام الأول، بل أردت ctypes هدف.

فقط ردًا على تورستن، لم أتمكن من الاتصال به 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

مع com.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
  • مؤشرات الذاكرة هي فكرة صالحة.

يحرر:إضافة معلومات حول استقلال المترجم لأنواع ctypes

يمكنك الحصول على شيء مناسب لهذا الغرض من خلال:

id(self)

في حين أن هذا صحيح id(object) يحصل على عنوان الكائن في تطبيق CPython الافتراضي، وهذا غير مفيد بشكل عام...لا يمكنك يفعل أي شيء يحمل عنوانًا من كود Python الخالص.

المرة الوحيدة التي ستتمكن فيها فعليًا من استخدام العنوان هي من مكتبة ملحق C...في هذه الحالة، يكون الحصول على عنوان الكائن أمرًا تافهًا نظرًا لأن كائنات Python يتم تمريرها دائمًا كمؤشرات C.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top