অবজেক্ট মেমরি ঠিকানা প্রবেশ করা


168

object.__repr__()পাইথনে আপনি যখন পদ্ধতিটি কল করবেন তখন আপনি এই রকম কিছু পাবেন:

<__main__.Test object at 0x2aba1c0cf890> 

যদি আপনি ওভারলোড করেন __repr__(), অন্যটি কল করে super(Class, obj).__repr__()এবং এটি পুনরায় বের করেন তবে মেমরি ঠিকানাটি ধরে রাখার কোনও উপায় আছে কি ?

উত্তর:


208

পাইথন ম্যানুয়াল এই সম্পর্কে বলার আছে id():

কোনও সামগ্রীর "পরিচয়" "ফিরিয়ে দিন This এটি একটি পূর্ণসংখ্যা (বা দীর্ঘ পূর্ণসংখ্যা) যা তার জীবদ্দশায় এই অবজেক্টটির জন্য অনন্য এবং ধ্রুবক হওয়ার নিশ্চয়তাযুক্ত- (বাস্তবায়ন দ্রষ্টব্য: এটি বস্তুর ঠিকানা))

সিপিথনে তাই এটিতে বস্তুর ঠিকানা হবে। যদিও অন্য কোনও পাইথন ইন্টারপ্রেটারের পক্ষে এরকম কোনও গ্যারান্টি নেই।

মনে রাখবেন যে আপনি যদি কোনও সি এক্সটেনশন লিখছেন, তবে পাইথন ইন্টারপ্রেটারের অভ্যন্তরীণগুলিতে সরাসরি অবজেক্টের ঠিকানায় অ্যাক্সেস সহ আপনার সম্পূর্ণ অ্যাক্সেস রয়েছে।


7
এটি প্রশ্নের সর্বজনীন উত্তর নয় ; এটি কেবল সিপিথনের ক্ষেত্রে প্রযোজ্য।
ডিলিথিয়ামম্যাট্রিক্স

5
স্বরে নোট করুন: গ্যারান্টিটি মাল্টিপ্রসেসিংয়ের জন্য প্রযোজ্য নয়
রুফাস

1
এটি ব্যবহারের কিছু উপায় (এতে থাকা মানের তুলনা করার জন্য): ফোরাম.ফ্রেইকোডেক্যাম্প
জে

এই প্রসঙ্গে কোন বস্তুর lifetime(এবং আজীবন এর অর্থ কী overlap/not overlap) বোঝায়?
মিন ট্রান

4
@ মিনিট্রান কারণ আইডি হ'ল অবজেক্টের মেমরি ঠিকানা, এটি প্রক্রিয়াটির মধ্যে অনন্যরূপে গ্যারান্টিযুক্ত এবং অবজেক্টের অস্তিত্ব থাকাকালীন। বস্তুর আবর্জনা সংগ্রহের কিছু সময় পরে মেমরিটি পুনরায় ব্যবহার করা যেতে পারে। একটি ওভারল্যাপিং নয় এমন আজীবন বোঝানো উচিত যখন নতুন অবজেক্টটি তৈরি করা হবে তখন মূল অবজেক্টটি আর থাকবে না। সুতরাং এই সীমাবদ্ধতার অর্থ আপনি সংরক্ষণের জন্য, এটিকে মুক্ত করতে এবং পরে পুনরায় ইনস্টল করার জন্য কোনও আইটেমের একটি হ্যাশ তৈরি করতে নিরাপদে আইডি () ব্যবহার করতে পারবেন না।
জোশুয়া ক্লেটন

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)
এটির

2
@ আর্টিয়ার: এই প্রশ্নের মূল প্রশ্নের সাথে কী সম্পর্ক আছে? এখানে পোস্ট করা উত্তরটি মূল প্রশ্নের অনুরোধ অনুসারে ঠিকানাটি পুনরায় তৈরি করছে। আপনি যদি পরামর্শ মতো করেন তবে তা কি আপনাকে ম্যাংলে স্ট্রিং করতে হবে না?
রাফে

