শ্রেণিবদ্ধদের উপর সম্পত্তি () ব্যবহার করা


173

মূলত একটি স্ট্যাটিক ভেরিয়েবল কী পেতে এবং সেট করার জন্য আমার দুটি ক্লাসের পদ্ধতি (ক্লাসমেডুডथ () ফাংশন ব্যবহার করে) সহ একটি ক্লাস রয়েছে। আমি এগুলির সাথে সম্পত্তি () ফাংশনটি ব্যবহার করার চেষ্টা করেছি, তবে এটির ফলে একটি ত্রুটি ঘটেছে। আমি দোভাষীটিতে নিম্নলিখিতগুলির সাথে ত্রুটিটি পুনরুত্পাদন করতে সক্ষম হয়েছি:

class Foo(object):
    _var = 5
    @classmethod
    def getvar(cls):
        return cls._var
    @classmethod
    def setvar(cls, value):
        cls._var = value
    var = property(getvar, setvar)

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

>>> f = Foo()
>>> f.getvar()
5
>>> f.setvar(4)
>>> f.getvar()
4
>>> f.var
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable
>>> f.var=5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: 'classmethod' object is not callable

শ্রেণিবদ্ধ সজ্জিত ফাংশনগুলির সাথে সম্পত্তি () ফাংশনটি ব্যবহার করা কি সম্ভব?

উত্তর:


90

একটি সম্পত্তি একটি শ্রেণিতে তৈরি করা হয় তবে একটি দৃষ্টান্তকে প্রভাবিত করে। সুতরাং আপনি যদি একটি শ্রেণিবদ্ধ সম্পত্তি চান, মেটাক্লাসে সম্পত্তি তৈরি করুন।

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         pass
...     @classmethod
...     def getvar(cls):
...         return cls._var
...     @classmethod
...     def setvar(cls, value):
...         cls._var = value
...     
>>> foo.__metaclass__.var = property(foo.getvar.im_func, foo.setvar.im_func)
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

তবে যেহেতু আপনি কোনও মেটাক্লাস ব্যবহার করছেন, আপনি কেবল সেখানে শ্রেণিবদ্ধদের স্থানান্তরিত করলে এটি আরও ভাল পড়বে।

>>> class foo(object):
...     _var = 5
...     class __metaclass__(type):  # Python 2 syntax for metaclasses
...         @property
...         def var(cls):
...             return cls._var
...         @var.setter
...         def var(cls, value):
...             cls._var = value
... 
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

বা, পাইথন 3 এর metaclass=...সিনট্যাক্স এবং fooক্লাস বডির বাইরে সংজ্ঞায়িত মেটাক্লাস এবং মেটাক্লাস এর প্রাথমিক মান নির্ধারণের জন্য দায়ী _var:

>>> class foo_meta(type):
...     def __init__(cls, *args, **kwargs):
...         cls._var = 5
...     @property
...     def var(cls):
...         return cls._var
...     @var.setter
...     def var(cls, value):
...         cls._var = value
...
>>> class foo(metaclass=foo_meta):
...     pass
...
>>> foo.var
5
>>> foo.var = 3
>>> foo.var
3

1
পাইথন ৩.২ এ এটি আমার পক্ষে কাজ করবে বলে মনে হয় না। আমি যদি foo পরিবর্তন করি। "foo.var" সম্পাদন করার সময় অবজেক্ট 'foo' এর কোনও বৈশিষ্ট্য 'var' "নেই।
মাইকেল কেলি

সিগ ডাবল সংশোধন: এটি পাইথন ২.7 এ কাজ করে তবে পাইথন ৩.২ নয়।
মাইকেল কেলি

@ মিশেলকেলি - এটি কারণ মেটাক্লাসের
ম্যাক

1
আমি বুঝতে যথেষ্ট নিশ্চিত নই, তখন এটি লেখার পাইথন ৩.x উপায় কী হবে?
সিলভাইনড

