যদি এই সম্পত্তিটি উত্পন্ন শ্রেণিতে ওভাররাইট করা হচ্ছে তবে বেস শ্রেণীর কোনও সম্পত্তি কীভাবে কল করবেন?


88

আমি আমার কিছু শ্রেণি গেটার্স এবং সেটটারগুলির বিস্তৃত ব্যবহার থেকে সম্পত্তিগুলির আরও পাইথোনিক ব্যবহারে পরিবর্তন করছি।

তবে এখন আমি আটকে আছি কারণ আমার পূর্ববর্তী কিছু গেটার বা সেটটার বেস ক্লাসের সাথে সম্পর্কিত পদ্ধতিটি কল করে এবং পরে অন্য কিছু সম্পাদন করে। তবে কীভাবে সম্পত্তি সহ এটি সম্পন্ন করা যায়? প্যারেন্ট ক্লাসে সম্পত্তি গেটর বা সেটটারকে কীভাবে কল করবেন?

অবশ্যই কেবল অ্যাট্রিবিউটকে কল করা অসীম পুনরাবৃত্তি দেয়।

class Foo(object):

    @property
    def bar(self):
        return 5

    @bar.setter
    def bar(self, a):
        print a

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
        # perform the same action
        # as in the base class
        self.bar = c    # --> recursion!
        # then do something else
        print 'something else'

fb = FooBar()
fb.bar = 7

উত্তর:


103

আপনি হয়ত ভাবেন যে আপনি বেস ক্লাস ফাংশনটি কল করতে পারেন যা সম্পত্তি দ্বারা ডাকা হয়:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

যদিও আমি মনে করি এটি চেষ্টা করার সবচেয়ে সুস্পষ্ট বিষয় - এটি কাজ করে না কারণ বার একটি সম্পত্তি, কলযোগ্য নয়।

তবে সম্পত্তিটি কেবলমাত্র একটি অবজেক্ট, সম্পর্কিত বৈশিষ্ট্যটি সন্ধানের জন্য একটি গেটর পদ্ধতি সহ:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)

Foo.bar.fset(self, c)উত্তরাধিকার সূত্রে আমাকে কেন ফোন করা উচিত ? কেন না Foo.bar.fset(c)- "স্ব" ব্যতীত - আমি ভেবেছিলাম এটি নিখুঁতভাবে পাস হয়েছে?
নারডোক


@ উত্তরডোকটি selfচেইন থেকে কোথায় পাওয়া যায় Foo.bar.fset?
টেডগ ম্যাকডোনাল্ড-জেনসেন

কেবল একটি চিন্তা - AFAIK স্ব সর্বদা স্পষ্টভাবে পাস করা হয়। যদি আপনি একটি করেন foo = Foo()\ foo.bar(c)কোনও স্ব পাস হয় না তবে বার () পাইথন থেকে এটি গ্রহণ করে। আমি পাইথন বিশেষজ্ঞ নই, কমবেশি একজন শিক্ষানবিসও। এটা শুধু একটি চিন্তা।
নারডোক

selfপদ্ধতিটি যখন কোনও শ্রেণীর উদাহরণ হিসাবে ডাকা হয় কেবল তখনই স্পষ্টভাবে পাস করা হয়। উদাহরণস্বরূপ, যদি আমার Aকোনও পদ্ধতি সহ একটি ক্লাস থাকে b(self, arg)এবং আমি একটি উদাহরণ তৈরি করি c = A()তবে কল c.b(arg)করা সমানA.b(c, arg)
টালচাক

55

সুপারের কৌশলটি করা উচিত:

return super().bar

পাইথন ২.x এ আপনাকে আরও ভার্বোস সিনট্যাক্স ব্যবহার করতে হবে:

return super(FooBar, self).bar


4
আমার ধারণা (ভাল, লিঙ্কটি দ্বারা বিচার করা: পি), এই উত্তরটি পাইথন 3-সম্পর্কিত। পাইথন 3-এ সুপার () শূন্য আর্গুমেন্ট নিতে পারে, হ্যাঁ।
শীলেন্ট

