__Getattr__ এবং __getattribute__ এর মধ্যে পার্থক্য বোঝা


206

আমি পার্থক্য বুঝতে মধ্যে চেষ্টা করছি __getattr__এবং __getattribute__, কিন্তু, আমি এটাকে ব্যর্থ করছি।

উত্তর স্ট্যাক ওভারফ্লো প্রশ্নের মধ্যে পার্থক্য __getattr__বনাম__getattribute__ বলেছেন:

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

এর অর্থ কী তা আমার একেবারেই ধারণা নেই।

তারপরে এটি বলে যায়:

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

কেন?

আমি পড়ি যে যদি __getattribute__ব্যর্থ হয়, __getattr__বলা হয়। তাহলে কেন দুটি ভিন্ন পদ্ধতি একই জিনিস করছে? যদি আমার কোডটি নতুন স্টাইলের ক্লাসগুলি প্রয়োগ করে, আমার কী ব্যবহার করা উচিত?

এই প্রশ্নটি সাফ করার জন্য আমি কয়েকটি কোড উদাহরণ খুঁজছি। আমি আমার দক্ষতার সেরাতম দিকে গুগলড করেছি, তবে যে উত্তরগুলি আমি পেয়েছি সেগুলি সমস্যার পুরোপুরি আলোচনা করে না।

যদি কোনও ডকুমেন্টেশন থাকে তবে আমি এটি পড়তে প্রস্তুত।