8
@ জোসে: আপনাকে প্রথমে মেটাক্লাসটি সংজ্ঞায়িত করতে হবে, তারপরে নতুন class Foo(metaclass=...)সিনট্যাক্স ব্যবহার করে ক্লাসটি সংজ্ঞায়িত করতে হবে ।
কেভিন 0

69

পড়া পাইথন 2.2 রিলিজ নোট, আমি নিম্নলিখিত পাবেন।

যখন সম্পত্তিটি ইনস্ট্যান্ট অ্যাট্রিবিউট (সি ()। X) এর পরিবর্তে ক্লাস অ্যাট্রিবিউট (Cx) হিসাবে অ্যাক্সেস করা হয় তখন [কোনও সম্পত্তির] পাওয়ার পদ্ধতিটি কল করা হবে না। শ্রেণীর বৈশিষ্ট্য হিসাবে ব্যবহৃত হওয়ার জন্য আপনি যদি __get__ অপারেশনটিকে ওভাররাইড করতে চান তবে আপনি সম্পত্তিটি সাবক্লাস করতে পারেন - এটি নিজেই একটি নতুন ধরণের ধরণের - এর __get__ পদ্ধতিটি প্রসারিত করতে, বা আপনি কোনও নতুন তৈরি করে স্ক্র্যাচ থেকে কোনও বর্ণনাকারী টাইপ সংজ্ঞায়িত করতে পারেন স্টাইল ক্লাস যা __get__, __set__ এবং __ মোছা__ পদ্ধতিগুলি নির্ধারণ করে।

দ্রষ্টব্য: নীচের পদ্ধতিটি প্রকৃতপক্ষে কেবলমাত্র গেটারদের জন্য কাজ করে না।

অতএব, আমি বিশ্বাস করি যে নির্ধারিত সমাধানটি হ'ল সম্পত্তির সাবক্লাস হিসাবে শ্রেণিপ্রোপার্টি তৈরি করা।

class ClassProperty(property):
    def __get__(self, cls, owner):
        return self.fget.__get__(None, owner)()

class foo(object):
    _var=5
    def getvar(cls):
        return cls._var
    getvar=classmethod(getvar)
    def setvar(cls,value):
        cls._var=value
    setvar=classmethod(setvar)
    var=ClassProperty(getvar,setvar)

assert foo.getvar() == 5
foo.setvar(4)
assert foo.getvar() == 4
assert foo.var == 4
foo.var = 3
assert foo.var == 3

তবে সেটাররা আসলে কাজ করে না:

foo.var = 4
assert foo.var == foo._var # raises AssertionError

foo._var অপরিবর্তিত, আপনি কেবল নতুন মান দিয়ে সম্পত্তিটি ওভাররাইট করেছেন।

আপনি ClassPropertyএকটি সজ্জা হিসাবে ব্যবহার করতে পারেন :

class foo(object):
    _var = 5

    @ClassProperty
    @classmethod
    def var(cls):
        return cls._var

    @var.setter
    @classmethod
    def var(cls, value):
        cls._var = value

assert foo.var == 5

20
আমি মনে করি না ক্লাসপ্রপারটির সেটার অংশটি বাস্তবে বর্ণিত হিসাবে কাজ করে: উদাহরণের বক্তব্যগুলি শেষ হয়ে গেলে, foo._var == 4 (3 হিসাবে নয়, উল্লিখিত)। সম্পত্তি ক্লোবারদের সম্পত্তি সেট করে। অজগর-দেবের উপর যখন শ্রেণি-সম্পত্তি নিয়ে আলোচনা করা হত তখন এটি চিহ্নিত করা হয়েছিল যে গেটাররা তুচ্ছ, সেটটারগুলি মেটাক্লাস ছাড়াই কঠিন (অসম্ভব?)
গ্যাব্রিয়েল গ্রান্ট

4
@ গ্যাব্রিয়েল পুরোপুরি সঠিক। আমি বিশ্বাস করতে পারি না যে দু'বছরের জন্য কেউ এটিকে নির্দেশ করেনি।
agf

