__Getattr__ বনাম __getattribute__ এর মধ্যে পার্থক্য


417

আমি কখন __getattr__বা কখন ব্যবহার করব তা বোঝার চেষ্টা করছি __getattribute__ডকুমেন্টেশন উল্লেখ __getattribute__নতুন স্টাইলের শ্রেণীর ক্ষেত্রে প্রযোজ্য। নতুন ধাঁচের ক্লাস কি?



5
@ ট্র্যারিওন এখনও সেই প্রশ্নে এখান থেকে একটি উত্তরের উল্লেখ করেছে ...
জে.সি. রোকমন্ডে

উত্তর:


497

এর মধ্যে একটি মূল পার্থক্য __getattr__এবং __getattribute__যে __getattr__শুধুমাত্র যদি অ্যাট্রিবিউট স্বাভাবিক উপায়ে পাওয়া যায়নি প্রার্থনা করা হয়। অনুপস্থিত বৈশিষ্ট্যগুলির জন্য ফ্যালব্যাক বাস্তবায়নের জন্য এটি ভাল এবং সম্ভবত আপনি যে দুটিতে চান তার মধ্যে একটি এটি।

__getattribute__বস্তুর প্রকৃত বৈশিষ্ট্যগুলি দেখার আগে অনুরোধ করা হয়েছিল এবং তাই সঠিকভাবে প্রয়োগ করা জটিল trick আপনি খুব সহজেই অনন্ত পুনরাবৃত্তিতে শেষ করতে পারেন।

নতুন স্টাইলের ক্লাসগুলি থেকে প্রাপ্ত object, পুরাতন-শৈলীর ক্লাসগুলি পাইথন ২.x এর কোনও স্পষ্ট বেস ক্লাস নয়। কিন্তু পুরোনো শৈলী এবং নতুন স্টাইলের শ্রেণীর মধ্যে পার্থক্য গুরুত্বপূর্ণ যখন মধ্যবর্তী নির্বাচন নয় __getattr__এবং __getattribute__

আপনি প্রায় অবশ্যই চান __getattr__


6
আমি কি উভয়কে একই শ্রেণিতে প্রয়োগ করতে পারি? আমি যদি পারি, তবে উভয় বাস্তবায়নের জন্য এটি কী?
অ্যালকোট

13
@ অ্যালকোট: আপনি এগুলি উভয়ই বাস্তবায়ন করতে পারেন তবে কেন আপনি তা করবেন তা আমি নিশ্চিত নই। __getattribute__প্রতিটি অ্যাক্সেসের জন্য ডাকা হবে, এবং __getattr__যে বার __getattribute__উত্থাপিত হয়েছিল তার জন্য ডাকা হবে AttributeError। শুধু কেন সব কিছু রাখবেন না?
নেড ব্যাচেল্ডার

10
@ নেড ব্যাচেল্ডার, আপনি যদি বিদ্যমান শর্তগুলিতে (শর্তাধীন) কলগুলি ওভাররাইড করতে চান তবে আপনি ব্যবহার করতে চান __getattribute__
জেস ব্রাউনিং

28
"এই পদ্ধতিতে অসীম পুনরাবৃত্তি এড়ানোর জন্য, এর প্রয়োগকরণের সর্বদা প্রয়োজন নামের কোনও বৈশিষ্ট্য অ্যাক্সেস করার জন্য একই নামের সাথে বেস শ্রেণির পদ্ধতিটি কল করা উচিত, উদাহরণস্বরূপ, অবজেক্ট।
কমোনসুর

1
@kmonsoor। এটি উভয়ই বাস্তবায়নের একটি ভাল কারণ। সঠিক পরিস্থিতিতে objec.__getattribute__প্রার্থনা myclass.__getattr__
ম্যাড পদার্থবিদ

138

উভয় __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)