6
সুপার ()। বারটি প্রাপ্তির পক্ষে সূক্ষ্মভাবে কাজ করে বলে মনে হচ্ছে, তবে ওভাররাইড হওয়া সেটারে বেস প্রোপারটির মাধ্যমে অ্যাসাইনমেন্টের জন্য কাজ করে না। যদি আমি সুপার ()। বার = 3 করি তবে আমি অ্যাট্রিবিউটআরার পেয়েছি: 'সুপার' অবজেক্টটির কোনও 'গুণ' নেই
রব স্মলশায়ার

4
গুড পয়েন্ট রব, সেটা জানত না। এখানে আরো তথ্য রয়েছে stackoverflow.com/questions/10810369/...
Pankrat

4
যদিও এটি পাওয়ার জন্য কাজ করে এটি একটির সাথে সেট করতে ব্যর্থ হয় AttributeError
ইথান ফুরম্যান

27

ব্যবহারের বিকল্প রয়েছে super করে বেস ক্লাসের নামটি স্পষ্টভাবে উল্লেখ করতে হবে না।

বেস ক্লাস এ:

class A(object):
    def __init__(self):
        self._prop = None

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass

বি তে, পিতামত্তা শ্রেণীর A এর সম্পত্তি প্রাপ্তির অ্যাক্সেস করা:

অন্যরা ইতিমধ্যে উত্তর হিসাবে, এটি:

super(B, self).prop

বা পাইথন 3 এ:

super().prop

এটি সম্পত্তি প্রাপ্তকারীর দ্বারা প্রদত্ত মানটি ফেরত দেয়, গেটর নিজেই দেয় না তবে গেটারকে প্রসারিত করার পক্ষে এটি যথেষ্ট।

বি তে, পিতামাত্ত শ্রেণীর সম্পত্তি সেটারের অ্যাক্সেস করা:

আমি এখনও অবধি সবচেয়ে ভাল সুপারিশটি দেখেছি:

A.prop.fset(self, value)

আমি বিশ্বাস করি এটি আরও ভাল:

super(B, self.__class__).prop.fset(self, value)

এই উদাহরণে উভয় বিকল্প সমতুল্য তবে সুপার ব্যবহারের বেস ক্লাসগুলি থেকে স্বতন্ত্র হওয়ার সুবিধা রয়েছে B। যদি Bকোনও Cশ্রেণীর সম্পত্তিও প্রসারিত হয়ে উত্তরাধিকার সূত্রে হয় তবে আপনাকে আপডেট করতে হবে নাB কোডটি ।

এ এর সম্পত্তি বাড়ানোর বি এর সম্পূর্ণ কোড:

class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(B, self.__class__).prop.fset(self, value)

একটি সতর্কতা:

যদি আপনার সম্পত্তির কোনও সেটটার না Bথাকে তবে আপনি কেবল সেগুলির মধ্যে একটির আচরণ পরিবর্তন করলেও আপনাকে সেটার এবং গিটার উভয়কেই সংজ্ঞায়িত করতে হবে।


হ্যালো, এটি খুব সহায়ক। আমি এই সম্পর্কে একটি ফলো আপ প্রশ্ন আছে। এই সেটআপটি ভাল কাজ করে; যাইহোক, আমি অতিরিক্ত বৈশিষ্ট্য সংজ্ঞায়িত করার জন্য যখন বি এর জন্য ডিগ্রি সেট করি তখন এটি কাজ করা বন্ধ করে দেয় । বি এর জন্য আলাদা ডিগ্রি দেওয়ার কোনও উপায় আছে কি ? ধন্যবাদ আপনি
স্যাং

আপনি দয়া করে বর্ণনা করতে পারেন কিভাবে super(B, self.__class__)ঠিক এর সাথে কাজ করে super(class, class)? এটি কোথায় নথিবদ্ধ?
আর্ট


4

চেষ্টা করুন