আমি নিশ্চিত না কেন আপনি এখানে কেন একেবারেই ব্যবহার self.fget(owner)করার প্রয়োজনটি ব্যবহার করেন না এবং সরান না কেন @classmethod? (যে কী classmethod করে , অনুবাদ .__get__(instance, owner)(*args, **kwargs)করতে function(owner, *args, **kwargs)কল, মধ্যস্থতার মাধ্যমে; বৈশিষ্ট্য মধ্যবর্তী প্রয়োজন হবে না)।
মার্টিজন পিটারস

আপনার বিক্ষোভকারী গ্রাহক বা সেটারে যে কোনও প্রকৃত রূপান্তর ঘাটতি রয়েছে যে ঝরঝরেভাবে দেখিয়ে দেবে যে আপনার foo.var = 3কার্যভারটি বাস্তবে সম্পত্তির মধ্য দিয়ে যায় না এবং এর পরিবর্তে সম্পত্তি সংস্থাকে কেবল fooপূর্ণসংখ্যার সাথে প্রতিস্থাপন করে । যদি আপনি assert isinstance(foo.__dict__['var'], ClassProperty)নিজের দাবিগুলির মধ্যে কল যুক্ত করেন তবে আপনি দেখতে পাবেন যে foo.var = 3মৃত্যুদন্ড কার্যকর হওয়ার পরে এটি ব্যর্থ হয়।
মার্টিজন পিটারস

1
পাইথন শ্রেণীর সেটিং উপর বাঁধাই সমর্থন বর্ণনাকারী না বর্গ নিজেই , শুধুমাত্র পেয়ে (তাই instance.attr, instance.attr = valueএবং del instance.attrসব বেঁধে বর্ণনাকারী পাওয়া হবে type(instance), কিন্তু classobj.attrশুশ্রূষা, classobj.attr = valueএবং del classobj.attrনা না এবং এর পরিবর্তে প্রতিস্থাপন বা বর্ণনাকারী বস্তুর নিজেই মোছা)। আপনার সেটিং এবং মুছে ফেলা (ক্লাস অবজেক্টটি উদাহরণ হিসাবে তৈরি করা এবং মেটাক্লাস টাইপটি তৈরি করা) সমর্থন করার জন্য আপনার একটি মেটাক্লাসের প্রয়োজন।
মার্টিজন পিটারস

56

আমি আশা করি এই মৃত-সরল কেবল পঠনযোগ্য @classpropertyসাজসজ্জা কারও কারও শ্রেণিকোণীর সন্ধানে সহায়তা করবে।

class classproperty(object):

    def __init__(self, fget):
        self.fget = fget

    def __get__(self, owner_self, owner_cls):
        return self.fget(owner_cls)

class C(object):

    @classproperty
    def x(cls):
        return 1

assert C.x == 1
assert C().x == 1

2
এটি কি সাবক্লাসের সাথে কাজ করে? (একটি উপশ্রেণীর শ্রেণিবিন্যাসকে ওভাররাইড করা যায়?)
জাকদানস

1
হুম? class D(C): x = 2; assert D.x == 2
dtheodor