1
এটি আমার কাছে সেরা উত্তর বলে মনে হচ্ছে। কেবলমাত্র একটি বস্তু তৈরি করার চেষ্টা করুন () এটি মুদ্রণ করুন, তারপরে হেক্স (আইডি (অবজেক্ট)) এবং ফলাফলগুলি মুদ্রণ করুন
রাফ

@ রাফা আপনার উত্তরটি দীর্ঘায়িত করার পদ্ধতি __repr__ = object.__repr__এবং এটি প্রায় বোকা প্রমাণ নয়, কারণ বিভিন্ন পরিস্থিতিতে এমনটি দেখা যায় যেখানে এটি কাজ করে না, যেমন একটি ওভাররাইড __getattribute__বা একটি সিপিথন বাস্তবায়ন যেখানে আইডি নেই স্মৃতি অবস্থান। এটি জেড-ফিলও করে না, সুতরাং সিস্টেমটি 64 বিট হলে আপনাকে কাজ করতে হবে এবং প্রয়োজনীয়ভাবে শূন্যগুলি যুক্ত করতে হবে।
আর্টিয়ার

@ আর্টিয়ার: আমার উদাহরণটি দেখায় যে কীভাবে একটি পুনর্নির্মাণ করা যায়। আমরা প্রায়শই কাস্টম তথ্য যুক্ত করি (এবং আমি বলব এটি ভাল কোডিং অনুশীলন হিসাবে এটি ডিবাগিংয়ে সহায়তা করে)। আমরা এই স্টাইলটি ভারীভাবে ব্যবহার করি এবং আমি আপনার প্রান্তের ক্ষেত্রে কখনও অংশ নিতে পারি না। তাদের ভাগ করে নেওয়ার জন্য ধন্যবাদ!
রাফ


24

এখানে কয়েকটি সমস্যা রয়েছে যা অন্য কোনও উত্তর দ্বারা আবৃত নয়।

প্রথমত, idকেবল ফেরত:

একটি বস্তুর "পরিচয়"। এটি একটি পূর্ণসংখ্যা (বা দীর্ঘ পূর্ণসংখ্যা) যা তার জীবদ্দশায় এই বিষয়টির জন্য অনন্য এবং ধ্রুবক হওয়ার গ্যারান্টিযুক্ত। না-ওভারল্যাপিং লাইফটাইমযুক্ত দুটি বস্তুর একই id()মান থাকতে পারে ।


সিপিথনে, এটি হ'ল পয়েন্টারটি PyObjectহ'ল যা দোভাষীগুলিতে বস্তুর প্রতিনিধিত্ব করে, যা একই জিনিসটি object.__repr__প্রদর্শিত হয়। তবে এটি কেবলমাত্র পাইথনের বাস্তবায়ন বিশদ, সাধারণভাবে পাইথনের সত্য নয় something জাইথন ​​পয়েন্টারগুলিতে ডিল করে না, এটি জাভা রেফারেন্সগুলিতে ডিল করে (যা অবশ্যই জেভিএম সম্ভবত পয়েন্টার হিসাবে উপস্থাপন করে, তবে আপনি সেগুলি দেখতে পারবেন না এবং চান না, কারণ জিসি তাদের চারপাশে স্থানান্তরিত করার অনুমতি দেয়)। পিপিআই বিভিন্ন ধরণের বিভিন্ন ধরণের অনুমতি দেয় idতবে সর্বাধিক সাধারণ কেবল আপনি যে বস্তুর ডেকে পাঠিয়েছেন তার একটি সারণীতে সূচকidচালু, যা স্পষ্টতই একটি পয়েন্টার হতে যাচ্ছে না। আমি আয়রন পাইথন সম্পর্কে নিশ্চিত নই, তবে আমি সন্দেহ করি এটি এ ক্ষেত্রে সিপিথনের মতো জাইথনের মতো। সুতরাং, বেশিরভাগ পাইথন বাস্তবায়নে, যা প্রদর্শিত হয়েছিল তা পাওয়ার কোনও উপায় reprনেই এবং আপনি যদি তা করেন তবে কোনও ব্যবহার নেই।


