পাইথনে সম্পত্তি বৈশিষ্ট্যটি কীভাবে ব্যবহার করবেন সে সম্পর্কে বাস্তব বিশ্বের উদাহরণ?


142

@propertyপাইথনে কীভাবে ব্যবহার করতে হয় তা সম্পর্কে আমি আগ্রহী । আমি পাইথন ডক্স এবং সেখানে উদাহরণটি পড়েছি, আমার মতে, এটি একটি খেলনা কোড:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

_xসম্পত্তি সাজসজ্জারের সাথে ভরাট মোড়ানো থেকে আমি কী সুবিধা (গুলি) পেতে পারি তা আমি জানি না । কেন শুধু হিসাবে প্রয়োগ করা হয় না:

class C(object):
    def __init__(self):
        self.x = None

আমি মনে করি, সম্পত্তি বৈশিষ্ট্যটি কিছু পরিস্থিতিতে কার্যকর হতে পারে। কিন্তু যখন? কেউ দয়া করে আমাকে কিছু বাস্তব-বিশ্বের উদাহরণ দিতে পারেন?

ধন্যবাদ।


9
সম্পত্তির সাজসজ্জার সম্পর্কে আমি এটি খুঁজে পেয়েছি সেরা এবং পরিষ্কার ব্যাখ্যা [এখানে ক্লিক করুন ]
সুমুদু

2
@ অ্যানুবিস আপনার সরবরাহিত লিঙ্কটির শেষ উদাহরণে সি = সেলসিয়াস সেট করে (-500) কোনও মানই বাড়াতে পারেনি, যা আমার মনে হয় উদ্দেশ্যযুক্ত ফলাফলটি অর্জন করছে না।
সাজুউক

@ আনুবিসের সাথে একমত এটি এখানে যথাযথভাবে প্রয়োগ করা হয়েছে: পাইথন
কোর্স.ইউ

উত্তর:


91

অন্যান্য উদাহরণগুলি সেট বৈশিষ্ট্যের বৈধতা / ফিল্টারিং (তাদের সীমাবদ্ধ বা গ্রহণযোগ্য হতে বাধ্য করা) এবং জটিল বা দ্রুত পরিবর্তিত পদগুলির অলস মূল্যায়ন হবে।

জটিলতার গণনা একটি বৈশিষ্ট্যের পিছনে লুকানো:

class PDB_Calculator(object):
    ...
    @property
    def protein_folding_angle(self):
        # number crunching, remote server calls, etc
        # all results in an angle set in 'some_angle'
        # It could also reference a cache, remote or otherwise,
        # that holds the latest value for this angle
        return some_angle

>>> f = PDB_Calculator()
>>> angle = f.protein_folding_angle
>>> angle
44.33276

ভ্যালিডেশন:

class Pedometer(object)
    ...
    @property
    def stride_length(self):
        return self._stride_length

    @stride_length.setter
    def stride_length(self, value):
        if value > 10:
            raise ValueError("This pedometer is based on the human stride - a stride length above 10m is not supported")
        else:
            self._stride_length = value

1
আমি পিডিবি_ক্যালকুলেটর উদাহরণটি পছন্দ করি - জটিল জিনিসগুলি বিমূর্ত করা হয়, পুরো জিনিসটি কাজ করে এবং ব্যবহারকারী সরলতা উপভোগ করতে পারেন!
অ্যাডাম কুরকিউইকজ