আমি এটি ব্যবহার করতে .formatচাই যখন আমি এটি ব্যবহার করতে চাই "{x}".format(**dict(self.__class__.__dict__, **self.__dict__)):(
2rs2ts

@ নাথান কেবল নয় ... আপনি যখন এটি সেট করেন আপনি সমস্ত xঅ্যাক্সেসকে ওভাররাইড করে 10। আমি এই পদ্ধতিটি পছন্দ করি কারণ ঝরঝরে এবং সরল তবে এন্টিপ্যাটার্নের মতো মনে হচ্ছে
মিশেল ডি'আমিকো

সহজেই স্থির করা হয়েছে: ওভাররাইড প্রতিরোধের জন্য __set__এটি যুক্ত করুন ValueError
কিরণ জোনালাগদদা

30

শ্রেণিবদ্ধ সজ্জিত ফাংশনগুলির সাথে সম্পত্তি () ফাংশনটি ব্যবহার করা কি সম্ভব?

না।

যাইহোক, একটি শ্রেণিবদ্ধ একটি শ্রেণীর উপর কেবল সেই শ্রেণীর উদাহরণ থেকে অ্যাক্সেসযোগ্য একটি আবদ্ধ পদ্ধতি (আংশিক ফাংশন)।

যেহেতু উদাহরণটি ক্লাসের একটি ক্রিয়াকলাপ এবং উদাহরণটি থেকে আপনি ক্লাসটি অর্জন করতে পারেন তাই আপনি শ্রেণি-সম্পত্তি থেকে যা কিছু পছন্দ করতে পারেন তা পেতে পারেন property:

class Example(object):
    _class_property = None
    @property
    def class_property(self):
        return self._class_property
    @class_property.setter
    def class_property(self, value):
        type(self)._class_property = value
    @class_property.deleter
    def class_property(self):
        del type(self)._class_property

এই কোডটি পরীক্ষার জন্য ব্যবহার করা যেতে পারে - এটি কোনও ত্রুটি না বাড়িয়ে পাস করা উচিত:

ex1 = Example()
ex2 = Example()
ex1.class_property = None
ex2.class_property = 'Example'
assert ex1.class_property is ex2.class_property
del ex2.class_property
assert not hasattr(ex1, 'class_property')

এবং মনে রাখবেন যে আমাদের মোটেও মেটাক্লাসের প্রয়োজন হয়নি - এবং আপনি কোনওভাবেই ক্লাসের উদাহরণগুলির মাধ্যমে কোনও মেটাক্লাস অ্যাক্সেস করেন না।

একটি @classpropertyসজ্জা লেখক

আপনি classpropertyসাবক্লাসিং করে কোডের কয়েকটি লাইনটিতে প্রকৃতপক্ষে একটি সজ্জা তৈরি করতে পারেন property(এটি সি তে প্রয়োগ করা হয়েছে, তবে আপনি এখানে পাইথন সমতুল্য দেখতে পারেন ):

class classproperty(property):
    def __get__(self, obj, objtype=None):
        return super(classproperty, self).__get__(objtype)
    def __set__(self, obj, value):
        super(classproperty, self).__set__(type(obj), value)
    def __delete__(self, obj):
        super(classproperty, self).__delete__(type(obj))

তারপরে সাজসজ্জারকে এমন আচরণ করুন যেন এটি সম্পত্তির সাথে মিলিত কোনও শ্রেণিবদ্ধ thod

class Foo(object):
    _bar = 5
    @classproperty
    def bar(cls):
        """this is the bar attribute - each subclass of Foo gets its own.
        Lookups should follow the method resolution order.
        """
        return cls._bar
    @bar.setter
    def bar(cls, value):
        cls._bar = value
    @bar.deleter
    def bar(cls):
        del cls._bar

এবং এই কোডটি ত্রুটি ছাড়াই কাজ করা উচিত:

def main():
    f = Foo()
    print(f.bar)
    f.bar = 4
    print(f.bar)
    del f.bar
    try:
        f.bar
    except AttributeError:
        pass
    else:
        raise RuntimeError('f.bar must have worked - inconceivable!')
    help(f)  # includes the Foo.bar help.
    f.bar = 5

    class Bar(Foo):
        "a subclass of Foo, nothing more"
    help(Bar) # includes the Foo.bar help!
    b = Bar()
    b.bar = 'baz'
    print(b.bar) # prints baz
    del b.bar
    print(b.bar) # prints 5 - looked up from Foo!

    
if __name__ == '__main__':
    main()

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

ক্লাসে কাজ করার জন্য সম্পত্তি পাওয়া:

উপরের দিকের দিকটি হ'ল "শ্রেণীর সম্পত্তি" ক্লাস থেকে অ্যাক্সেসযোগ্য নয়, কারণ এটি কেবল শ্রেণি থেকে ডেটা বর্ণনাকারীকে ওভাররাইট করে __dict__

তবে, আমরা এটি মেটাক্লাসে সংজ্ঞায়িত কোনও সম্পত্তি দিয়ে ওভাররাইড করতে পারি __dict__। উদাহরণ স্বরূপ:

class MetaWithFooClassProperty(type):
    @property
    def foo(cls):
        """The foo property is a function of the class -
        in this case, the trivial case of the identity function.
        """
        return cls

এবং তারপরে মেটাক্লাসের একটি শ্রেণীর উদাহরণটিতে এমন একটি সম্পত্তি থাকতে পারে যা পূর্ববর্তী বিভাগগুলিতে ইতিমধ্যে প্রদর্শিত নীতিটি ব্যবহার করে শ্রেণীর সম্পত্তি অ্যাক্সেস করে:

class FooClassProperty(metaclass=MetaWithFooClassProperty):
    @property
    def foo(self):
        """access the class's property"""
        return type(self).foo

এবং এখন আমরা উভয় উদাহরণ দেখতে পাচ্ছি

>>> FooClassProperty().foo
<class '__main__.FooClassProperty'>

এবং ক্লাস

>>> FooClassProperty.foo
<class '__main__.FooClassProperty'>

শ্রেণীর সম্পত্তি অ্যাক্সেস আছে।


3
পরিষ্কার, সংক্ষিপ্ত, পুঙ্খানুপুঙ্খ: এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
pfabri

25

পাইথন 3!

পুরানো প্রশ্ন, প্রচুর ভিউ, এক-সত্যিকারের পাইথন 3 উপায়ের জন্য খুব দরকার।

ভাগ্যক্রমে, metaclassকোয়ার্গের সাথে এটি সহজ :

class FooProperties(type):

    @property
    def var(cls):
        return cls._var

class Foo(object, metaclass=FooProperties):
    _var = 'FOO!'

তারপর, >>> Foo.var

'যদি foo!'


1
এটি বলতে হবে যে বাক্স থেকে
বেরোনোর

@ মেমমেট এটি কি সহজ নয়? Fooএটি এর মেটাক্লাসের উদাহরণ, এবং @propertyএর পদ্ধতির জন্য যেমন ব্যবহার করা যায় তেমনি উদাহরণগুলির জন্য এটি ব্যবহার করা যেতে পারে Foo
ওজেফোর্ড

2
আপনাকে ক্লাসের জন্য অন্য শ্রেণীর সংজ্ঞা দিতে হয়েছিল, সেটি দ্বিগুণ জটিলতা ধরে নিয়ে মেটাক্লাস পুনরায় ব্যবহারযোগ্য নয়।
মেহমেট

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

1
@ অ্যারোনহল যদি এটি গুরুত্বপূর্ণ হয় তবে এটি সহজেই যুক্ত করা যায় Foo.__new__। যদিও সেই মুহুর্তে এটির পরিবর্তে গেটট্রিবিউট ব্যবহার করা মূল্যবান হতে পারে, বা কোনও ভাষা বৈশিষ্ট্য উপস্থিত রয়েছে বলে ভান করা যদি সত্যই হয় তবে আপনি একেবারেই নিতে চান এমন পন্থা really
ওজেফোর্ড

16

পাইথনে কাজ করার জন্য এই "শ্রেণীর সম্পত্তি" সিস্টেমটি করার কোনও যুক্তিসঙ্গত উপায় নেই।

এটি কার্যকর করার জন্য এখানে একটি অযৌক্তিক উপায়। আপনি ক্রমবর্ধমান পরিমাণে মেটাক্লাস যাদুতে এটি আরও বিজোড় করতে পারেন।

class ClassProperty(object):
    def __init__(self, getter, setter):
        self.getter = getter
        self.setter = setter
    def __get__(self, cls, owner):
        return getattr(cls, self.getter)()
    def __set__(self, cls, value):
        getattr(cls, self.setter)(value)

class MetaFoo(type):
    var = ClassProperty('getvar', 'setvar')

class Foo(object):
    __metaclass__ = MetaFoo
    _var = 5
    @classmethod
    def getvar(cls):
        print "Getting var =", cls._var
        return cls._var
    @classmethod
    def setvar(cls, value):
        print "Setting var =", value
        cls._var = value

x = Foo.var
print "Foo.var = ", x
Foo.var = 42
x = Foo.var
print "Foo.var = ", x

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

আপনি যদি মোটামুটি উন্নত কাঠামোটি প্রয়োগ করেন তবে আপনাকে কেবল এই ধরণের জিনিসগুলি বোঝার প্রয়োজন। স্বচ্ছ বস্তুর অধ্যবসায় বা আরপিসি সিস্টেমের মতো, বা এক ধরণের ডোমেন-নির্দিষ্ট ভাষার মতো।

তবে, পূর্বের উত্তরের মন্তব্যে আপনি বলেছেন যে আপনি you

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

আমার কাছে মনে হচ্ছে, আপনি যা চান তা হ'ল একটি পর্যবেক্ষক ডিজাইনের ধরণ।


আমি কোড উদাহরণটির ধারণাটি পছন্দ করি তবে মনে হয় এটি অনুশীলনে কিছুটা বিশৃঙ্খল হবে।
মার্ক রডি

আমি যেটি সম্পাদন করতে চাইছি তা হ'ল বেশ সোজা ফরোয়ার্ড সেট করা এবং একটি একক বৈশিষ্ট্য প্রাপ্তি যা সমস্ত দৃষ্টান্তের আচরণটি পরিবর্তন করতে পতাকা হিসাবে ব্যবহৃত হয় তাই আমি মনে করি যে আমি যা করতে চেষ্টা করছি তার জন্য পর্যবেক্ষককে আচ্ছন্ন করে দেওয়া হবে। যদি প্রশ্নে একাধিক বৈশিষ্ট্য থাকে তবে আমি আরও ঝোঁক হব।
মার্ক রডি

দেখে মনে হচ্ছে যে কেবলমাত্র ফাংশনগুলি জনসাধারণের কাছে করা এবং তাদের সরাসরি কল করা সহজ সরলতার সমাধান ছিল। আমি কৌতুহল ছিলাম যদি আমি কিছু ভুল করে যাচ্ছিলাম বা যদি আমি চেষ্টা করে যাচ্ছিলাম তবে এটি অসম্ভব ছিল। উপায় দ্বারা একাধিক মন্তব্য সম্পর্কে দুঃখিত। 300 অক্ষর সীমা sucks।
মার্ক রডি 21

কোড উদাহরণের জন্য নিফটি বিষয়টি হ'ল আপনি একবারে সমস্ত ক্লানকি বিটগুলি প্রয়োগ করতে পারেন এবং তারপরে তাদের উত্তরাধিকারী হতে পারেন। কেবলমাত্র _varটিকে উত্পন্ন শ্রেণিতে স্থানান্তর করুন। ক্লাস ডি 1 (ফু): _var = 21 ক্লাস ডি 2 (ফু) _ভর = "হ্যালো" ডি 1.var 21 ডি 2.var হ্যালো
থমাস এল

6

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

#!/usr/bin/python

class classproperty(property):
    def __get__(self, obj, type_):
        return self.fget.__get__(None, type_)()

    def __set__(self, obj, value):
        cls = type(obj)
        return self.fset.__get__(None, cls)(value)

class A (object):

    _foo = 1

    @classproperty
    @classmethod
    def foo(cls):
        return cls._foo

    @foo.setter
    @classmethod
    def foo(cls, value):
        cls.foo = value

a = A()

print a.foo

b = A()

print b.foo

b.foo = 5

print a.foo

A.foo = 10

print b.foo

print A.foo

3

অর্ধ সমাধান, ক্লাসে __set__ কাজ করে না, এখনও। সমাধান হ'ল একটি কাস্টম সম্পত্তি সম্পত্তি যা একটি সম্পত্তি এবং একটি স্ট্যাটিকমেডিক উভয়ই প্রয়োগ করে

class ClassProperty(object):
    def __init__(self, fget, fset):
        self.fget = fget
        self.fset = fset

    def __get__(self, instance, owner):
        return self.fget()

    def __set__(self, instance, value):
        self.fset(value)

class Foo(object):
    _bar = 1
    def get_bar():
        print 'getting'
        return Foo._bar

    def set_bar(value):
        print 'setting'
        Foo._bar = value

    bar = ClassProperty(get_bar, set_bar)

f = Foo()
#__get__ works
f.bar
Foo.bar

f.bar = 2
Foo.bar = 3 #__set__ does not

3

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

আপনার কি ক্লাসের কমপক্ষে একটি ইভেন্টে অ্যাক্সেস রয়েছে? আমি তখন এটি করার কোনও উপায় সম্পর্কে ভাবতে পারি:

class MyClass (object):
    __var = None

    def _set_var (self, value):
        type (self).__var = value

    def _get_var (self):
        return self.__var

    var = property (_get_var, _set_var)

a = MyClass ()
b = MyClass ()
a.var = "foo"
print b.var

2

এটি ব্যবহার করে দেখুন, প্রচুর বিদ্যমান কোড পরিবর্তন / যুক্ত না করেই কাজটি সম্পন্ন হয়।

>>> class foo(object):
...     _var = 5
...     def getvar(cls):
...         return cls._var
...     getvar = classmethod(getvar)
...     def setvar(cls, value):
...         cls._var = value
...     setvar = classmethod(setvar)
...     var = property(lambda self: self.getvar(), lambda self, val: self.setvar(val))
...
>>> f = foo()
>>> f.var
5
>>> f.var = 3
>>> f.var
3

propertyফাংশন দুই দরকার callableআর্গুমেন্ট। তাদের ল্যাম্বদা র‌্যাপারগুলি দিন (এটি এটি প্রথম যুক্তি হিসাবে দৃষ্টান্তটি পাস করে) এবং সবকিছু ঠিক আছে।


ফ্লোরিয়ান বুশ যেমন উল্লেখ করেছেন, সিনট্যাক্সগুলি প্রয়োজনীয় (তৃতীয় পক্ষের লাইব্রেরি বা উত্তরাধিকার কোড দ্বারা) foo.var।
থমাস এল Holaday

2

এখানে এমন একটি সমাধান রয়েছে যা ক্লাসের মাধ্যমে অ্যাক্সেস এবং মেটাক্লাস ব্যবহার করে এমন দৃষ্টান্তের মাধ্যমে অ্যাক্সেস উভয়ের জন্য কাজ করা উচিত।

In [1]: class ClassPropertyMeta(type):
   ...:     @property
   ...:     def prop(cls):
   ...:         return cls._prop
   ...:     def __new__(cls, name, parents, dct):
   ...:         # This makes overriding __getattr__ and __setattr__ in the class impossible, but should be fixable
   ...:         dct['__getattr__'] = classmethod(lambda cls, attr: getattr(cls, attr))
   ...:         dct['__setattr__'] = classmethod(lambda cls, attr, val: setattr(cls, attr, val))
   ...:         return super(ClassPropertyMeta, cls).__new__(cls, name, parents, dct)
   ...:

In [2]: class ClassProperty(object):
   ...:     __metaclass__ = ClassPropertyMeta
   ...:     _prop = 42
   ...:     def __getattr__(self, attr):
   ...:         raise Exception('Never gets called')
   ...:

In [3]: ClassProperty.prop
Out[3]: 42

In [4]: ClassProperty.prop = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-e2e8b423818a> in <module>()
----> 1 ClassProperty.prop = 1

AttributeError: can't set attribute

In [5]: cp = ClassProperty()

In [6]: cp.prop
Out[6]: 42

In [7]: cp.prop = 1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-e8284a3ee950> in <module>()
----> 1 cp.prop = 1

<ipython-input-1-16b7c320d521> in <lambda>(cls, attr, val)
      6         # This makes overriding __getattr__ and __setattr__ in the class impossible, but should be fixable
      7         dct['__getattr__'] = classmethod(lambda cls, attr: getattr(cls, attr))
----> 8         dct['__setattr__'] = classmethod(lambda cls, attr, val: setattr(cls, attr, val))
      9         return super(ClassPropertyMeta, cls).__new__(cls, name, parents, dct)

AttributeError: can't set attribute

এটি মেটাক্লাসে সংজ্ঞায়িত সেটারের সাথেও কাজ করে।


1

বিভিন্ন স্থান অনুসন্ধান করার পরে আমি পাইথন 2 এবং 3 এর সাথে বৈধ শ্রেণিবদ্ধের সংজ্ঞা দেওয়ার একটি পদ্ধতি পেয়েছি।

from future.utils import with_metaclass

class BuilderMetaClass(type):
    @property
    def load_namespaces(self):
        return (self.__sourcepath__)

class BuilderMixin(with_metaclass(BuilderMetaClass, object)):
    __sourcepath__ = 'sp'        

print(BuilderMixin.load_namespaces)

আশা করি এটি কারও সাহায্য করতে পারে :)


