পাইথন ক্লাসের __ রায় __.__ ডিক__ গুণাবলী কী?


92
>>> class A(object): pass
... 
>>> A.__dict__
<dictproxy object at 0x173ef30>
>>> A.__dict__.__dict__
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
AttributeError: 'dictproxy' object has no attribute '__dict__'
>>> A.__dict__.copy()
{'__dict__': <attribute '__dict__' of 'A' objects> ... }
>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects> # What is this object?

আমি যদি করি তবে A.something = 10এটি goesুকে পড়ে A.__dict__। কি হয় এই <attribute '__dict__' of 'A' objects>পাওয়া A.__dict__.__dict__, এবং যখন এটা কিছু রয়েছে?


11
আরও উপযুক্ত উদাহরণ পরিবর্তনশীল হয়েছে ive। কমপক্ষে এটি আরও একটি A.__dict__['ive']প্রশ্ন করে তুলেছে;) আমি নিজেকে দেখব
জোয়াকিম

উত্তর:


110

প্রথমত A.__dict__.__dict__পৃথক পৃথক A.__dict__['__dict__'], এবং পূর্বের অস্তিত্ব নেই। পরেরটি হচ্ছে __dict__শ্রেণীর উদাহরণগুলির মধ্যে থাকা বৈশিষ্ট্যটি। এটি একটি বর্ণনাকারী অবজেক্ট যা নির্দিষ্ট উদাহরণের জন্য বৈশিষ্ট্যের অভ্যন্তরীণ অভিধানটি ফিরিয়ে দেয়। সংক্ষেপে, __dict__কোনও বস্তুর বৈশিষ্ট্য অবজেক্টের মধ্যে সংরক্ষণ করা যায় না __dict__, সুতরাং এটি ক্লাসে সংজ্ঞায়িত বিবরণীর মাধ্যমে অ্যাক্সেস করা যায়।

এটি বুঝতে, আপনাকে বিবরণী প্রোটোকলের ডকুমেন্টেশন পড়তে হবে ।

সংক্ষিপ্ত সংস্করণ:

  1. শ্রেণীর উদাহরণের জন্য A, অ্যাক্সেস দেওয়া instance.__dict__হয় যার দ্বারা A.__dict__['__dict__']একই vars(A)['__dict__']
  2. ক্লাস এ এর ​​জন্য, অ্যাক্সেস A.__dict__সরবরাহ করা হয় type.__dict__['__dict__'](তত্ত্ব অনুসারে) যা একই vars(type)['__dict__']

দীর্ঘ সংস্করণ:

উভয় শ্রেণি এবং অবজেক্ট অ্যাট্রিবিউট অপারেটর (ক্লাস বা মেটাক্লাস এর মাধ্যমে প্রয়োগ করা হয় __getattribute__), এবং __dict__দ্বারা ব্যবহৃত বৈশিষ্ট্য / প্রোটোকলের মাধ্যমে উভয় বৈশিষ্ট্যে অ্যাক্সেস সরবরাহ করে vars(ob)

সাধারণ অবজেক্টের জন্য, __dict__অবজেক্টটি একটি পৃথক অবজেক্ট তৈরি করে dict, যা বৈশিষ্ট্যগুলি সংরক্ষণ করে এবং __getattribute__প্রথমে এটি অ্যাক্সেস করার এবং সেখান থেকে বৈশিষ্ট্যগুলি পাওয়ার চেষ্টা করে (বর্ণনামূলক প্রোটোকলটি ব্যবহার করে শ্রেণিতে বৈশিষ্ট্যটি অনুসন্ধান করার আগে এবং কল করার আগে __getattr__)। __dict__শ্রেণীর বর্ণনাকারী এই অভিধানটিতে অ্যাক্সেস প্রয়োগ করে।

  • x.nameঅনুক্রমে সেই চেষ্টা সমতূল্য: x.__dict__['name'], type(x).name.__get__(x, type(x)),type(x).name
  • x.__dict__ একই কাজ করে তবে সুস্পষ্ট কারণে প্রথমটিকে এড়িয়ে যায়

এটির জন্য অসম্ভব হিসেবে __dict__এর instanceসংরক্ষণ করার জন্য __dict__উদাহরণস্বরূপ, এটি বর্ণনাকারী প্রোটোকল মাধ্যমে সরাসরি পরিবর্তে অ্যাক্সেস করা হয়, এবং উদাহরণ হিসেবে বলা যায় একটি বিশেষ ক্ষেত্র মধ্যে সংরক্ষিত হয়।