1
ওভাররাইডিংয়ের ক্ষেত্রে ব্যবহারের ক্ষেত্রে কী হবে তা আমি নিশ্চিত নই __getattribute__তবে অবশ্যই এটি নয়। কারণ আপনার উদাহরণ অনুসারে, আপনি যা করছেন __getattribute__তা AttributeErrorব্যতিক্রম বাড়াচ্ছে যদি অ্যাট্রিবিউটটির মধ্যে বৈশিষ্ট্যটি না থাকে __dict__; তবে আপনার সত্যিই __getattribute__এটির প্রয়োজন নেই কারণ এটি ডিফল্ট বাস্তবায়ন এবং __getattr__ফলব্যাক প্রক্রিয়া হিসাবে আপনার যা প্রয়োজন ঠিক তেমনই ।
রোহিত

@Rohit currentদৃষ্টান্ত উপর সংজ্ঞায়িত করা হয় Count(দেখুন __init__), তাই কেবল উত্থাপন AttributeErrorঅ্যাট্রিবিউট সেখানে নেই হলে বেশ কি ঘটছে না - এটি অবকাশ __getattr__জন্য সব নাম 'বর্তমান' শুরু সহ current, কিন্তু curious, curly...
joelb

16

নেড ব্যাচেল্ডারের ব্যাখ্যার ভিত্তিতে এটি কেবল একটি উদাহরণ ।

__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


9
আসলে, এটি ভয়ানক। রিয়েল-ওয়ার্ল্ড __getattr__()বাস্তবায়ন কেবল AttributeErrorঅবৈধ বৈশিষ্ট্য নামগুলির জন্য উত্থাপনের মাধ্যমে বৈধ বৈশিষ্ট্য নামের একটি সীমাবদ্ধ সেট গ্রহণ করে , যার ফলে সূক্ষ্ম এবং কঠিন থেকে ডিবাগ সমস্যাগুলি এড়ানো হয় । এই উদাহরণটি নিঃশর্তভাবে সমস্ত বৈশিষ্ট্যের নামকে বৈধ হিসাবে গ্রহণ করে - একটি উদ্ভট (এবং স্পষ্টতই ত্রুটি-প্রবণ) এর অপব্যবহার __getattr__()। আপনি যদি উদাহরণ হিসাবে যেমন গুণাবলী তৈরির উপরে "সম্পূর্ণ নিয়ন্ত্রণ" চান তবে আপনি তার __getattribute__()পরিবর্তে চান ।
সিসিল কারি

3
@ সিসিলক্রোরি: আপনি যে সমস্ত ইস্যুতে জড়িত তার সাথে জড়িত সমস্ত বিষয় ইস্যুতে কোনও মান বাদ দিয়ে আর কিছুই প্রত্যাবর্তন করছে, যা এই উত্তর দেয় না। সমস্ত অ্যাট্রিবিউটর নাম গ্রহণে ভুল কী? এটি একটি হিসাবে একই defaultdict
নিক মাত্তিও

2
সমস্যাটি হ'ল সুপারক্লাস অনুসন্ধানের আগে__getattr__ ডাকা হবে । এটি সরাসরি উপশ্রেণীর জন্য ঠিক আছে , যেহেতু আপনি যে পদ্ধতিগুলির বিষয়ে সত্যই যত্নবান হন কেবল সেই পদ্ধতিতে যাদুর পদ্ধতি রয়েছে যা উদাহরণটিকে উপেক্ষা করে তবে আরও জটিল উত্তরাধিকার কাঠামোর জন্য আপনি পিতামাতার কাছ থেকে কোনও কিছুর উত্তরাধিকারী হওয়ার ক্ষমতা সম্পূর্ণভাবে সরিয়ে ফেলেন। object
ম্যাড পদার্থবিদ

1
@ সিমন কে ভাট্টা 4ya, আপনার শেষ মুদ্রণ বিবৃতিটি একটি মন্তব্য। রাইট? এটি একটি দীর্ঘ লাইন এবং পড়ার জন্য ক্লান্তিকর (একটি ডানদিকে অনেক স্ক্রোল করতে হবে)। কোড বিভাগের পরে লাইন স্থাপন সম্পর্কে কী? অথবা আপনি যদি কোড বিভাগে রাখতে চান তবে আমার মনে হয় এটি দুটি ভিন্ন লাইনে বিভক্ত করা ভাল be
মোঃ আবু নাফী ইবনা জাহিদ