1
এই পদ্ধতিটি যদি আপনার কোথাও পাওয়া যায় তবে একটি লিঙ্ক দেওয়া ভাল হবে ( অন্যের লিখিত সামগ্রীর রেফারেন্স কীভাবে দেখুন )
অ্যান্ড্রু মায়ার্স

-27

এখানে আমার পরামর্শ। ক্লাস পদ্ধতি ব্যবহার করবেন না।

সিরিয়াসলি।

এক্ষেত্রে শ্রেণিক পদ্ধতি ব্যবহারের কারণ কী? কেন একটি সাধারণ শ্রেণির একটি সাধারণ বিষয় নেই?


আপনি যদি কেবল মানটি পরিবর্তন করতে চান তবে কোনও সম্পত্তি আসলেই খুব সহায়ক হয় না এটি? কেবল অ্যাট্রিবিউট মানটি সেট করুন এবং এটি দিয়ে সম্পন্ন করুন।

গোপন করার মতো কিছু আছে তবেই কোনও সম্পত্তি ব্যবহার করা উচিত - এমন কিছু যা ভবিষ্যতের বাস্তবায়নে পরিবর্তিত হতে পারে।

হতে পারে আপনার উদাহরণটি একেবারে ছিটকে গেছে, এবং এমন কিছু নরক গণনা রয়েছে যা আপনি রেখে গেছেন। তবে দেখে মনে হচ্ছে না সম্পত্তিটি উল্লেখযোগ্য মান যুক্ত করে।

জাভা প্রভাবিত "গোপনীয়তা" কৌশলগুলি (পাইথনে, বিশিষ্ট নামগুলি _ _ দিয়ে শুরু হয়) আসলে খুব বেশি সহায়ক নয়। কার কাছ থেকে প্রাইভেট? আপনার উত্সটি থাকলে (ব্যক্তিগতভাবে যেমন পাইথনে করেন private

জাভা-প্রভাবিত EJB- স্টাইলের getters এবং সেটারগুলি (প্রায়শই পাইথনের বৈশিষ্ট্য হিসাবে সম্পন্ন হয়) জাভাটির আদিম অন্তর্মুখীকরণের পাশাপাশি স্ট্যাটিক ল্যাঙ্গুয়েজ সংকলক দিয়ে মাস্টার পাস করার জন্য রয়েছে। এই সমস্ত getters এবং setters পাইথনে তেমন সহায়ক নয়।


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