2
যদি এটি ডক্স থেকে সহায়তা করে "এই পদ্ধতিতে অসীম পুনরাবৃত্তি এড়ানোর জন্য, এর প্রয়োগকরণকে সর্বদা প্রয়োজন নামের কোনও বৈশিষ্ট্য অ্যাক্সেস করার জন্য একই নামের সাথে বেস শ্রেণির পদ্ধতিটি কল করা উচিত, উদাহরণস্বরূপ, বস্তু __ getattribute __ (স্ব, নাম)। " [ docs.python.org/2/references/…
kmonsoor

উত্তর:


306

প্রথমে কিছু বেসিক।

বস্তুগুলির সাথে, আপনাকে এর বৈশিষ্ট্যগুলি মোকাবেলা করতে হবে। সাধারণত আমরা করি instance.attribute। কখনও কখনও আমাদের আরও নিয়ন্ত্রণের প্রয়োজন হয় (যখন আমরা আগে থেকেই গুণটির নাম জানি না)।

উদাহরণস্বরূপ, instance.attributeহয়ে উঠবে getattr(instance, attribute_name)। এই মডেলটি ব্যবহার করে, আমরা একটি স্ট্রিং হিসাবে অ্যাট্রিবিউট_নাম সরবরাহ করে বৈশিষ্ট্যটি পেতে পারি ।

ব্যাবহার __getattr__

আপনি কোনও শ্রেণিকে এটিও বলতে পারেন যে কীভাবে এমন বৈশিষ্ট্যগুলি মোকাবেলা করতে হবে যা এটি স্পষ্টভাবে পরিচালনা করে না এবং __getattr__পদ্ধতিটির মাধ্যমে তা করে ।

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

একটি ক্লাসিক ব্যবহারের কেস:

class A(dict):
    def __getattr__(self, name):
       return self[name]
a = A()
# Now a.somekey will give a['somekey']

গুহা এবং ব্যবহার __getattribute__

আপনার যদি প্রতিটি অ্যাট্রিবিউট উপস্থিত না থাকুক নির্বিশেষে ধরার দরকার হয় তবে তার __getattribute__পরিবর্তে ব্যবহার করুন। পার্থক্যটি হ'ল কেবল এমন __getattr__বৈশিষ্ট্যগুলির জন্য আহ্বান করা হয় যা বাস্তবে বিদ্যমান নেই। আপনি যদি সরাসরি কোনও অ্যাট্রিবিউট সেট করেন, সেই গুণটি উল্লেখ করে কল না করে এটিকে পুনরুদ্ধার করতে হবে __getattr__

__getattribute__ সব সময় বলা হয়।


"উদাহরণস্বরূপ, উদাহরণস্বরূপ getattr(instance, attribute_name)। অবদান হয়ে যাবে "। এটা করা উচিত নয় __getattribute__(instance, attribute_name)?
মোঃ আবু নাফী ইবনা জাহিদ

1
@ মোঃআবুনাফিআইবনাজাহিদ getattrএকটি অন্তর্নির্মিত ফাংশন। getattr(foo, 'bar')সমতূল্য foo.bar
wizzwizz4

লক্ষ্য করার মতো যে __getattr__এটি কেবল সংজ্ঞায়িত হলেই ডেকে আনা হয়, কারণ এটি উত্তরাধিকার সূত্রে প্রাপ্ত নয়object
joelb

94

__getattribute__ যখনই কোনও অ্যাট্রিবিউট অ্যাক্সেস ঘটে তখন তাকে ডাকা হয়।

class Foo(object):
    def __init__(self, a):
        self.a = 1

    def __getattribute__(self, attr):
        try:
            return self.__dict__[attr]
        except KeyError:
            return 'default'
f = Foo(1)
f.a

এটি অসীম পুনরাবৃত্তি ঘটায়। এখানে অপরাধী লাইন return self.__dict__[attr]। আসুন ভান করা যাক (এটি সত্যের নিকটবর্তী) যে সমস্ত বৈশিষ্ট্যগুলি self.__dict__তাদের নামে সঞ্চিত এবং উপলব্ধ। লাইন

f.a

এর aবৈশিষ্ট্যটি অ্যাক্সেস করার চেষ্টা করে f। এই কল f.__getattribute__('a')__getattribute__তারপরে লোড করার চেষ্টা করে self.__dict____dict__একটি অ্যাট্রিবিউট self == fএবং তাই পাইথন কলগুলি f.__getattribute__('__dict__')আবার বৈশিষ্ট্যটি অ্যাক্সেস করার চেষ্টা করে '__dict__। এটি অসীম পুনরাবৃত্তি।

__getattr__পরিবর্তে যদি ব্যবহার করা হয়

  1. এটি কখনও চালিত হত না কারণ fএকটি aবৈশিষ্ট্য রয়েছে।
  2. যদি এটি চালানো হয়, (আসুন আমরা এটি জিজ্ঞাসা করি যে আপনি জিজ্ঞাসা করেছিলেন f.b) তবে এটি অনুসন্ধানের জন্য ডাকা হত না __dict__কারণ এটি ইতিমধ্যে রয়েছে এবং __getattr__কেবলমাত্র অনুরোধ করা হয়েছে যদি বৈশিষ্ট্যটি অনুসন্ধানের অন্যান্য সমস্ত পদ্ধতি ব্যর্থ হয়

'সঠিক' পথ ব্যবহার করে উপরে উল্লেখিত বর্গ লিখতে __getattribute__হয়

class Foo(object):
    # Same __init__

    def __getattribute__(self, attr):
        return super(Foo, self).__getattribute__(attr)

super(Foo, self).__getattribute__(attr)__getattribute__'নিকটতম' সুপারক্লাসের পদ্ধতিটি (আনুষ্ঠানিকভাবে, ক্লাসের মেথড রেজোলিউশন অর্ডারের পরবর্তী শ্রেণি, বা এমআরও) বর্তমান অবজেক্টের সাথে আবদ্ধ করে selfএবং পরে এটি কল করে এবং সেই কাজটি করতে দেয়।

এই সমস্ত সমস্যা এড়ানো এড়ানো যায় __getattr__যা কোনও অ্যাট্রিবিউট সন্ধান না পাওয়া পর্যন্ত পাইথনটিকে এটি স্বাভাবিক জিনিস করতে দেয় । সেই সময়ে পাইথন আপনার __getattr__পদ্ধতির উপর নিয়ন্ত্রণ রাখে এবং এটিকে কিছু দিয়ে আসে।

আপনি যে অসীম পুনরাবৃত্তি দিয়ে চালাতে পারেন তাও লক্ষণীয় __getattr__

class Foo(object):
    def __getattr__(self, attr):
        return self.attr

ওকে আমি এক্সারসাইজ হিসাবে ছেড়ে দেব।


60

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

# prop.py
import inspect

class PropClass(object):
    def __getattribute__(self, attr):
        val = super(PropClass, self).__getattribute__(attr)
        if callable(val):
            argcount = len(inspect.getargspec(val).args)
            # Account for self
            if argcount == 1:
                return val()
            else:
                return val
        else:
            return val

এবং ইন্টারেক্টিভ দোভাষী থেকে:

>>> import prop
>>> class A(prop.PropClass):
...     def f(self):
...             return 1
... 
>>> a = A()
>>> a.f
1

অবশ্যই এটি একটি নির্বোধ উদাহরণ এবং আপনি সম্ভবত কখনও এটি করতে চান না, তবে এটি আপনাকে ওভাররাইডিং থেকে পাওয়ার পাওয়ারটি দেখায় __getattribute__


6

আমি অন্যের দুর্দান্ত ব্যাখ্যা দিয়ে গিয়েছি have তবে আমি পাইথন ম্যাজিক পদ্ধতি এবং__getattr__ এই ব্লগ থেকে একটি সহজ উত্তর পেয়েছি । নিম্নলিখিত সমস্ত সেখান থেকে।

__getattr__ম্যাজিক পদ্ধতিটি ব্যবহার করে আমরা সেই অযোগ্য বৈশিষ্ট্য অনুসন্ধানকে বাধা দিতে পারি এবং এটি ব্যর্থ হয় না এমন কিছু করতে পারি:

class Dummy(object):

    def __getattr__(self, attr):
        return attr.upper()

d = Dummy()
d.does_not_exist # 'DOES_NOT_EXIST'
d.what_about_this_one  # 'WHAT_ABOUT_THIS_ONE'

তবে যদি বৈশিষ্ট্যটি বিদ্যমান থাকে, __getattr__তবে তা চাওয়া হবে না:

class Dummy(object):

    def __getattr__(self, attr):
        return attr.upper()

d = Dummy()
d.value = "Python"
print(d.value)  # "Python"

__getattribute____getattr__গুরুত্বপূর্ণ পার্থক্যটির সাথে অনুরূপ , যা প্রতিটি বৈশিষ্ট্য অনুসন্ধানে __getattribute__বাধা দেবে , বৈশিষ্ট্যটি উপস্থিত রয়েছে কি না তা বিবেচনাধীন নয়।

class Dummy(object):

    def __getattribute__(self, attr):
        return 'YOU SEE ME?'

d = Dummy()
d.value = "Python"
print(d.value)  # "YOU SEE ME?"

এই উদাহরণে, dঅবজেক্টটির ইতিমধ্যে একটি বৈশিষ্ট্যযুক্ত মান রয়েছে। তবে আমরা যখন এটি অ্যাক্সেস করার চেষ্টা করি তখন আমরা আসল প্রত্যাশিত মান পাই না ("পাইথন"); আমরা যা কিছু __getattribute__ফিরিয়ে দিয়েছি তা পাচ্ছি । এর অর্থ হ'ল আমরা কার্যত মানটির বৈশিষ্ট্যটি হারিয়ে ফেলেছি; এটি "অ্যাক্সেসযোগ্য" হয়ে গেছে।

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