एक्सेस करने वाली ऑब्जेक्ट मेमोरी एड्रेस


168

जब तुम बुलाओगे object.__repr__() पाइथन में विधि आपको कुछ इस तरह मिलता है:

<__main__.Test object at 0x2aba1c0cf890> 

क्या मेमोरी एड्रेस की पकड़ पाने का कोई तरीका है यदि आप ओवरलोड करते हैं __repr__(), तो अन्य कॉलिंगsuper(Class, obj).__repr__() करके उसे लोड करना है?

जवाबों:


208

अजगर के मैनुअल इस बारे में क्या कहना है id():

किसी ऑब्जेक्ट की "पहचान" लौटाएं। यह एक पूर्णांक (या लंबा पूर्णांक) है जो इस वस्तु के लिए अपने जीवनकाल के दौरान अद्वितीय और स्थिर रहने की गारंटी है। गैर-अतिव्यापी जीवनकाल वाली दो वस्तुओं का एक ही आईडी () मान हो सकता है। (कार्यान्वयन नोट: यह ऑब्जेक्ट का पता है।)

तो सीपीथॉन में, यह ऑब्जेक्ट का पता होगा। हालांकि किसी भी अन्य पायथन दुभाषिया के लिए ऐसी कोई गारंटी नहीं है।

ध्यान दें कि यदि आप C एक्सटेंशन लिख रहे हैं, तो आपके पास सीधे वस्तुओं के पते तक पहुंच सहित पायथन दुभाषिया के आंतरिक तक पूर्ण पहुंच है।


7
यह सवाल का एक सार्वभौमिक जवाब नहीं है; यह केवल सीपीथॉन पर लागू होता है।
Dil लिथियमMatrix

5
स्वयं पर ध्यान दें: गारंटी मल्टीप्रोसेसिंग पर लागू नहीं होती है
रूफस

1
इसे इस्तेमाल करने के कुछ तरीके (इसमें मौजूद मूल्य की तुलना करने के लिए): forum.freecodecamp.com/t/python-id-object/19207
J. करता है

इस संदर्भ में किसी वस्तु का lifetimeक्या (और जीवनकाल के लिए क्या मतलब है overlap/not overlap) इसका संदर्भ देता है?
मिन्ह ट्रान

