পাইথনে @ foo.setter আমার জন্য কেন কাজ করে না?


155

সুতরাং, আমি পাইথন ২.6 এ সজ্জকারদের সাথে খেলছি এবং তাদের কাজ করতে আমার কিছুটা সমস্যা হচ্ছে। আমার ক্লাস ফাইলটি এখানে:

class testDec:

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

আমি এর অর্থ কী বোঝাতে xচাই তা হ'ল সম্পত্তির মতো আচরণ করা , তবে এই ফাংশনগুলিকে গেট অ্যান্ড সেট করে কল করুন। সুতরাং, আমি আইডিএল বরখাস্ত করেছি এবং এটি পরীক্ষা করেছি:

>>> from testDec import testDec
from testDec import testDec
>>> t = testDec()
t = testDec()
>>> t.x
t.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "testDec.py", line 18, in x
    return self._x
AttributeError: testDec instance has no attribute '_x'
>>> t.x = 5
t.x = 5
>>> t.x
t.x
5

স্পষ্টতই প্রথম কলটি প্রত্যাশার মতো কাজ করে, যেহেতু আমি গ্রাহককে কল করি এবং কোনও ডিফল্ট মান নেই এবং এটি ব্যর্থ হয়। ঠিক আছে, ভাল, আমি বুঝতে পেরেছি। যাইহোক, বরাদ্দ করার জন্য কলটি t.x = 5একটি নতুন সম্পত্তি তৈরি করেছে বলে মনে হচ্ছে x, এবং এখন প্রাপ্তিটি কাজ করে না!

আমি কী মিস করছি?


6
একটি বড় হাতের অক্ষরের সাথে ক্লাসের নাম দিন Name আপনি ভেরিয়েবল এবং মডিউল ফাইলগুলির জন্য ছোট হাতের ব্যবহার করতে পারেন।
এস.লোট

উত্তর:


306

আপনি অজগর 2 এ ক্লাসিক পুরানো-শৈলীর ক্লাস ব্যবহার করছেন বলে মনে হচ্ছে বৈশিষ্ট্যগুলি সঠিকভাবে কাজ করার জন্য পরিবর্তে আপনাকে নতুন-স্টাইলের ক্লাসগুলি ব্যবহার করা উচিত (পাইথন 2 এ আপনার অবশ্যই উত্তরাধিকার সূত্রে প্রাপ্তobject হতে হবে )। আপনার ক্লাসটিকে কেবল এই হিসাবে ঘোষণা করুন MyClass(object):

class testDec(object):

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

এটি কাজ করে:

>>> k = testDec()
>>> k.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/devel/class_test.py", line 6, in x
    return self._x
AttributeError: 'testDec' object has no attribute '_x'
>>> k.x = 5
called setter
>>> k.x
called getter
5
>>> 

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

@x.setter
def x_setter(self, value):
    ...

এবং আরও একটি জিনিস যা প্রথমে স্পট করা সম্পূর্ণ সহজ নয়, তা হ'ল আদেশটি: প্রথমে গ্রাহককে অবশ্যই সংজ্ঞায়িত করতে হবে । আপনি যদি প্রথমে সেটারটি সংজ্ঞায়িত করেন তবে আপনি name 'x' is not definedত্রুটি পান।


4
পাইথন 3-তে এটি আর দরকার নেই - "ক্লাসিক" ক্লাসগুলি
সেটটারগুলির

20
এটি অজগর 3 তে কাজ করে কারণ প্রতিটি ক্লাস একটি নতুন ধাঁচের শ্রেণি, আর কোনও 'ক্লাসিক' ক্লাস নেই।
ক্রেগড

আমি মনে করি, যদি এই ক্ষেত্রে ডেকরেটার সঠিকভাবে প্রক্রিয়া না করা হয় তবে একজনকে একটি সতর্কতা / ত্রুটি পাওয়া উচিত।
stfn

82

এই ব্যতিক্রমটির জন্য এখানে যারা হোঁচট খায় কেবল তাদের জন্য কেবল একটি নোট: উভয় ফাংশনের একই নাম হওয়া দরকার। পদ্ধতিগুলি নীচে নামকরণ করার ফলে একটি ব্যতিক্রম হবে:

@property
def x(self): pass

@x.setter
def x_setter(self, value): pass

পরিবর্তে উভয় পদ্ধতি একই নাম দিন

@property
def x(self): pass

@x.setter
def x(self, value): pass

ঘোষণার আদেশের বিষয়টি বিবেচনা করাও গুরুত্বপূর্ণ। গেটরটি অবশ্যই ফাইলটিতে সেটারের আগে সংজ্ঞায়িত করা উচিত অন্যথায় আপনি একটি পাবেনNameError: name 'x' is not defined


এটি সম্ভবত "নতুন" সেরা উত্তর হয়ে উঠতে চলেছে, পাইথন 3-তে আরও বেশি লোকের সাথে ...
trpt4im

5
এই উত্তর দুর্দান্ত। আমি মনে করি যে সম্পূর্ণ হওয়ার জন্য, এটি দুর্দান্ত হবে যদি আপনি মন্তব্য করতে পারেন যে ক্রমটি গুরুত্বপূর্ণ, অর্থাত্ কোডের মধ্যে সেটটারের আগে পাওয়া উচিত। অন্যথায়, আপনি একটি NameError: name 'x' is not definedব্যতিক্রম পাবেন।
এগুইও

এর জন্য ধন্যবাদ. আমি এই উপর একটি দিনের সেরা অংশ নষ্ট করেছি। এটি আমার কাছে কখনও ঘটেনি যে পদ্ধতিগুলিকে একই জিনিস বলা উচিত। সত্যিই হতাশ ছোট্ট আইডিয়োম!
আজকাওয়ানাঘ

এই উত্তরের পিছনে "কেন" বোঝার জন্য, এখানে যথাযথ ডকুমেন্টেশন পড়ুন: ডকস.পাইথন.আর / 2 / লাইব্রেরি / ফাংশনস html# প্রপার্টি বিশেষত "ঠিক সমতুল্য" অংশটি নোট করুন।
এভেজেনি সার্জিভ

23

আপনার নতুন-স্টাইলের ক্লাসগুলি ব্যবহার করা দরকার যা আপনি আপনার ক্লাসটি অবজেক্ট থেকে উত্পন্ন করে করেন:

class testDec(object):
   ....

তাহলে এটি কাজ করা উচিত।


উপরের সব কিছু ঠিক জায়গায় ছিল। ক্লাসে বৈশিষ্ট্যগুলি সঠিকভাবে লাথি মারার জন্য পাইথন ২.7.x এ আমার জন্য এটি প্রয়োজন ছিল।
ড্রোন ব্রেইন

12

যদি কেউ গুগল থেকে এখানে আসে তবে উপরের উত্তরগুলি ছাড়াও আমি যুক্ত করতে চাই যে উত্তরটির__init__ উপর ভিত্তি করে আপনার শ্রেণীর পদ্ধতি থেকে সেটারকে অনুরোধ করার সময় এটির যত্নবান মনোযোগ প্রয়োজন বিশেষত:

class testDec(object):                                                                                                                                            

    def __init__(self, value):
        print 'We are in __init__'
        self.x = value # Will call the setter. Note just x here
        #self._x = value # Will not call the setter

    @property
    def x(self):
        print 'called getter'
        return self._x # Note the _x here

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value # Note the _x here

t = testDec(17)
print t.x 

Output:
We are in __init__
called setter
called getter
17

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