2
সম্ভবত, প্রো দৃষ্টিকোণ থেকে, এই খুব ভাল উদাহরণ। তবে, নুবি হিসাবে, আমি এই উদাহরণগুলি বেশ অকার্যকর বলে মনে করি। আমার খারাপ ... :(
kmonsoor

77

একটি সাধারণ ব্যবহারের ক্ষেত্রে হ'ল কেবল পঠনযোগ্য অ্যান্ট্রিবিউট সেট করতে হবে, কারণ আপনি জানেন যে অজগরটিতে একটি আন্ডারস্কোর সহ একটি চলক নামের নেতৃত্ব করা _xসাধারণত সাধারণত এটি ব্যক্তিগত (অভ্যন্তরীণ ব্যবহার) বোঝায় তবে কখনও কখনও আমরা উদাহরণের বৈশিষ্ট্যটি পড়তে সক্ষম হতে চাই এবং না লিখতে চাই এটি যাতে আমরা এটির propertyজন্য ব্যবহার করতে পারি :

>>> class C(object):

        def __init__(self, x):
            self._x = x

        @property
        def x(self):
            return self._x

>>> c = C(1)
>>> c.x
1
>>> c.x = 2
AttributeError        Traceback (most recent call last)

AttributeError: can't set attribute

6
c._xব্যবহারকারী এখনও চাইলে কেউ সেট করতে পারে। পাইথনের প্রকৃত ব্যক্তিগত বৈশিষ্ট্য নেই।

20

খুব ব্যবহারিক ব্যবহারের জন্য এই নিবন্ধটি একবার দেখুন । সংক্ষেপে, এটি ব্যাখ্যা করে যে পাইথনে আপনি সাধারণত স্পষ্টভাবে গেটর / সেটার পদ্ধতিটি খনন করতে পারেন, যেহেতু আপনার যদি কোনও পর্যায়ে তাদের প্রয়োজন হয় তবে আপনি propertyএকটি বিরামবিহীন বাস্তবায়নের জন্য ব্যবহার করতে পারেন ।


15

একটি জিনিস যা আমি এটির জন্য ব্যবহার করেছি তা হ'ল স্লো-টু-লুক-আপকে ক্যাচ করা, তবে অপরিবর্তনীয়, ডাটাবেসে সঞ্চিত মান। এটি আপনার অবস্থার জন্য গণনা বা কিছু অন্যান্য দীর্ঘ ক্রিয়াকলাপের প্রয়োজন (যেমন, ডাটাবেস চেক, নেটওয়ার্ক যোগাযোগ) যা আপনি কেবল চাহিদা অনুযায়ী করতে চান সেই পরিস্থিতিতে এটি সাধারণীকরণ করে।

class Model(object):

  def get_a(self):
    if not hasattr(self, "_a"):
      self._a = self.db.lookup("a")
    return self._a

  a = property(get_a)

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


1
আপনি @cached_propertyএই জন্য ব্যবহার করতে পারবেন না ?
আদর্শ

@ আদর্শ - আকর্ষণীয় মনে হচ্ছে কোথায় আছে?
স্পষ্টভাবে

আমি এটি ব্যবহার করছি তবে আমি ভুলে গেছি যে এটি কোনও অন্তর্নির্মিত ছিল না, তবে আপনি এটি দিয়ে এটি ব্যবহার করতে পারেন, পাইপি.পিথন.আর
পিপিআই

2
মজাদার. আমি মনে করি এটি প্রথম এই উত্তরের পরে প্রকাশিত হয়েছিল, তবে যে কেউ এটি পড়ছে তার পরিবর্তে সম্ভবত এটি ব্যবহার করা উচিত।
স্পষ্টত

10

উত্তর এবং মন্তব্যগুলি পড়ে, মূল থিমটি মনে হচ্ছে উত্তরগুলি একটি সহজ, তবুও দরকারী উদাহরণ অনুপস্থিত। আমি এখানে খুব সাধারণ একটি অন্তর্ভুক্ত করেছি যা @propertyসাজসজ্জার সাধারণ ব্যবহার প্রদর্শন করে । এটি এমন একটি শ্রেণি যা ব্যবহারকারীর বিভিন্ন ইউনিট, অর্থাৎ in_feetবা ব্যবহার করে দূরত্ব পরিমাপ নির্দিষ্ট করতে এবং পেতে সহায়তা করে in_metres

class Distance(object):
    def __init__(self):
        # This private attribute will store the distance in metres
        # All units provided using setters will be converted before
        # being stored
        self._distance = 0.0

    @property
    def in_metres(self):
        return self._distance

    @in_metres.setter
    def in_metres(self, val):
        try:
            self._distance = float(val)
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

    @property
    def in_feet(self):
        return self._distance * 3.2808399

    @in_feet.setter
    def in_feet(self, val):
        try:
            self._distance = float(val) / 3.2808399
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

    @property
    def in_parsecs(self):
        return self._distance * 3.24078e-17

    @in_parsecs.setter
    def in_parsecs(self, val):
        try:
            self._distance = float(val) / 3.24078e-17
        except:
            raise ValueError("The input you have provided is not recognised "
                             "as a valid number")

ব্যবহার:

>>> distance = Distance()
>>> distance.in_metres = 1000.0
>>> distance.in_metres
1000.0
>>> distance.in_feet
3280.8399
>>> distance.in_parsecs
3.24078e-14

ব্যক্তিগতভাবে আমার জন্য, গ্রাহকরা / সেটটারগুলির সর্বোত্তম উদাহরণ হ'ল লোকেরা আপনাকে পরবর্তী সময়ে যে ধরণের পরিবর্তনগুলি করা দরকার তা দেখানো কিন্তু স্পষ্টতই, এতে আরও কিছুটা সময় লাগে।
dtc

7

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

@property
def x(self):
    """I'm the 'x' property."""
    if self._x is None:
        self._x = Foo()

    return self._x

6

হ্যাঁ, পোস্ট করা মূল উদাহরণের জন্য, সম্পত্তিটি কেবলমাত্র একটি উদাহরণ ভেরিয়েবল 'x' থাকার মতোই কাজ করবে।

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

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

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

শ্রেণীর বাইরে কোড সহ অনেকগুলি ভাষা (যেমন জাভা) ব্যবহার করে

object.get_i()
    #and
object.set_i(value)

#in place of (with python)
object.i
    #and 
object.i = value

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

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


6

সেটেটর এবং গেটর ব্যবহার করে বৈশিষ্ট্যগুলির আরও একটি দুর্দান্ত বৈশিষ্ট্য যা তারা আপনাকে এখনও কোনও বৈধতা, অ্যাক্সেস নিয়ন্ত্রণ, ক্যাচিং ইত্যাদি বজায় রেখে আপনার বৈশিষ্ট্যগুলিতে ওপ = অপারেটরগুলি (যেমন + =, - =, * = ইত্যাদি) ব্যবহার চালিয়ে যেতে দেয় that সেটটার এবং গেটাররা সরবরাহ করত।

উদাহরণস্বরূপ, আপনি যদি Personসেটার setage(newage), এবং গেটর সহ ক্লাস লিখে থাকেন getage()তবে বয়স বাড়ানোর জন্য আপনাকে লিখতে হবে:

bob = Person('Robert', 25)
bob.setage(bob.getage() + 1)

তবে আপনি যদি ageকোনও সম্পত্তি তৈরি করেন তবে আপনি আরও ক্লিনার লিখতে পারেন:

bob.age += 1

5

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

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


4

প্রথমে অনেকেই লক্ষ্য করে না এমন কিছু হ'ল আপনি নিজের সম্পত্তিটির নিজস্ব সাবক্লাস তৈরি করতে পারেন। এটি আমি কেবল পঠনযোগ্য অবজেক্টের বৈশিষ্ট্য বা গুণাবলী যা আপনি পড়তে এবং লিখতে পারেন তবে মুছে ফেলতে পারবেন না এমন প্রকাশের জন্য খুব দরকারী useful অবজেক্ট ক্ষেত্রগুলিতে ট্র্যাকিংয়ের পরিবর্তনগুলির মতো কার্যকারিতা মোড়ানোর পক্ষে এটি একটি দুর্দান্ত উপায়।

class reader(property):
    def __init__(self, varname):
        _reader = lambda obj: getattr(obj, varname)
        super(reader, self).__init__(_reader)

class accessor(property):
    def __init__(self, varname, set_validation=None):
        _reader = lambda obj: getattr(obj, varname)
        def _writer(obj, value):
            if set_validation is not None:
               if set_validation(value):
                  setattr(obj, varname, value)
        super(accessor, self).__init__(_reader, _writer)

#example
class MyClass(object):
   def __init__(self):
     self._attr = None

   attr = reader('_attr')

আমি এই পছন্দ। আমি কি এটি সঠিকভাবে পড়ছি যে পাঠক মুছে ফেলা সক্ষমতা ছাড়াই অ্যাক্সেসর পড়তে / লিখতে কেবল তখনই পড়তে হয়? আপনি কিভাবে ডেটা বৈধতা যুক্ত করবেন? আমি পাইথনে মোটামুটি নতুন তবে আমি ভাবছি attr = reader('_attr')লাইনে কলব্যাক যুক্ত করার মতো উপায় আছে বা এর মতো প্রাক-পরীক্ষার কোনও ফর্ম রয়েছে attr = if self.__isValid(value): reader('_attr')। পরামর্শ?
গাবে স্প্রেডলিন

দুঃখিত, আমি কেবলমাত্র পঠনযোগ্য ভেরিয়েবলের জন্য ডেটা বৈধতা সম্পর্কে জিজ্ঞাসা করেছি বুঝতে পেরেছি। তবে স্পষ্টতই এটি কেবলমাত্র অ্যাক্সেসর শ্রেণির সেটার অংশের জন্য প্রযোজ্য। তাই পরিবর্তন attr = reader('_attr')করার জন্য attr = accessor('_attr')। ধন্যবাদ
গ্যাব স্প্রেডলিন

আপনি ঠিক যে আপনি যদি বৈধতা চেয়েছিল তারপর আপনি যাচাইকৃত এবং বাড়াতে ব্যতিক্রম যদি অবৈধ (বা যাই হোক না কেন আচরণ আপনি যদি কিছু সহ পছন্দ করেছে) এর একটি ফাংশন যোগ যাবে Init । আমি একটি সম্ভাব্য প্যাটার্ন দিয়ে উপরেরটিকে সংশোধন করেছি। সেটটি ঘটে কি না তা নির্দেশিকার জন্য বৈধকারীর সত্য | মিথ্যা প্রত্যাবর্তন করা উচিত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.