4
@MinhTran क्योंकि आईडी ऑब्जेक्ट का मेमोरी एड्रेस है, यह प्रक्रिया के भीतर अद्वितीय की गारंटी है, और जबकि ऑब्जेक्ट मौजूद है। कुछ समय के बाद वस्तु कचरा इकट्ठा हो जाने पर मेमोरी का पुन: उपयोग किया जा सकता है। एक गैर अतिव्यापी जीवनकाल का मतलब होगा कि जब नई वस्तु बनाई जाती है तो मूल वस्तु मौजूद नहीं होती है। तो इस सीमा का मतलब है कि आप सुरक्षित रूप से आईडी का उपयोग नहीं कर सकते हैं (किसी वस्तु का हैश बनाने के लिए इसे बंद कर सकते हैं, इसे मुफ़्त कर सकते हैं और बाद में इसे पुनः स्थापित कर सकते हैं।
जोशुआ क्लेटन

71

आप इस तरह से डिफ़ॉल्ट पुन: लागू कर सकते हैं:

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

1
मुझे पता है कि यह पुराना है, लेकिन आप एक नया वर्ग बनाने के बजाय जब भी आपको इसकी आवश्यकता होती return object.__repr__(self)है, object.__repr__(obj)तब भी आप सिर्फ या केवल कर सकते हैं
19

2
@ ऑयरर: इस टिप्पणी का मूल प्रश्न से क्या लेना-देना है? यहां पोस्ट किया गया उत्तर मूल प्रश्न के अनुरोध के अनुसार पते को फिर से बना रहा है। यदि आप जिस तरह से यह सुझाव देते हैं, क्या आपको स्ट्रिंग मैनिंग नहीं करना होगा?
राफ

1
यह मुझे सबसे अच्छा जवाब लगता है। बस एक ऑब्जेक्ट () बनाने की कोशिश करें, इसे प्रिंट करें, फिर हेक्स (आईडी (ऑब्जेक्ट)) प्रिंट करें और परिणाम मिलान करें
Rafe

@ आपका जवाब देने का एक लंबा घुमावदार तरीका है __repr__ = object.__repr__, और लगभग मूर्ख प्रमाण के रूप में नहीं है, क्योंकि ऐसी स्थितियों की एक किस्म है जहाँ यह काम नहीं करता है, उदाहरण के लिए एक overrided __getattribute__या एक गैर- CPython कार्यान्वयन जहां आईडी नहीं है स्मृति स्थान। यह z-fill भी नहीं करता है, इसलिए आपको यह काम करना होगा यदि सिस्टम 64bit है और आवश्यकतानुसार शून्य जोड़ दें।
अर्टिअर

@Artyer: मेरे उदाहरण से पता चलता है कि रीप का निर्माण कैसे किया जाता है। हम अक्सर कस्टम जानकारी जोड़ते हैं (और मैं कहूंगा कि यह अच्छा कोडिंग अभ्यास है क्योंकि यह डिबगिंग में सहायता करता है)। हम इस शैली का भारी उपयोग करते हैं और मैं आपके किनारे के मामलों में कभी नहीं चला हूं। उन्हें साझा करने के लिए धन्यवाद!
राफेल


24

यहाँ कुछ मुद्दे हैं जो किसी भी अन्य उत्तर द्वारा कवर नहीं किए गए हैं।

सबसे पहले, idकेवल रिटर्न:

किसी वस्तु की "पहचान"। यह एक पूर्णांक (या लंबा पूर्णांक) है जो अपने जीवनकाल के दौरान इस वस्तु के लिए अद्वितीय और स्थिर रहने की गारंटी है। गैर-अतिव्यापी जीवनकाल वाली दो वस्तुओं का समान id()मूल्य हो सकता है ।


CPython में, यह सूचक के लिए होता है जो PyObjectकि दुभाषिया में वस्तु का प्रतिनिधित्व करता है, जो कि वही वस्तु है , जो स्पष्ट रूप से एक सूचक नहीं बनने जा रही है। मुझे आयरनपाइथन के बारे में निश्चित नहीं है, लेकिन मुझे संदेह है कि इस संबंध में सीपीथॉन की तुलना में यह ज्येथोन की तरह अधिक है। इसलिए, अधिकांश पायथन कार्यान्वयन में, जो कुछ भी दिखाया गया है उसे पाने का कोई तरीका नहीं है , और यदि आपने किया तो कोई फायदा नहीं है।object.__repr__ प्रदर्शित करता है। लेकिन यह केवल CPython का कार्यान्वयन विवरण है, न कि कुछ ऐसा जो सामान्य रूप से अजगर का सच है। Jython पॉइंटर्स में डील नहीं करता है, यह Java रेफरेंस में डील करता है (जो कि बेशक JVM पॉइंटर्स के रूप में प्रतिनिधित्व करता है, लेकिन आप उन लोगों को नहीं देख सकते - और नहीं चाहेंगे, क्योंकि जीसी को उन्हें स्थानांतरित करने की अनुमति है)। PyPy विभिन्न प्रकारों को अलग-अलग प्रकार की अनुमति देता है id, लेकिन सबसे सामान्य वस्तुओं की एक तालिका है जिसे आपने कहा हैidrepr


लेकिन क्या होगा यदि आप केवल सीपीथॉन के बारे में परवाह करते हैं? यह एक बहुत ही आम मामला है, सब के बाद।

ठीक है, पहले, आप देख सकते हैं कि idपूर्णांक है; * यदि आप 0x2aba1c0cf890संख्या के बजाय उस स्ट्रिंग को चाहते हैं 46978822895760, तो आपको इसे स्वयं प्रारूपित करना होगा। कवर के तहत, मेरा मानना है कि object.__repr__अंत में उपयोग कर रहा है printfके %pप्रारूप है, जो आप अजगर से नहीं है ... लेकिन आप हमेशा ऐसा कर सकते हैं:

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

* 3.x में, यह एक है int। 2.x में, यह एक ऐसा है जो intएक पॉइंटर को पकड़ने के लिए काफी बड़ा है - जो कि कुछ प्लेटफार्मों पर हस्ताक्षरित संख्या के मुद्दों के कारण नहीं हो सकता है- और longअन्यथा।

वहाँ कुछ भी आप इन संकेत के साथ कर सकते हैं इसके अलावा उन्हें बाहर प्रिंट? ज़रूर (फिर से, आप केवल सीपीथॉन के बारे में ध्यान रखते हैं)।

C API फ़ंक्शन के सभी एक PyObjectया एक संबंधित प्रकार के लिए एक पॉइंटर लेते हैं । उन संबंधित प्रकारों के लिए, आप बस PyFoo_Checkयह सुनिश्चित करने के लिए कॉल कर सकते हैं कि यह वास्तव में एक Fooऑब्जेक्ट है, फिर के साथ कास्ट करें (PyFoo *)p। इसलिए, यदि आप C एक्सटेंशन लिख रहे हैं, तो idठीक वही है जो आपको चाहिए।

क्या होगा अगर आप शुद्ध पायथन कोड लिख रहे हैं? आप के साथ ठीक उसी कार्यों कॉल कर सकते हैं pythonapiसे ctypes


अंत में, कुछ अन्य उत्तर सामने आए हैं ctypes.addressof। यह यहाँ प्रासंगिक नहीं है। यह केवल ctypesवस्तुओं के लिए काम करता है जैसे c_int32(और शायद कुछ मेमोरी-बफर जैसी वस्तुएं, जैसे प्रदान की गई numpy)। और, वहां भी, यह आपको c_int32मूल्य का पता नहीं दे रहा है , यह आपको सी-लेवल का पता दे रहा है int32जो कि c_int32लपेटता है।

यह कहा जा रहा है, अधिक बार नहीं, यदि आप वास्तव में सोचते हैं कि आपको किसी चीज़ के पते की आवश्यकता है, तो आप पहली जगह में एक देशी अजगर वस्तु नहीं चाहते थे, आप एक ctypesवस्तु चाहते थे ।


अच्छी तरह से यह एक ही तरीका है कि जब पहचान महत्वपूर्ण हो, तो नक्शों / सेटों में उत्परिवर्तित वस्तुओं को संग्रहीत करने के लिए ...
Enerccio

@Enerccio idएक seenसेट या एक निश्चित में परस्पर मूल्यों को धारण करने के लिए उन्हें उपयोग करने के अन्य उपयोग - एक सूचक होने cacheपर किसी भी तरह से निर्भर नहीं करता है id, या किसी भी तरह से संबंधित है repr। ठीक यही कारण है कि इस तरह के कोड सभी पायथन कार्यान्वयन में काम करते हैं, बजाय केवल सीपीथॉन में काम करने के।
बजे

हाँ, मैं इसके idलिए इस्तेमाल किया , लेकिन मेरा मतलब है कि अभी भी जावा में आप ऑब्जेक्ट का पता प्राप्त कर सकते हैं, अजीब लगता है कि (सी) पायथन में कोई रास्ता नहीं है क्योंकि एक वास्तव में स्थिर जीसी है जो वस्तुओं को स्थानांतरित नहीं करेगा इस प्रकार पता वही रहता है
Enerccio

@Enerccio लेकिन आप किसी ऑब्जेक्ट के पते का उपयोग करने योग्य मान के लिए नहीं करना चाहते हैं - आप किसी ऑब्जेक्ट के लिए ऑब्जेक्ट का उपयोग करना चाहते हैं id, चाहे वह पता हो या नहीं। उदाहरण के लिए, PyPy में, idअभी भी CPython में एक कुंजी के रूप में उपयोगी है, भले ही यह आमतौर पर कार्यान्वयन में कुछ छिपी हुई तालिका में एक सूचकांक है, लेकिन एक संकेतक बेकार होगा, क्योंकि (जावा की तरह) ऑब्जेक्ट को अंदर ले जाया जा सकता है स्मृति।
अबर्नेट

@Enerccio वैसे भी, CPython में एक पॉइंटर प्राप्त करने का एक तरीका है। जैसा कि उत्तर में बताया गया है, CPython ने स्पष्ट रूप से दस्तावेज़ों में, कार्यान्वयन-विशिष्ट विवरण के रूप में, कि idऑब्जेक्ट का मेमोरी में ऑब्जेक्ट के स्थान का सूचक है। तो, यदि आपके पास पॉइंटर मूल्य के लिए कोई उपयोग है (जो आप लगभग कभी नहीं करते हैं, जैसा कि उत्तर में भी बताया गया है) सीपीथॉन-विशिष्ट कोड में, इसे प्राप्त करने का एक तरीका है जो दस्तावेज और काम की गारंटी है।
abarnert

13

टॉर्स्टन के जवाब में, मैं addressof()एक नियमित अजगर वस्तु पर कॉल करने में सक्षम नहीं था । इसके अलावा, id(a) != addressof(a)। यह सीपीथॉन में है, किसी और चीज के बारे में नहीं जानते।

>>> 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

4

Ctypes के साथ , आप उसी चीज़ को प्राप्त कर सकते हैं

>>> import ctypes
>>> a = (1,2,3)
>>> ctypes.addressof(a)
3077760748L

प्रलेखन:

addressof(C instance) -> integer
C आवृत्ति आंतरिक बफ़र का पता लौटाएँ

ध्यान दें कि वर्तमान में सीपीथॉन में id(a) == ctypes.addressof(a), लेकिन ctypes.addressofप्रत्येक पायथन कार्यान्वयन के लिए वास्तविक पता वापस करना चाहिए, यदि

  • ctypes समर्थित है
  • मेमोरी पॉइंटर्स एक मान्य धारणा है।

संपादित करें : ctypes की दुभाषिया-स्वतंत्रता के बारे में जानकारी जोड़ी गई


13
>>> आयात ctypes >>> a = (1,2,3) >>> ctypes.addressof (a) ट्रेसबैक (सबसे हालिया कॉल अंतिम): फ़ाइल "<input>", लाइन 1, में <मॉड्यूल> टाइप करें: अमान्य प्रकार >>> आईडी (ए) 4493268872 >>>

5
मैं बैरी के साथ सहमत हूं: उपरोक्त कोड TypeError: invalid typeजब मैं पायथन 3.4 के साथ प्रयास करता हूं तो परिणाम होता है।
ब्रैंडन रोड्स


1

मुझे पता है कि यह एक पुराना सवाल है, लेकिन अगर आप अभी भी प्रोग्रामिंग में हैं, तो इन दिनों अजगर 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>'

0

हालांकि यह सच है कि id(object)डिफ़ॉल्ट CPython कार्यान्वयन में वस्तु का पता हो जाता है, यह आम तौर पर बेकार है ... तुम नहीं कर सकते कर शुद्ध अजगर कोड से पता के साथ कुछ भी।

केवल उस समय जब आप वास्तव में पते का उपयोग करने में सक्षम होंगे, एक सी एक्सटेंशन लाइब्रेरी से है ... इस मामले में ऑब्जेक्ट का पता प्राप्त करना तुच्छ है क्योंकि पायथन ऑब्जेक्ट्स को हमेशा सी पॉइंटर्स के रूप में चारों ओर से पारित किया जाता है।


1
जब तक आप ctypesमानक लाइब्रेरी में अंतर्निहित टूलकिट का उपयोग नहीं करते हैं । जिस स्थिति में आप पते के साथ सभी प्रकार की चीजें कर सकते हैं :)
ब्रैंडन रोड्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.