আমি কখন __getattr__
বা কখন ব্যবহার করব তা বোঝার চেষ্টা করছি __getattribute__
। ডকুমেন্টেশন উল্লেখ __getattribute__
নতুন স্টাইলের শ্রেণীর ক্ষেত্রে প্রযোজ্য। নতুন ধাঁচের ক্লাস কি?
আমি কখন __getattr__
বা কখন ব্যবহার করব তা বোঝার চেষ্টা করছি __getattribute__
। ডকুমেন্টেশন উল্লেখ __getattribute__
নতুন স্টাইলের শ্রেণীর ক্ষেত্রে প্রযোজ্য। নতুন ধাঁচের ক্লাস কি?
উত্তর:
এর মধ্যে একটি মূল পার্থক্য __getattr__
এবং __getattribute__
যে __getattr__
শুধুমাত্র যদি অ্যাট্রিবিউট স্বাভাবিক উপায়ে পাওয়া যায়নি প্রার্থনা করা হয়। অনুপস্থিত বৈশিষ্ট্যগুলির জন্য ফ্যালব্যাক বাস্তবায়নের জন্য এটি ভাল এবং সম্ভবত আপনি যে দুটিতে চান তার মধ্যে একটি এটি।
__getattribute__
বস্তুর প্রকৃত বৈশিষ্ট্যগুলি দেখার আগে অনুরোধ করা হয়েছিল এবং তাই সঠিকভাবে প্রয়োগ করা জটিল trick আপনি খুব সহজেই অনন্ত পুনরাবৃত্তিতে শেষ করতে পারেন।
নতুন স্টাইলের ক্লাসগুলি থেকে প্রাপ্ত object
, পুরাতন-শৈলীর ক্লাসগুলি পাইথন ২.x এর কোনও স্পষ্ট বেস ক্লাস নয়। কিন্তু পুরোনো শৈলী এবং নতুন স্টাইলের শ্রেণীর মধ্যে পার্থক্য গুরুত্বপূর্ণ যখন মধ্যবর্তী নির্বাচন নয় __getattr__
এবং __getattribute__
।
আপনি প্রায় অবশ্যই চান __getattr__
।
__getattribute__
প্রতিটি অ্যাক্সেসের জন্য ডাকা হবে, এবং __getattr__
যে বার __getattribute__
উত্থাপিত হয়েছিল তার জন্য ডাকা হবে AttributeError
। শুধু কেন সব কিছু রাখবেন না?
__getattribute__
।
objec.__getattribute__
প্রার্থনা myclass.__getattr__
।
উভয় __getattr__
এবং __getattribute__
যাদু পদ্ধতির কয়েকটি সাধারণ উদাহরণ দেখতে দিন ।
__getattr__
পাইথন __getattr__
যখনই এমন কোনও বৈশিষ্ট্যের জন্য অনুরোধ করবে যা ইতিমধ্যে সংজ্ঞায়িত করা হয়নি Py নিম্নলিখিত উদাহরণে আমার ক্লাস কাউন্টের কোনও __getattr__
পদ্ধতি নেই। এখন প্রধানত যখন আমি উভয়টি অ্যাক্সেস করার চেষ্টা করি obj1.mymin
এবং obj1.mymax
বৈশিষ্ট্যগুলি সবকিছু ঠিকঠাক করে দেয়। তবে যখন আমি obj1.mycurrent
অ্যাট্রিবিউটটি অ্যাক্সেস করার চেষ্টা করি - পাইথন আমাকে দেয়AttributeError: 'Count' object has no attribute 'mycurrent'
class Count():
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent'
এখন আমার ক্লাসের কাউন্ট হয়েছে __getattr__
পদ্ধতি। এখন যখন আমি obj1.mycurrent
অ্যাট্রিবিউটটি অ্যাক্সেস করার চেষ্টা করি - পাইথন আমার __getattr__
পদ্ধতিতে যা প্রয়োগ করেছি তা আমাকে ফিরিয়ে দেয় । আমার উদাহরণে আমি যখনই কোনও অ্যাট্রিবিউটকে কল করার চেষ্টা করি যা বিদ্যমান নেই, পাইথন সেই বৈশিষ্ট্যটি তৈরি করে এবং এটি পূর্ণসংখ্যার মান 0 তে সেট করে।
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
def __getattr__(self, item):
self.__dict__[item]=0
return 0
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)
__getattribute__
এখন __getattribute__
পদ্ধতিটি দেখতে দিন see আপনি যদি __getattribute__
আপনার বর্গ পদ্ধতি, পাইথন নির্বিশেষে প্রত্যেক অ্যাট্রিবিউট জন্য এই পদ্ধতি আবাহন করে ফাইলটার অস্তিত্ব তথা না। তাহলে আমাদের কেন __getattribute__
পদ্ধতি দরকার ? একটি ভাল কারণ হ'ল আপনি নীচের উদাহরণে বর্ণিত বৈশিষ্ট্যগুলিতে অ্যাক্সেস আটকাতে এবং এটিকে আরও সুরক্ষিত করতে পারেন।
যখনই কেউ আমার অ্যাট্রিবিউটগুলি অ্যাক্সেস করার চেষ্টা করে যা 'কার' পাইথনটি সাবস্ট্রিং দিয়ে শুরু হয় তার AttributeError
ব্যতিক্রম উত্থাপন করে । অন্যথায় এটি যে বৈশিষ্ট্যটি ফেরত দেয়।
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
গুরুত্বপূর্ণ: __getattribute__
পদ্ধতিতে অসীম পুনরাবৃত্তি এড়ানোর জন্য , এর বাস্তবায়নের জন্য প্রয়োজনীয় বৈশিষ্ট্যগুলির অ্যাক্সেসের জন্য সর্বদা একই নামের সাথে বেস বর্গ পদ্ধতিটি কল করা উচিত। : উদাহরণস্বরূপ object.__getattribute__(self, name)
বা super().__getattribute__(item)
নাself.__dict__[item]
যদি আপনার শ্রেণিতে উভয়টি গ্যাটট্রা এবং গেট্যাট্রিবিট যাদু পদ্ধতি থাকে তবে __getattribute__
প্রথমে তাকে বলা হয়। তবে যদি ব্যতিক্রম __getattribute__
উত্থাপন করে
AttributeError
তবে ব্যতিক্রম উপেক্ষা করা __getattr__
হবে এবং পদ্ধতিটি চাওয়া হবে। নিম্নলিখিত উদাহরণটি দেখুন:
class Count(object):
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattr__(self, item):
self.__dict__[item]=0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
# note this class subclass object
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
__getattribute__
তবে অবশ্যই এটি নয়। কারণ আপনার উদাহরণ অনুসারে, আপনি যা করছেন __getattribute__
তা AttributeError
ব্যতিক্রম বাড়াচ্ছে যদি অ্যাট্রিবিউটটির মধ্যে বৈশিষ্ট্যটি না থাকে __dict__
; তবে আপনার সত্যিই __getattribute__
এটির প্রয়োজন নেই কারণ এটি ডিফল্ট বাস্তবায়ন এবং __getattr__
ফলব্যাক প্রক্রিয়া হিসাবে আপনার যা প্রয়োজন ঠিক তেমনই ।
current
দৃষ্টান্ত উপর সংজ্ঞায়িত করা হয় Count
(দেখুন __init__
), তাই কেবল উত্থাপন AttributeError
অ্যাট্রিবিউট সেখানে নেই হলে বেশ কি ঘটছে না - এটি অবকাশ __getattr__
জন্য সব নাম 'বর্তমান' শুরু সহ current
, কিন্তু curious
, curly
...
নেড ব্যাচেল্ডারের ব্যাখ্যার ভিত্তিতে এটি কেবল একটি উদাহরণ ।
__getattr__
উদাহরণ:
class Foo(object):
def __getattr__(self, attr):
print "looking up", attr
value = 42
self.__dict__[attr] = value
return value
f = Foo()
print f.x
#output >>> looking up x 42
f.x = 3
print f.x
#output >>> 3
print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')
এবং যদি একই উদাহরণ ব্যবহার করা হয় তবে __getattribute__
আপনি >>> পাবেনRuntimeError: maximum recursion depth exceeded while calling a Python object
__getattr__()
বাস্তবায়ন কেবল AttributeError
অবৈধ বৈশিষ্ট্য নামগুলির জন্য উত্থাপনের মাধ্যমে বৈধ বৈশিষ্ট্য নামের একটি সীমাবদ্ধ সেট গ্রহণ করে , যার ফলে সূক্ষ্ম এবং কঠিন থেকে ডিবাগ সমস্যাগুলি এড়ানো হয় । এই উদাহরণটি নিঃশর্তভাবে সমস্ত বৈশিষ্ট্যের নামকে বৈধ হিসাবে গ্রহণ করে - একটি উদ্ভট (এবং স্পষ্টতই ত্রুটি-প্রবণ) এর অপব্যবহার __getattr__()
। আপনি যদি উদাহরণ হিসাবে যেমন গুণাবলী তৈরির উপরে "সম্পূর্ণ নিয়ন্ত্রণ" চান তবে আপনি তার __getattribute__()
পরিবর্তে চান ।
defaultdict
।
__getattr__
ডাকা হবে । এটি সরাসরি উপশ্রেণীর জন্য ঠিক আছে , যেহেতু আপনি যে পদ্ধতিগুলির বিষয়ে সত্যই যত্নবান হন কেবল সেই পদ্ধতিতে যাদুর পদ্ধতি রয়েছে যা উদাহরণটিকে উপেক্ষা করে তবে আরও জটিল উত্তরাধিকার কাঠামোর জন্য আপনি পিতামাতার কাছ থেকে কোনও কিছুর উত্তরাধিকারী হওয়ার ক্ষমতা সম্পূর্ণভাবে সরিয়ে ফেলেন। object
নতুন স্টাইলের ক্লাসগুলি উত্তরাধিকার সূত্রে object
বা অন্য নতুন শৈলীর শ্রেণীর কাছ থেকে:
class SomeObject(object):
pass
class SubObject(SomeObject):
pass
পুরানো স্টাইলের ক্লাসগুলি এটি করে না:
class SomeObject:
pass
এটি কেবল পাইথন 2 এ প্রযোজ্য - পাইথন 3 এ উপরের সমস্তগুলি নতুন-স্টাইলের ক্লাস তৈরি করবে।
দেখুন 9. ক্লাস (পাইথন টিউটোরিয়াল), NewClassVsClassicClass এবং পুরানো শৈলী এবং পাইথন নতুন শৈলী শ্রেণীর মধ্যে পার্থক্য কি? বিস্তারিত জানার জন্য.
নতুন স্টাইলের ক্লাসগুলি এমন হয় যা সাবক্লাসটি "অবজেক্ট" (প্রত্যক্ষ বা পরোক্ষভাবে) সাবক্লাস করে। এগুলির একটি __new__
শ্রেণিক পদ্ধতি ছাড়াও __init__
কিছুটা যুক্তিযুক্ত নিম্ন-স্তরের আচরণ রয়েছে।
সাধারণত, আপনি ওভাররাইড করতে চাইবেন __getattr__
(যদি আপনিও ওভাররাইড করছেন) তবে অন্যথায় আপনার পদ্ধতিগুলির মধ্যে "সেলফুফু" সিনট্যাক্সকে সমর্থন করতে আপনার একটি কঠিন সময় কাটাতে হবে।
অতিরিক্ত তথ্য: http://www.devx.com/opensource/Article/31482/0/page/4
বেজলি এবং জোন্স পিসিবি পড়ার সময়, আমি একটি স্পষ্ট এবং ব্যবহারিক ব্যবহারের ক্ষেত্রে হোঁচট খেয়েছি __getattr__
যে এর জন্য ওপি-র প্রশ্নের "যখন" অংশটির উত্তর দিতে সহায়তা করে। বইটি থেকে:
" __getattr__()
বৈশিষ্ট্যটি অনুসন্ধানের জন্য পদ্ধতিটি এক ধরণের মত। এটি এমন একটি পদ্ধতি যা কোডটি উপস্থিত না হয়ে এমন একটি বৈশিষ্ট্য অ্যাক্সেস করার চেষ্টা করে যদি কল হয়" " আমরা উপরের উত্তরগুলি থেকে এটি জানি, কিন্তু পিসিবি রেসিপি 8.15 এ এই কার্যকারিতাটি প্রতিনিধিদলের নকশার প্যাটার্ন প্রয়োগ করতে ব্যবহৃত হয় । যদি অবজেক্ট এ এর একটি বৈশিষ্ট্যযুক্ত অবজেক্ট বি থাকে যা অবজেক্ট এ এর অবজেক্ট বি এর সমস্ত পদ্ধতি পুনরায় সংজ্ঞায়িত না করে কেবল অবজেক্ট বি এর পদ্ধতিগুলি কল করার জন্য অনেকগুলি পদ্ধতি প্রয়োগ করে যা অবিলম্বে এটিকে প্রতিনিধিত্ব করতে চায়, নীচে একটি __getattr__()
পদ্ধতি নির্ধারণ করুন :
def __getattr__(self, name):
return getattr(self._b, name)
যেখানে _ বি হ'ল অবজেক্ট এ এর গুণাবলীর নাম যা একটি অবজেক্ট বি। যখন অবজেক্ট বিতে সংজ্ঞায়িত পদ্ধতিটি অবজেক্ট এতে ডাকা হয়, তখন __getattr__
পদ্ধতিটি অনুসন্ধান শৃঙ্খলের শেষে ডাকা হবে। এটি কোড ক্লিনারটিকেও পরিষ্কার করে দেবে, যেহেতু আপনার কাছে কেবল অন্য কোনও বস্তুতে অর্পণ করার জন্য সংজ্ঞায়িত পদ্ধতির একটি তালিকা নেই।