@property
def bar:
    return super(FooBar, self).bar

যদিও আমি নিশ্চিত নই যে পাইথন বেস ক্লাসের সম্পত্তি কল করতে সমর্থন করে। একটি সম্পত্তি আসলে একটি কলযোগ্য বস্তু যা নির্দিষ্ট ফাংশন দিয়ে সেট আপ করা হয় এবং তারপরে ক্লাসে সেই নামটি প্রতিস্থাপন করে। এটি সহজেই বোঝাতে পারে যে এখানে কোনও সুপার ফাংশন উপলব্ধ নেই।

সম্পত্তি () ফাংশনটি ব্যবহার করতে আপনি সর্বদা আপনার সিনট্যাক্সটি স্যুইচ করতে পারেন যদিও:

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7

আপনি বেস ক্লাসটি লিখলে এটি সূক্ষ্ম কাজ করে। তবে আপনি যদি কোনও তৃতীয় পক্ষের বেস শ্রেণি প্রসারিত করেন যা সম্পত্তি এবং প্রাপ্তির জন্য একই নাম ব্যবহার করে?
আকাইহোলা

2

ম্যাক্সিমের উত্তরে কিছু ছোট উন্নতি :

  • __class__লেখা এড়াতে ব্যবহার করা B। দ্রষ্টব্য যে self.__class__এটি রানটাইম ধরণের ধরণের self, তবে __class__ বিনা self ক্লাস সংজ্ঞাটির নাম। super()একটি সংক্ষিপ্তকরণsuper(__class__, self)
  • এর __set__পরিবর্তে ব্যবহার করা হচ্ছে fset। পরেরটি propertys এর ক্ষেত্রে নির্দিষ্ট , তবে পূর্ববর্তী সমস্ত সম্পত্তি-জাতীয় বস্তুর (বর্ণনাকারী) ক্ষেত্রে প্রযোজ্য।
class B(A):
    @property
    def prop(self):
        value = super().prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(__class__, self.__class__).prop.__set__(self, value)

1

আপনি নিম্নলিখিত টেমপ্লেট ব্যবহার করতে পারেন:

class Parent():
    def __init__(self, value):
        self.__prop1 = value

    #getter
    @property
    def prop1(self):
        return self.__prop1

    #setter
    @prop1.setter
    def prop1(self, value):
        self.__prop1 = value

    #deleter
    @prop1.deleter
    def prop1(self):
        del self.__prop1
  
class Child(Parent):

    #getter
    @property
    def prop1(self):
        return super(Child, Child).prop1.__get__(self)

    #setter
    @prop1.setter
    def prop1(self, value):
        super(Child, Child).prop1.__set__(self, value)

    #deleter
    @prop1.deleter
    def prop1(self):
        super(Child, Child).prop1.__delete__(self)

বিঃদ্রঃ! সমস্ত সম্পত্তি পদ্ধতি একসাথে পুনরায় সংজ্ঞায়িত করা আবশ্যক। যদি সমস্ত পদ্ধতি পুনরায় সংজ্ঞায়িত করতে না চান তবে পরিবর্তে নিম্নলিখিত টেমপ্লেটটি ব্যবহার করুন:

class Parent():
    def __init__(self, value):
        self.__prop1 = value

    #getter
    @property
    def prop1(self):
        return self.__prop1

    #setter
    @prop1.setter
    def prop1(self, value):
        self.__prop1 = value

    #deleter
    @prop1.deleter
    def prop1(self):
        del self.__prop1


class Child(Parent):

    #getter
    @Parent.prop1.getter
    def prop1(self):
        return super(Child, Child).prop1.__get__(self)

    #setter
    @Parent.prop1.setter
    def prop1(self, value):
        super(Child, Child).prop1.__set__(self, value)

    #deleter
    @Parent.prop1.deleter
    def prop1(self):
        super(Child, Child).prop1.__delete__(self)

-4
    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

(এটি হ'ল যদি না আমি আপনার ব্যাখ্যা থেকে কিছু মিস করি)


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