আমি পাইথনের বর্ণনাকারী কী এবং সেগুলি কীভাবে কার্যকর হতে পারে তা বোঝার চেষ্টা করছি।
বর্ণনাকারী হ'ল নিম্নলিখিত বিশেষ পদ্ধতির সাথে শ্রেণীর বৈশিষ্ট্যগুলি (যেমন বৈশিষ্ট্য বা পদ্ধতিগুলি):
__get__ (অ-ডেটা বর্ণনাকারী পদ্ধতি, উদাহরণস্বরূপ কোনও পদ্ধতি / ফাংশনে)
__set__ (ডেটা বর্ণনাকারী পদ্ধতি, উদাহরণস্বরূপ কোনও সম্পত্তি উদাহরণে)
__delete__ (তথ্য বিবরণী পদ্ধতি)
এই বর্ণনাকারী অবজেক্টগুলিকে অন্যান্য অবজেক্ট শ্রেণির সংজ্ঞা হিসাবে অ্যাট্রিবিউট হিসাবে ব্যবহার করা যেতে পারে। ( __dict__এটি ক্লাস অবজেক্টের মধ্যে থাকে।
ডেস্ক্রিপ্টর অবজেক্টগুলি বিন্দুযুক্ত অনুসন্ধানের ফলাফলগুলি (যেমন foo.descriptor) একটি সাধারণ অভিব্যক্তি, একটি অ্যাসাইনমেন্ট এবং এমনকি একটি মুছে ফেলার ক্ষেত্রে প্রোগ্রামিয়ালি পরিচালনা করতে ব্যবহার করা যেতে পারে ।
কার্যাবলী / পদ্ধতি, আবদ্ধ পদ্ধতি, property, classmethod, এবং staticmethodসব ব্যবহারের নিয়ন্ত্রণের এই বিশেষ পদ্ধতি কিভাবে তারা ডটেড লুকআপ মাধ্যমে অ্যাক্সেস করা হয়।
একটি ডেটা বর্ণনাকারী , পছন্দproperty , বস্তুর একটি সহজ রাষ্ট্র উপর ভিত্তি করে গুণাবলীর অলস নিরীক্ষার জন্য অনুমতি দিতে পারেন, দৃষ্টান্ত চেয়ে যদি আপনি প্রতিটি সম্ভাব্য অ্যাট্রিবিউট precomputed কম মেমরি ব্যবহার করতে সক্ষম হবেন।
আরেকটি তথ্য বর্ণনাকারী, একটি member_descriptor, দ্বারা নির্মিত __slots__, একটি চপল ডেটা সংরক্ষণ করার বর্গ অনুমতি দিয়ে মেমরির সঞ্চয়ী অনুমতি tuple মত পরিবর্তে datastructure নমনীয় কিন্তু স্থান সাপেক্ষ __dict__।
অ-ডেটা বর্ণনাকারী, সাধারণত উদাহরণস্বরূপ, শ্রেণি এবং স্থির পদ্ধতিগুলি তাদের অ-ডেটা বর্ণনাকারী পদ্ধতি থেকে তাদের অন্তর্নিহিত প্রথম যুক্তি (সাধারণত নাম clsএবং selfযথাক্রমে) পান __get__।
পাইথনের বেশিরভাগ ব্যবহারকারীর কেবলমাত্র সাধারণ ব্যবহার শিখতে হবে, এবং আরও বিবরণীর প্রয়োগ আরও শিখতে বা বুঝতে হবে না।
গভীরতায়: বর্ণনাকারী কী?
বর্ণনাকারী হ'ল নীচের যে কোনও পদ্ধতি ( __get__,, __set__বা __delete__) যুক্ত একটি বস্তু যা বিন্দু-অনুসন্ধানের মাধ্যমে ব্যবহার করা হবে যেন এটি কোনও উদাহরণের বৈশিষ্ট্য। মালিক-অবজেক্টের জন্য, obj_instanceকোনও descriptorবস্তু সহ:
obj_instance.descriptor
descriptor.__get__(self, obj_instance, owner_class)একটি প্রত্যাবর্তন আহ্বান value
এইভাবে সমস্ত পদ্ধতি এবং getকোনও সম্পত্তি কাজ করে।
obj_instance.descriptor = valueপূজা
descriptor.__set__(self, obj_instance, value)ফিরে None
এই জন্যে কত setterএকটি সম্পত্তি উপর কাজ করে।
del obj_instance.descriptorপূজা
descriptor.__delete__(self, obj_instance)ফিরে None
এই জন্যে কত deleterএকটি সম্পত্তি উপর কাজ করে।
obj_instanceযার ক্লাসে বর্ণনাকারী অবজেক্টের উদাহরণ রয়েছে class বর্ণনাকারীরself উদাহরণ (সম্ভবত বর্গের জন্য কেবল একটিobj_instance )
কোড সহ এটি সংজ্ঞায়িত করতে, কোনও বস্তু হ'ল বর্ণনাকারী যদি এর বৈশিষ্ট্যগুলির সেটটি কোনও প্রয়োজনীয় বৈশিষ্ট্যের সাথে ছেদ করে:
def has_descriptor_attrs(obj):
return set(['__get__', '__set__', '__delete__']).intersection(dir(obj))
def is_descriptor(obj):
"""obj can be instance of descriptor or the descriptor class"""
return bool(has_descriptor_attrs(obj))
একটি ডেটা বর্ণনাকারী টি __set__এবং / অথবা __delete__।
একটি অ-ডেটা-বর্ণনাকারীর নেই __set__এবং নেই __delete__।
def has_data_descriptor_attrs(obj):
return set(['__set__', '__delete__']) & set(dir(obj))
def is_data_descriptor(obj):
return bool(has_data_descriptor_attrs(obj))
বিল্টিন বর্ণনাকারী অবজেক্টের উদাহরণ:
classmethod
staticmethod
property
- সাধারণভাবে ফাংশন
অ-ডেটা বর্ণনাকারী
আমরা এটি দেখতে পারি classmethodএবং staticmethodঅ-ডেটা-বর্ণনাকারী:
>>> is_descriptor(classmethod), is_data_descriptor(classmethod)
(True, False)
>>> is_descriptor(staticmethod), is_data_descriptor(staticmethod)
(True, False)
উভয়েরই কেবল __get__পদ্ধতি রয়েছে:
>>> has_descriptor_attrs(classmethod), has_descriptor_attrs(staticmethod)
(set(['__get__']), set(['__get__']))
নোট করুন যে সমস্ত ফাংশন হ'ল নন-ডেটা-বর্ণনাকারী:
>>> def foo(): pass
...
>>> is_descriptor(foo), is_data_descriptor(foo)
(True, False)
ডেটা বর্ণনাকারী, property
তবে, propertyএটি একটি ডেটা-বর্ণনাকারী:
>>> is_data_descriptor(property)
True
>>> has_descriptor_attrs(property)
set(['__set__', '__get__', '__delete__'])
ডটেড লুকআপ অর্ডার
এই গুরুত্বপূর্ণ প্রভেদ , তারা বিন্দু যুক্ত লুকআপ জন্য লুকআপ অর্ডার প্রভাবিত।
obj_instance.attribute
- প্রথমে উপরের অংশটি দেখতে হবে যে বৈশিষ্ট্যটি উদাহরণের শ্রেণিতে কোনও ডেটা-বর্ণনাকারী কিনা,
- যদি না হয়, এটা যদি অ্যাট্রিবিউট রয়েছে কিনা তা দেখে মনে হচ্ছে
obj_instanceএর __dict__, তারপর
- অবশেষে এটি কোনও অ-ডেটা-বর্ণনাকারীর কাছে পড়ে।
এই অনুসন্ধানের আদেশের পরিণতি হ'ল নন-ডেটা-বর্ণনাকারীর মতো ফাংশন / পদ্ধতিগুলি উদাহরণগুলির দ্বারা ওভাররাইড করা যায় ।
পুনরুদ্ধার এবং পরবর্তী পদক্ষেপ
আমরা শিখেছি যে, বর্ণনাকারী সাথে বস্তু __get__, __set__বা __delete__। এই বর্ণনাকারী অবজেক্টগুলিকে অন্যান্য অবজেক্ট শ্রেণির সংজ্ঞা হিসাবে অ্যাট্রিবিউট হিসাবে ব্যবহার করা যেতে পারে। উদাহরণস্বরূপ আপনার কোডটি ব্যবহার করে এখন সেগুলি কীভাবে ব্যবহৃত হয় তা আমরা পর্যালোচনা করব।
প্রশ্ন থেকে কোড বিশ্লেষণ
এখানে আপনার কোড, আপনার প্রতিটি প্রশ্নের উত্তর এবং উত্তর:
class Celsius(object):
def __init__(self, value=0.0):
self.value = float(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = float(value)
class Temperature(object):
celsius = Celsius()
- আমার কেন বর্ণনাকারী শ্রেণি দরকার?
আপনার বর্ণনাকারী নিশ্চিত করে যে আপনার সর্বদা এই শ্রেণীর বৈশিষ্ট্যের জন্য একটি ভাসা রয়েছে Temperatureএবং আপনি delগুণটি মুছতে ব্যবহার করতে পারবেন না :
>>> t1 = Temperature()
>>> del t1.celsius
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __delete__
অন্যথায়, আপনার বর্ণনাকারীরা মালিক-শ্রেণি এবং মালিকের দৃষ্টান্তগুলি উপেক্ষা করে পরিবর্তে বর্ণনাকারীর মধ্যে রাজ্য সংরক্ষণ করে। আপনি সরল শ্রেণীর অ্যাট্রিবিউট দিয়ে সহজেই সমস্ত দৃষ্টান্তে রাজ্য ভাগ করে নিতে পারেন (যতক্ষণ না আপনি সর্বদা এটি ক্লাসে একটি ভাসা হিসাবে সেট করেছেন এবং এটি কখনও মুছবেন না, বা আপনার কোড ব্যবহারকারীদের সাথে স্বাচ্ছন্দ্য বোধ করছেন):
class Temperature(object):
celsius = 0.0
এটি আপনার উদাহরণের মতো ঠিক একই আচরণ পেয়েছে (নীচের প্রশ্নের 3 propertyটির প্রতিক্রিয়া দেখুন), তবে পাইথন বিল্টিন ( ) ব্যবহার করে এবং এটি আরও মূর্খ বলে বিবেচিত হবে:
class Temperature(object):
_celsius = 0.0
@property
def celsius(self):
return type(self)._celsius
@celsius.setter
def celsius(self, value):
type(self)._celsius = float(value)
- উদাহরণ এবং মালিক এখানে কি? ( পেতে ) এই পরামিতিগুলির উদ্দেশ্য কী?
instanceএটি হ'ল মালিকের উদাহরণ যা বর্ণনাকারীকে কল করে। মালিক হ'ল শ্রেণি যেখানে বর্ণনাকারী অবজেক্টটি ডেটা পয়েন্টে অ্যাক্সেস পরিচালনা করতে ব্যবহৃত হয়। আরও বর্ণনামূলক পরিবর্তনশীল নামের জন্য এই উত্তরের প্রথম অনুচ্ছেদের পাশের বর্ণনাকারীদের সংজ্ঞায়িতকারী বিশেষ পদ্ধতির বর্ণনা দেখুন।
- এই উদাহরণটি আমি কীভাবে কল / ব্যবহার করব?
এখানে একটি বিক্ষোভ:
>>> t1 = Temperature()
>>> t1.celsius
0.0
>>> t1.celsius = 1
>>>
>>> t1.celsius
1.0
>>> t2 = Temperature()
>>> t2.celsius
1.0
আপনি গুণটি মুছতে পারবেন না:
>>> del t2.celsius
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __delete__
এবং আপনি কোনও ভেরিয়েবল বরাদ্দ করতে পারবেন না যা ফ্লোটে রূপান্তর করা যাবে না:
>>> t1.celsius = '0x02'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __set__
ValueError: invalid literal for float(): 0x02
অন্যথায়, আপনার এখানে যা আছে তা সমস্ত দৃষ্টান্তের জন্য একটি বৈশ্বিক রাষ্ট্র, যা কোনও উদাহরণকে বরাদ্দ করে পরিচালিত হয়।
পাইথন প্রোগ্রামাররা যে ফলাফলটি প্রত্যাশিতভাবে সম্পন্ন করবে তা propertyহ'ল সাজসজ্জার ব্যবহার করা , যা একই বর্ণনাকারীকে হুডের নীচে ব্যবহার করে তবে মালিক শ্রেণীর প্রয়োগে আবার আচরণ করে (আবার উপরে বর্ণিত হিসাবে):
class Temperature(object):
_celsius = 0.0
@property
def celsius(self):
return type(self)._celsius
@celsius.setter
def celsius(self, value):
type(self)._celsius = float(value)
যার কোডটির মূল অংশের ঠিক একই প্রত্যাশিত আচরণ রয়েছে:
>>> t1 = Temperature()
>>> t2 = Temperature()
>>> t1.celsius
0.0
>>> t1.celsius = 1.0
>>> t2.celsius
1.0
>>> del t1.celsius
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't delete attribute
>>> t1.celsius = '0x02'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in celsius
ValueError: invalid literal for float(): 0x02
উপসংহার
আমরা বর্ণনাকারীদের সংজ্ঞা দেয় এমন বৈশিষ্ট্যগুলি, ডেটা- এবং অ-ডেটা-বিবরণকারীগুলির মধ্যে পার্থক্যগুলি, সেগুলি ব্যবহার করে এমন বিল্টিন অবজেক্ট এবং ব্যবহার সম্পর্কে নির্দিষ্ট প্রশ্নগুলি আবরণ করেছি।
আবার, আপনি কিভাবে প্রশ্নের উদাহরণ ব্যবহার করবেন? আমি আশা করি আপনি না। আমি আশা করি আপনি আমার প্রথম পরামর্শটি (একটি সাধারণ শ্রেণীর বৈশিষ্ট্য) দিয়ে শুরু করবেন এবং যদি আপনার প্রয়োজনীয়তা মনে হয় তবে দ্বিতীয় পরামর্শ (সম্পত্তি সজ্জাকার) এ এগিয়ে চলবেন।
selfএবংinstance?