ক্লাসগুলির জন্য একই জাতীয় দৃশ্য সত্য, যদিও __dict__এগুলি একটি বিশেষ প্রক্সি অবজেক্ট যা অভিধান হিসাবে ভান করে (তবে অভ্যন্তরীণভাবে এটি হতে পারে না), এবং আপনাকে এটি পরিবর্তন করতে বা এটি অন্য কোনওটির সাথে প্রতিস্থাপন করতে দেয় না। এই প্রক্সি আপনাকে অন্য সকলের মধ্যেও নির্দিষ্ট শ্রেণীর বৈশিষ্ট্যগুলি অ্যাক্সেস করার অনুমতি দেয় এবং এর কোনও বেসে সংজ্ঞায়িত করা হয় না।

ডিফল্টরূপে, একটি vars(cls)খালি শ্রেণীর মধ্যে তিনটি বর্ণনাকারী বহন করে - __dict__উদাহরণগুলির বৈশিষ্ট্যগুলি সংরক্ষণের জন্য, __weakref__যা অভ্যন্তরীণভাবে ব্যবহৃত হয় weakrefএবং শ্রেণীর ডক্ট্রিং। আপনি সংজ্ঞা দিলে প্রথম দুটি চলে যেতে পারে __slots__। তারপর আপনি হবে না __dict__এবং __weakref__বৈশিষ্ট্যাবলী, কিন্তু এর পরিবর্তে আপনি প্রতিটি স্লটে জন্য একটি একক বর্গ অ্যাট্রিবিউট আছে চাই। উদাহরণস্বরূপের বৈশিষ্ট্যগুলি তখন কোনও অভিধানে সংরক্ষণ করা হবে না এবং এগুলিতে অ্যাক্সেস ক্লাসে সংশ্লিষ্ট বর্ণনাকারীদের দ্বারা সরবরাহ করা হবে।


এবং সর্বশেষে, অসঙ্গতি যে A.__dict__থেকে ভিন্ন A.__dict__['__dict__']কারণ অ্যাট্রিবিউট __dict__হয়, ব্যতিক্রম দ্বারা, কখনো আপে লাগছিল vars(A), তাই কি এটা জন্য সত্য কার্যকরীভাবে অন্য কোন বৈশিষ্ট্য আপনি ব্যবহার করতে চাই জন্য সত্য নয়। উদাহরণস্বরূপ, A.__weakref__হিসাবে একই জিনিস A.__dict__['__weakref__']। যদি এই অসঙ্গতিটি না থাকে তবে ব্যবহার করা কার্যকর A.__dict__হবে না এবং vars(A)পরিবর্তে আপনাকে সর্বদা ব্যবহার করতে হবে।


6
বিস্তারিত উত্তর করার জন্য ধন্যবাদ। যদিও আমাকে এটি কয়েকবার পড়তে হয়েছিল, আমি মনে করি পাইথনের এতগুলি নতুন বিবরণ শিখার পরে অনেক সময় হয়ে গেছে।
porgarmingduod

কেন __dict__কোনও বস্তুর বৈশিষ্ট্য অবজেক্টের মধ্যে সংরক্ষণ করা যায় না __dict__?
zumgruenenbaum

4
@zumgruenenbaum যেহেতু __dict__সব উদাহরণস্বরূপ বৈশিষ্ট্যাবলী সংরক্ষণ বোঝানো হয়, ফর্মের একটি বৈশিষ্ট্য এক্সেস obj.xঅবশেষে আপ বস্তুর উপর লাগছিল হয় __dict__, যথা obj.__dict__['x']। এখন যদি __dict__কোনও বিবরণকারী হিসাবে প্রয়োগ না করা হয় তবে এটি অসীম পুনরাবৃত্তি হতে পারে, যেহেতু অ্যাক্সেস করার জন্য obj.__dict__আপনাকে এটির মতো সন্ধান করা দরকার obj.__dict__['__dict__']। বর্ণনাকারী এই সমস্যাটিকে পরিস্কার করে।
a_guest

11

যেহেতু A.__dict__একটি অভিধান সংরক্ষণ করা Aগুণাবলী, A.__dict__['__dict__']একই A.__dict__বৈশিষ্ট্যের প্রত্যক্ষ রেফারেন্স ।

A.__dict__নিজের কাছে একটি (ধরণের) উল্লেখ রয়েছে contains "ধরণের" অংশটি কেন অভিব্যক্তিটিকে একটি স্বাভাবিকের পরিবর্তে A.__dict__ফিরিয়ে দেয় ।dictproxydict