14

নতুন স্টাইলের ক্লাসগুলি উত্তরাধিকার সূত্রে objectবা অন্য নতুন শৈলীর শ্রেণীর কাছ থেকে:

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass

পুরানো স্টাইলের ক্লাসগুলি এটি করে না:

class SomeObject:
    pass

এটি কেবল পাইথন 2 এ প্রযোজ্য - পাইথন 3 এ উপরের সমস্তগুলি নতুন-স্টাইলের ক্লাস তৈরি করবে।

দেখুন 9. ক্লাস (পাইথন টিউটোরিয়াল), NewClassVsClassicClass এবং পুরানো শৈলী এবং পাইথন নতুন শৈলী শ্রেণীর মধ্যে পার্থক্য কি? বিস্তারিত জানার জন্য.


6

নতুন স্টাইলের ক্লাসগুলি এমন হয় যা সাবক্লাসটি "অবজেক্ট" (প্রত্যক্ষ বা পরোক্ষভাবে) সাবক্লাস করে। এগুলির একটি __new__শ্রেণিক পদ্ধতি ছাড়াও __init__কিছুটা যুক্তিযুক্ত নিম্ন-স্তরের আচরণ রয়েছে।

সাধারণত, আপনি ওভাররাইড করতে চাইবেন __getattr__(যদি আপনিও ওভাররাইড করছেন) তবে অন্যথায় আপনার পদ্ধতিগুলির মধ্যে "সেলফুফু" সিনট্যাক্সকে সমর্থন করতে আপনার একটি কঠিন সময় কাটাতে হবে।

অতিরিক্ত তথ্য: http://www.devx.com/opensource/Article/31482/0/page/4


2

বেজলি এবং জোন্স পিসিবি পড়ার সময়, আমি একটি স্পষ্ট এবং ব্যবহারিক ব্যবহারের ক্ষেত্রে হোঁচট খেয়েছি __getattr__যে এর জন্য ওপি-র প্রশ্নের "যখন" অংশটির উত্তর দিতে সহায়তা করে। বইটি থেকে:

" __getattr__()বৈশিষ্ট্যটি অনুসন্ধানের জন্য পদ্ধতিটি এক ধরণের মত। এটি এমন একটি পদ্ধতি যা কোডটি উপস্থিত না হয়ে এমন একটি বৈশিষ্ট্য অ্যাক্সেস করার চেষ্টা করে যদি কল হয়" " আমরা উপরের উত্তরগুলি থেকে এটি জানি, কিন্তু পিসিবি রেসিপি 8.15 এ এই কার্যকারিতাটি প্রতিনিধিদলের নকশার প্যাটার্ন প্রয়োগ করতে ব্যবহৃত হয় । যদি অবজেক্ট এ এর ​​একটি বৈশিষ্ট্যযুক্ত অবজেক্ট বি থাকে যা অবজেক্ট এ এর ​​অবজেক্ট বি এর সমস্ত পদ্ধতি পুনরায় সংজ্ঞায়িত না করে কেবল অবজেক্ট বি এর পদ্ধতিগুলি কল করার জন্য অনেকগুলি পদ্ধতি প্রয়োগ করে যা অবিলম্বে এটিকে প্রতিনিধিত্ব করতে চায়, নীচে একটি __getattr__()পদ্ধতি নির্ধারণ করুন :

def __getattr__(self, name):
    return getattr(self._b, name)

যেখানে _ বি হ'ল অবজেক্ট এ এর ​​গুণাবলীর নাম যা একটি অবজেক্ট বি। যখন অবজেক্ট বিতে সংজ্ঞায়িত পদ্ধতিটি অবজেক্ট এতে ডাকা হয়, তখন __getattr__পদ্ধতিটি অনুসন্ধান শৃঙ্খলের শেষে ডাকা হবে। এটি কোড ক্লিনারটিকেও পরিষ্কার করে দেবে, যেহেতু আপনার কাছে কেবল অন্য কোনও বস্তুতে অর্পণ করার জন্য সংজ্ঞায়িত পদ্ধতির একটি তালিকা নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.