আমি কীভাবে পাইথনে __getattr__ কে ডিফল্ট আচরণ না ভেঙে ওভাররাইড করব?


185

__getattr__অভিনব কিছু করার জন্য আমি ক্লাসে পদ্ধতিটি ওভাররাইড করতে চাই তবে আমি ডিফল্ট আচরণটি ভাঙতে চাই না।

এটি করার সঠিক উপায় কী?


20
"বিরতি," এটি জিজ্ঞাসা করে, "পরিবর্তন" নয়। এটি যথেষ্ট পরিষ্কার: "অভিনব" বৈশিষ্ট্যগুলি অন্তর্নির্মিত বৈশিষ্ট্যের সাথে হস্তক্ষেপ করা উচিত নয় এবং তাদের মতো যথাসম্ভব আচরণ করা উচিত। মাইকেল এর উত্তর সঠিক এবং সহায়ক উভয়।
olioney

উত্তর:


268

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

class Foo(object):
    def __getattr__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            raise AttributeError

তবে, এর বিপরীতে __getattr__, __getattribute__প্রথম বলা হবে (কেবলমাত্র নতুন স্টাইলের ক্লাসের জন্য কাজ করে যারা বস্তু থেকে উত্তরাধিকারসূত্রে আসে)। এই ক্ষেত্রে, আপনি এর মতো ডিফল্ট আচরণ সংরক্ষণ করতে পারেন:

class Foo(object):
    def __getattribute__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            return object.__getattribute__(self, name)

আরও জন্য পাইথন ডক্স দেখুন


বাহ, আপনার সম্পাদনার একই জিনিসটি আমি আমার উত্তরটিতে দেখছিলাম, +1।

12
দুর্দান্ত, পাইথন সুপারস ইন কল করতে পছন্দ করছে না __getattr__- কোনও ধারণা কি করতে হবে? ( AttributeError: 'super' object has no attribute '__getattr__')
গাটোয়াগ্রাগো

1
আপনার কোড না দেখে এটি বলা শক্ত, তবে এটি দেখতে আপনার চশমাগুলির কোনওটিই getattr সংজ্ঞায়িত করে না বলে মনে হচ্ছে ।
কলিন ভিএইচ

এটি হ্যাশট্রারের সাথেও কাজ করে কারণ: "এটি গ্যাটট্রা (বস্তু, নাম) কল করে এবং এটি একটি ব্যতিক্রম উত্থাপন করে কিনা তা দেখে এটি প্রয়োগ করা হয়।" docs.python.org/2/library/function.html#hasattr
শাবং

1
-1 এই নেই ডিফল্ট আচরণ পরিবর্তন করুন। এখন আপনার AttributeErrorব্যতিক্রম আরগসগুলিতে বৈশিষ্ট্যের প্রসঙ্গ ছাড়াই আছে without
Wim

33
class A(object):
    def __init__(self):
        self.a = 42

    def __getattr__(self, attr):
        if attr in ["b", "c"]:
            return 42
        raise AttributeError("%r object has no attribute %r" %
                             (self.__class__.__name__, attr))

>>> a = A()
>>> a.a
42
>>> a.b
42
>>> a.missing
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in __getattr__
AttributeError: 'A' object has no attribute 'missing'
>>> hasattr(a, "b")
True
>>> hasattr(a, "missing")
False

এর জন্য ধন্যবাদ. উত্সের আশেপাশে খনন না করেই আমার ডিফল্ট বার্তাটি সঠিক ছিল তা নিশ্চিত করতে চেয়েছিলেন।
শনফুমো

4
আমার মনে হয় ক্লাসটি ওভাররাইডের self.__class__.__name__পরিবর্তে এটি ব্যবহার করা উচিতself.__class____repr__
মাইকেল স্কট কুথবার্ট

3
স্বীকৃত উত্তরের চেয়ে এটি উত্তম, তবে শব্দের সংশোধন করা উচিত বা ভবিষ্যতে ব্যতিক্রম অবজেক্টে অতিরিক্ত প্রসঙ্গ যুক্ত করা গেলে সেই কোডটি পুনরায় লিখতে এবং সম্ভাব্যভাবে প্রবাহের পরিবর্তনগুলি মিস না করা ভাল।
wim

12

মাইকেল উত্তরটি প্রসারিত করতে, আপনি যদি ডিফল্ট আচরণটি ব্যবহার করে বজায় রাখতে চান তবে আপনি __getattr__এটি এর মতো করতে পারেন:

class Foo(object):
    def __getattr__(self, name):
        if name == 'something':
            return 42

        # Default behaviour
        return self.__getattribute__(name)

এখন ব্যতিক্রম বার্তা আরও বর্ণনামূলক:

>>> foo.something
42
>>> foo.error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __getattr__
AttributeError: 'Foo' object has no attribute 'error'

2
@ fed.pavlo আপনি কি নিশ্চিত? আপনি মিশ্রিত __getattr__এবং __getattribute__?
জোসে লুইস

আমার খারাপ আমি স্ব থেকে বিভিন্ন পদ্ধতিতে কল মিস করেছি। ; (
fed.pavlo

1
প্রকৃতপক্ষে @ মাইকেল এর উত্তরটি এই উত্তর ব্যতীত অসম্পূর্ণ
গ্রিজেশ চৌহান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.