>>> class B(object):
...     "Documentation of B class"
...     pass
...
>>> B.__doc__
'Documentation of B class'
>>> B.__dict__
<dictproxy object at 0x00B83590>
>>> B.__dict__['__doc__']
'Documentation of B class'

9
A.__dict__['__dict__']একটি রেফারেন্স নয় A.__dict__। এটি __dict__উদাহরণগুলির বৈশিষ্ট্য প্রয়োগ করে । নিজের জন্য এই চেষ্টা করতে, A.__dict__['__dict__'].__get__(A(), A)গুণাবলীর ফেরৎ A(), যখন A.__dict__['__dict__'].__get__(A, type)ব্যর্থ।
রোশ অক্সিমারন

10

কিছু অন্বেষণ করতে দিন!

>>> A.__dict__['__dict__']
<attribute '__dict__' of 'A' objects>

আমি ভাবছি কি এটা?

>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>

একটি getset_descriptorবস্তুর কি বৈশিষ্ট্য রয়েছে?

>>> type(A.__dict__["__dict__"]).__dict__
<dictproxy object at 0xb7efc4ac>

যে একটি কপি করা হলে dictproxyআমরা কিছু মজার বৈশিষ্ট্য খুঁজে পেতে পারেন, বিশেষভাবে __objclass__এবং __name__

>>> A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__
(<class '__main__.A'>, '__dict__')

সুতরাং __objclass__একটি রেফারেন্স Aএবং __name__শুধুমাত্র একটি স্ট্রিং '__dict__', একটি বৈশিষ্ট্যের নাম সম্ভবত?

>>> getattr(A.__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__) == A.__dict__
True

ওখানে আমাদের আছে! A.__dict__['__dict__']এমন একটি বস্তু যা আবার উল্লেখ করতে পারে A.__dict__


পিইপি 252 বলে যে __objclass__এই শ্রেণিটি এই বৈশিষ্ট্যটিকে সংজ্ঞায়িত করে , এটি সেই শ্রেণীর কোনও বৈশিষ্ট্য নয়। এটি আপনার getattrউদাহরণকে ভুল করে তোলে । আরো সঠিক এক হতে হবেgetattr(A().__dict__['__dict__'].__objclass__, A.__dict__['__dict__'].__name__)
রশ বিরোধাভাস

4
KeyError: '__dict__'@ রোশ অক্সিমারন আপনার মন্তব্যটি @ অ্যান্ড্রু ক্লার্কের বিপরীতে উত্থাপন করেছে।
ম্যাগগিরো

9

এর আরও বুঝতে আপনি নীচের সাধারণ উদাহরণটি ব্যবহার করে দেখতে পারেন:

>>> class A(object): pass
... 
>>> a = A()
>>> type(A)
<type 'type'>
>>> type(a)
<class '__main__.A'>
>>> type(a.__dict__)
<type 'dict'>
>>> type(A.__dict__)
<type 'dictproxy'>
>>> type(type.__dict__)
<type 'dictproxy'>
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> type(type.__dict__['__dict__'])
<type 'getset_descriptor'>
>>> a.__dict__ == A.__dict__['__dict__'].__get__(a)
True
>>> A.__dict__ == type.__dict__['__dict__'].__get__(A)
True
>>> a.__dict__ == type.__dict__['__dict__'].__get__(A)['__dict__'].__get__(a)
True

উপরের উদাহরণ থেকে দেখে মনে হচ্ছে শ্রেণিবদ্ধ বস্তুর বৈশিষ্ট্যগুলি তাদের শ্রেণীর দ্বারা সংরক্ষণ করা হয়, শ্রেণীর বৈশিষ্ট্যগুলি তাদের শ্রেণীর দ্বারা সংরক্ষণ করা হয়, যা মেটাক্লাস হয়। এটি দ্বারা বৈধ:

>>> a.__dict__ == A.__getattribute__(a, '__dict__')
True
>>> A.__dict__ == type.__getattribute__(A, '__dict__')
True

4
আশ্চর্যের বিষয়, দ্বিতীয় তুলনাতে যদি isপ্রতিস্থাপন করা ==হয় A.__dict__ is type.__dict__['__dict__'].__get__(A), তবে ফলাফলটি Falseপাইথন ২.y.১৫+ এবং ৩.6.৮ উভয় ক্ষেত্রেই পাওয়া যায়।
অর্ণ ভোগেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.