তবে আপনি যদি কেবল সিপিথনকেই যত্নবান করেন? এটি সর্বোপরি একটি সাধারণ ঘটনা।

ঠিক আছে, প্রথমে, আপনি লক্ষ্য করতে পারেন যে idএটি একটি পূর্ণসংখ্যা; * যদি আপনি 0x2aba1c0cf890সংখ্যার পরিবর্তে সেই স্ট্রিংটি চান তবে আপনাকে 46978822895760এটি নিজেই ফর্ম্যাট করতে হবে। প্রচ্ছদের অধীনে, আমি বিশ্বাস করি object.__repr__শেষ পর্যন্ত printfএর %pফর্ম্যাটটি ব্যবহার করা হচ্ছে , যা পাইথন থেকে আপনার নেই ... তবে আপনি সর্বদা এটি করতে পারেন:

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

* 3.x এ, এটি একটি int। ২.x এ, এটি intপয়েন্টার ধরে রাখার মতো যথেষ্ট বড় যদি এটি হয় - এটি কোনও প্ল্যাটফর্মের সাইনড নম্বর ইস্যু এবং longঅন্য কোনও কারণে নয়।

এই পয়েন্টারগুলি মুদ্রণ করার পাশাপাশি আপনি কি কিছু করতে পারেন? অবশ্যই (আবার, ধরে নিচ্ছেন আপনি কেবল সিপিথন সম্পর্কে যত্নশীল)।

সি এপিআইয়ের সমস্ত ফাংশন একটি PyObjectবা কোনও সম্পর্কিত ধরণের কাছে একটি পয়েন্টার নেয় । সম্পর্কিত সম্পর্কিত ধরণের জন্য, আপনি কেবল PyFoo_Checkএটি সত্যই কোনও Fooবস্তু কিনা তা নিশ্চিত করতে কল করতে পারেন , তারপরে কাস্ট করুন (PyFoo *)p। সুতরাং, আপনি যদি একটি সি এক্সটেনশন লিখছেন তবে idআপনার যা প্রয়োজন তা হ'ল।

আপনি যদি খাঁটি পাইথন কোড লিখছেন? আপনি ঠিক একই ফাংশন pythonapiথেকে কল করতে পারেন ctypes


অবশেষে, অন্যান্য উত্তর কয়েকটি নিয়ে এসেছে ctypes.addressof। এটি এখানে প্রাসঙ্গিক নয়। এটি কেবলমাত্র জন্য কাজ করে ctypesমত বস্তু c_int32(এবং হয়ত কয়েক মেমরি বাফার মত বস্তু, দ্বারা উপলব্ধ মতো numpy)। এবং এমনকি সেখানেও, এটি আপনাকে c_int32মানটির ঠিকানা দিচ্ছে না , এটি আপনাকে সি-লেভেলের ঠিকানা দিচ্ছে int32যা c_int32মোড়ানো।

বলা হচ্ছে, প্রায়শই বলা যায় না, যদি আপনি সত্যিই মনে করেন যে আপনার কোনও কিছুর ঠিকানা প্রয়োজন, আপনি প্রথমে নেটিভ পাইথন অবজেক্টটি চান না, আপনি একটি ctypesবস্তু চেয়েছিলেন ।


ভাল পরিচয় জরুরী যখন মানচিত্র / সেটে পরিবর্তনযোগ্য বস্তু সংরক্ষণ করার একমাত্র উপায় ...
এনারসিসিও

@ এনারসিসিও id- seenসেট বা cacheডিকের পরিবর্তে পরিবর্তনীয় মান ধরে রাখতে তাদের ব্যবহার সহ অন্যান্য ব্যবহারগুলি - idপয়েন্টার হওয়ার কোনও উপায়ের উপর নির্ভর করে না, বা কোনওভাবেই সম্পর্কিত নয় repr। ঠিক এই কারণেই এই জাতীয় কোডটি কেবল সিপিথনে কাজ করার পরিবর্তে সমস্ত পাইথন বাস্তবায়নে কাজ করে।
abarnert

হ্যাঁ, আমি idএটির জন্য ব্যবহার করেছি, তবে আমার অর্থ এখনও জাভাতেও আপনি অবজেক্টের ঠিকানা পেতে পারেন, অদ্ভুত বলে মনে হচ্ছে (সি) পাইথনের কোনও উপায় নেই কারণ যেটির আসলে স্থিতিশীল জিসি রয়েছে যা বস্তুগুলিকে সরবে না সুতরাং ঠিকানা একই থাকে address
এনারসিসিও

@ এনারসিসিও তবে আপনি কোনও ক্যাশেবল মানের জন্য কোনও সামগ্রীর ঠিকানা ব্যবহার করতে চান না — আপনি কোনও বস্তুর জন্য এটি ব্যবহার করতে চান id, এটি ঠিকানা হোক বা না হোক। উদাহরণস্বরূপ, পাইপাইতে সিপিথনের idকী হিসাবে এখনও দরকারী, যদিও এটি সাধারণত বাস্তবায়নের কোনও গোপন টেবিলের জন্য একটি সূচক হয় তবে একটি পয়েন্টারটি অকেজো হয়ে যায়, কারণ (জাভার মতো) বস্তুটি সরানো যেতে পারে স্মৃতি.
অবার্নেট

@Enerccio যাই হোক, সেখানে হয় একটি উপায় CPython একটি পয়েন্টার জন্য। উত্তরে বর্ণিত হিসাবে, সিপিথন স্পষ্টভাবে ডকুমেন্টস, একটি বাস্তবায়ন-নির্দিষ্ট বিশদ হিসাবে, যে idকোনও বস্তুর মেমরির মধ্যে বস্তুর অবস্থানের নির্দেশক। সুতরাং, সিপিথন-নির্দিষ্ট কোডে যদি আপনার পয়েন্টার ভ্যালু (যা আপনি প্রায়শই করেন না, যেমনটি উত্তরেও ব্যাখ্যা করা হয়েছে) এর জন্য আপনার কোনও ব্যবহার থাকে, তবে এটি ডকুমেন্টেড এবং কাজের গ্যারান্টিযুক্ত এটি পাওয়ার একটি উপায় রয়েছে।
অবার্নেট

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
সি উদাহরণ অভ্যন্তরীণ বাফারের ঠিকানাটি ফিরিয়ে দিন

নোট করুন সিপিথনে, বর্তমানে id(a) == ctypes.addressof(a), তবে ctypes.addressofপ্রতিটি পাইথন বাস্তবায়নের জন্য আসল ঠিকানাটি ফেরত দেওয়া উচিত, যদি

  • সিটাইপস সমর্থিত
  • মেমরি পয়েন্টার একটি বৈধ ধারণা।

সম্পাদনা করুন : টাইপগুলির দোভাষী-স্বাধীনতার সম্পর্কে তথ্য যুক্ত করা হয়েছে


13
>>> সিটিপস আমদানি করুন >>> a = (1,2,3) >>> ctypes.addressof (a) ট্রেসব্যাক (সর্বশেষতম কলটি শেষ): ফাইল "<ইনপুট>", লাইন 1, <মডুল> টাইপ এরর: অবৈধ >>> আইডি (ক) 4493268872 >>>

5
আমি ব্যারি সহ সম্মতি জানাই: উপরের কোডগুলি ফলাফল TypeError: invalid typeযখন আমি পাইথন ৩.৪ দিয়ে চেষ্টা করি তখন ফলাফল হয় ।
ব্র্যান্ডন রোডস


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যদি না স্ট্যান্ডার্ড লাইব্রেরিতে বিল্ট-ইন টুলকিট ব্যবহার না করেন। সেক্ষেত্রে আপনি ঠিকানা দিয়ে সমস্ত ধরণের কাজ করতে পারেন :)
ব্র্যান্ডন রোডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.