गतिशील रूप से वर्ग में संपत्ति कैसे जोड़ें?


215

लक्ष्य एक मॉक क्लास बनाना है जो db परिणाम की तरह व्यवहार करता है।

उदाहरण के लिए, यदि कोई डेटाबेस क्वैक्शन देता है, एक तानाशाही अभिव्यक्ति का उपयोग करके {'ab':100, 'cd':200}, तो मैं देखना चाहूंगा:

>>> dummy.ab
100

पहले मुझे लगा कि शायद मैं इसे इस तरह से कर सकता हूं:

ks = ['ab', 'cd']
vs = [12, 34]
class C(dict):
    def __init__(self, ks, vs):
        for i, k in enumerate(ks):
            self[k] = vs[i]
            setattr(self, k, property(lambda x: vs[i], self.fn_readyonly))

    def fn_readonly(self, v)
        raise "It is ready only"

if __name__ == "__main__":
    c = C(ks, vs)
    print c.ab

लेकिन c.abइसके बजाय एक संपत्ति वस्तु देता है।

setattrलाइन को बदलने k = property(lambda x: vs[i])से कोई फायदा नहीं है।

तो रनटाइम पर इंस्टेंस प्रॉपर्टी बनाने का सही तरीका क्या है?

PS मुझे इस बात की जानकारी है कि प्रस्तुत विधि का उपयोग कैसे __getattribute__किया जाता है?


2
आपके कोड में कुछ टाइपो हैं: fn_readonly की परिभाषा को एक :और __init__संदर्भ की आवश्यकता है self.fn_readyonly
शावके

तुम सही हो। मैंने रनटाइम में एक संपत्ति बनाने के कारण को रेखांकित करने के लिए अंतिम मिनट में उस सेटर फ़ंक्शन को जोड़ा।
एंथनी कोंग

आरंभिककरण पर गुण बनाने के साथ मेरे पास मुख्य मुद्दा यह था कि, कुछ मामलों में अगर मैंने मदद करने वालों को जल्दी बुलाया, या कोई समस्या थी, तो मुझे एक त्रुटि मिलेगी कि वे इस तथ्य के बावजूद मौजूद नहीं थे कि वे करते हैं। नीचे दिए गए मेरे समाधान में, मैं 2 कक्षाएं बनाता हूं। एक आधार / माता-पिता के रूप में (जो मैं बचने के लिए एक समाधान खोजने की कोशिश कर रहा हूं), और मुख्य वस्तु, जो आधार / माता-पिता का विस्तार करता है। फिर, मुख्य ऑब्जेक्ट में, बिना शुरुआती, मैं अपने AccessorFunc निर्माता को कॉल करता हूं जो गुण, सहायक कार्य, और बहुत कुछ बनाता है।
ऐसकूल

यानी: वर्ग उदाहरणबस: पास; वर्ग उदाहरण (उदाहरणबेस): __x = एक्सेसर (उदाहरणबेस, 'x', 'X', 123); --- जो एक्स के तहत एक संपत्ति का निर्माण करेगा और एक्स के नाम से कार्यों का नाम होगा, इसलिए गेटएक्स, सेटएक्स, और अधिक ... और संपत्ति के लिए .x, .x, और .__ x। तो .x डेटा के माध्यम से स्वयं को प्राप्त करने के लिए संपत्ति है (स्वयं के माध्यम से प्राप्त करना / स्थापित करना। 123 = या उत्पादन के लिए स्व। X)। मैंने संग्रहीत डेटा के लिए self._x का उपयोग किया, इसलिए यह आसानी से सुलभ हो सकता है क्योंकि मैंने भी संग्रहीत डेटा में उन्हें सेट किए बिना डिफ़ॉल्ट मानों को असाइन करने की अनुमति दी थी। इसलिए _x कोई नहीं हो सकता है और .x 123 वापस आ सकता है। और।
Access

यहां मूल संस्करण का एक लिंक है जो गतिशील गुण बनाता है, और गतिशील फ़ंक्शन - फ़ाइल में अन्य संस्करणों के लिंक का एक गुच्छा है। एक सहायक का उपयोग करने के लिए एक फ़ंक्शन का उपयोग कर AccessorFunc प्रणाली है (एक कार्य के लिए, गुणों के लिए एक, दोनों के लिए एक व्यक्तिगत तत्व के रूप में - इसलिए यह उस फ़ाइल में किसी भी चीज में कोड छोटा करने का उपयोग नहीं करता है) .. अगर कुछ भी याद नहीं है, तो एक में से एक अन्य फाइलों में यह है: dropbox.com/s/phnnuavssmzeqrr/dynamic_properties_simple.py?dl=0
Acecool

जवाबों:


333

मुझे लगता है कि मुझे इस उत्तर का विस्तार करना चाहिए, अब जब मैं बड़ा और समझदार हूं और जानता हूं कि क्या चल रहा है। देर आए दुरुस्त आए।

आप एक क्लास में एक संपत्ति को गतिशील रूप से जोड़ सकते हैं। लेकिन यह पकड़ है: आपको इसे कक्षा में जोड़ना होगा ।

>>> class Foo(object):
...     pass
... 
>>> foo = Foo()
>>> foo.a = 3
>>> Foo.b = property(lambda self: self.a + 1)
>>> foo.b
4

A propertyवास्तव में एक डिस्क्रिप्टर नामक चीज़ का एक सरल कार्यान्वयन है । यह एक ऐसी वस्तु है जो किसी दिए गए वर्ग पर एक विशेष विशेषता के लिए कस्टम हैंडलिंग प्रदान करती है । एक विशाल ifपेड़ को बाहर करने के लिए एक तरह से किंडा __getattribute__

जब मैं के लिए पूछ foo.bऊपर के उदाहरण में, अजगर देखता है कि bवर्ग के औजार पर परिभाषित वर्णनकर्ता प्रोटोकॉल -which बस इसे एक साथ एक वस्तु का मतलब __get__, __set__या __delete__विधि। वर्णनकर्ता उस विशेषता को संभालने के लिए ज़िम्मेदारी का दावा करता है, इसलिए पायथन कॉल करता है Foo.b.__get__(foo, Foo), और वापसी मूल्य आपको विशेषता के मूल्य के रूप में वापस दिया जाता है। के मामले में property, इन तरीकों में से प्रत्येक सिर्फ कॉल fget, fsetया fdelआप के लिए पारित propertyनिर्माता।

Descriptors वास्तव में Python का तरीका है जो इसके पूरे OO कार्यान्वयन की नलसाजी को उजागर करता है। वास्तव में, वर्णनकर्ता का एक और प्रकार है जो इससे भी अधिक सामान्य है property

>>> class Foo(object):
...     def bar(self):
...         pass
... 
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x7f2a439d5dd0>>
>>> Foo().bar.__get__
<method-wrapper '__get__' of instancemethod object at 0x7f2a43a8a5a0>

विनम्र विधि वर्णनकर्ता का एक और प्रकार है। __get__पहली दलील के रूप में कॉलिंग इंस्टेंस पर इसकी कमी; वास्तव में, यह ऐसा करता है:

def __get__(self, instance, owner):
    return functools.partial(self.function, instance)

वैसे भी, मुझे इस बात पर संदेह है कि वर्णक केवल कक्षाओं पर काम क्यों करते हैं: वे उस सामान का एक औपचारिककरण करते हैं जो पहली जगह में शक्तियों का वर्ग करता है। वे नियम के अपवाद भी हैं: आप स्पष्ट रूप से एक वर्ग के लिए वर्णनकर्ता असाइन कर सकते हैं, और कक्षाएं स्वयं के उदाहरण हैं type! वास्तव में, Foo.bअभी भी कॉल पढ़ने की कोशिश कर रहा है property.__get__; वर्ग विशेषताओं के रूप में एक्सेस होने पर खुद को वापस करने के लिए विवरणकर्ताओं के लिए यह केवल मुहावरेदार है।

मुझे लगता है कि यह बहुत अच्छा है कि वास्तव में अजगर के ओओ सिस्टम के सभी पायथन में व्यक्त किए जा सकते हैं। :)

ओह, और मैंने कुछ समय पहले यदि आप रुचि रखते हैं, तो वर्णनकर्ताओं के बारे में एक चिंताजनक ब्लॉग पोस्ट लिखी ।


35
Add_property पद्धति को जोड़ने की आवश्यकता नहीं है। setattr (Foo, 'name', property (func))
कोर्टनी डी

8
आपका "लेकिन वह कैच है ..." बस मुझे कई घंटों के काम से बचाया। धन्यवाद।
मैट हॉवेल

2
यदि आप किसी एकल उदाहरण पर किसी संपत्ति को परिभाषित करना चाहते हैं, तो आप रनटाइम पर एक क्लास बना सकते हैं और __class__ को संशोधित कर सकते हैं
विल्फ्रेड ह्यूजेस

1
@ myproperty.setter के बारे में क्या? इसे रात्रिभोज में कैसे जोड़ा जाए?
LRMAAX

आपको एक प्रारंभिक ऑब्जेक्ट में एक संपत्ति जोड़ने की आवश्यकता नहीं है। ऐसा करने का मतलब यह हो सकता है कि यह केवल उदाहरण से जुड़ा हो, लेकिन मुझे इसकी दोहरी जांच करनी होगी। मुझे पता है कि मैं इसी तरह के मुद्दे पर भाग गया था, जहां मेरे गतिशील गुण केवल उदाहरण थे, मैं एक स्थिर सेटअप के साथ भी समाप्त हो गया था और जो मैं चाहता था कि वह वस्तु है जो कि भविष्य के प्रारंभिककरण उनका उपयोग करेगा। मेरी पोस्ट नीचे है और यह सहायक कार्यों को बनाता है, और आसानी से सब कुछ एक्सेस करने के आसान तरीके। प्रॉपर्टी के लिए .x। कच्चे डेटा के लिए ._x गेट्टर / सेटर का उपयोग करता है (जो कोई भी नहीं हो सकता है), और एक्सेसरी ऑब्जेक्ट के लिए .__ x है।
ऐस्कूल

57

लक्ष्य एक मॉक क्लास बनाना है जो db परिणाम की तरह व्यवहार करता है।

तो आप जो चाहते हैं वह एक शब्दकोश है जहाँ आप एक ['बी'] को ऐब्स के रूप में पेश कर सकते हैं।

यह आसान है:

class atdict(dict):
    __getattr__= dict.__getitem__
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

1
अधिक सामान्य सेटअप में, यह सीमित उद्देश्य को पूरा करता है। यदि ताना में बहुस्तरीय पदानुक्रम है, जैसे d = {'a1': {'b': 'c'}, 'a2': ...}, तो जब आप d.a1 या d.a2 कर सकते हैं, तो आप कर सकते हैं ' t do d.a1.b
श्रेयस

1
ध्यान में रखने की एक बात यह है कि इस dict तरीकों या विशेषताओं के रूप में एक ही नाम के साथ विशेषताओं के लिए विशेषता मान स्थापित करने की अनुमति देता है, लेकिन एक ही रास्ता फिर से मूल्यों को पुन: प्राप्त अनुमति नहीं देता: d.items = 1, d.itemsरिटर्न <built-in method items of atdict object at ...>। आप इसके बजाय अभी भी कर सकते हैं d["items"]या उपयोग कर सकते हैं , लेकिन यह अधिकांश तानाशाह तरीकों का उपयोग __getattribute__करने से __getattr__रोकता है।
19con में Marcono1234

बस चबाना पुस्तकालय का उपयोग करें ! (गुच्छा का कांटा)
ब्रायन पीटरसन

38

ऐसा लगता है कि आप इस समस्या को बहुत आसानी से हल कर सकते हैं namedtuple, क्योंकि आप समय से पहले खेतों की पूरी सूची जानते हैं।

from collections import namedtuple

Foo = namedtuple('Foo', ['bar', 'quux'])

foo = Foo(bar=13, quux=74)
print foo.bar, foo.quux

foo2 = Foo()  # error

यदि आपको अपने स्वयं के सेटर को लिखने की आवश्यकता है, तो आपको कक्षा स्तर पर मेटाप्रोग्रामिंग करना होगा; property()उदाहरणों पर काम नहीं करता है।


महान विचार। दुर्भाग्य से मैं इस समय अजगर 2.4 के साथ फंस गया हूं।
एंथनी कोंग


2
जिस आदमी ने लिखा है namedtupleवह वफादार वस्तु-उन्मुख सिद्धांतों के लिए इसे सुचारू और सुरुचिपूर्ण बनाने के लिए एक पुरस्कार का हकदार है।
कीथ पिंसन

4
क्षमा करें, कम से कम, यह उत्तर केवल उस विशेष मामले पर लागू होता है जहां एक वाडा वर्ग जिसमें केवल पढ़ने के लिए केवल विशेषताएँ होती हैं, जो सभी पहले से जानते हैं। दूसरे शब्दों में, मुझे नहीं लगता कि यह सामान्य गुणों को जोड़ने के व्यापक प्रश्न को संबोधित करता है - न केवल पढ़ने के लिए - केवल रनटाइम पर एक वर्ग के लिए (और न ही दूसरे "ऐड-ऑन" उत्तर का वर्तमान संस्करण भी) लेखक द्वारा पोस्ट किया गया)।
मार्टिउ

@ मार्टीन्यू तो ... और अधिक तर्क पारित करने के लिए property()? या तो उत्तर में कुछ भी नहीं है जो केवल पढ़ने के लिए विशिष्ट है।
ईवे

32

आपको इसके लिए किसी प्रॉपर्टी का उपयोग करने की आवश्यकता नहीं है। बस __setattr__उन्हें केवल पढ़ने के लिए ओवरराइड करें।

class C(object):
    def __init__(self, keys, values):
        for (key, value) in zip(keys, values):
            self.__dict__[key] = value

    def __setattr__(self, name, value):
        raise Exception("It is read only!")

टाडा।

>>> c = C('abc', [1,2,3])
>>> c.a
1
>>> c.b
2
>>> c.c
3
>>> c.d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'd'
>>> c.d = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __setattr__
Exception: It is read only!
>>> c.a = 'blah'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __setattr__
Exception: It is read only!

9

एक अजगर वर्ग को गतिशील रूप से संपत्ति कैसे जोड़ें?

कहते हैं कि आपके पास एक वस्तु है जिसे आप एक संपत्ति जोड़ना चाहते हैं। आमतौर पर, मैं गुणों का उपयोग करना चाहता हूं जब मुझे कोड में एक विशेषता तक पहुंच का प्रबंधन शुरू करना पड़ता है जिसमें डाउनस्ट्रीम उपयोग होता है, ताकि मैं एक सुसंगत एपीआई बनाए रख सकूं। अब मैं आम तौर पर उन्हें स्रोत कोड में जोड़ूंगा जहां ऑब्जेक्ट परिभाषित किया गया है, लेकिन मान लें कि आपके पास वह एक्सेस नहीं है, या आपको प्रोग्रामेटिक रूप से अपने कार्यों को सही मायने में चुनने की आवश्यकता है।

एक वर्ग बनाएँ

के लिए प्रलेखन केproperty आधार पर एक उदाहरण का उपयोग करते हुए , आइए एक "छिपी" विशेषता के साथ ऑब्जेक्ट का एक वर्ग बनाएं और इसका एक उदाहरण बनाएं:

class C(object):
    '''basic class'''
    _x = None

o = C()

पायथन में, हम चीजों को करने का एक स्पष्ट तरीका होने की उम्मीद करते हैं। हालांकि, इस मामले में, मैं दो तरीके दिखाने जा रहा हूं: डेकोरेटर संकेतन के साथ, और बिना। सबसे पहले, डेकोरेटर संकेतन के बिना। यह प्राप्तकर्ताओं, बसने वालों या हटाने वालों के गतिशील असाइनमेंट के लिए अधिक उपयोगी हो सकता है।

गतिशील (उर्फ बंदर पैचिंग)

चलो हमारी कक्षा के लिए कुछ बनाएँ:

def getx(self):
    return self._x

def setx(self, value):
    self._x = value

def delx(self):
    del self._x

और अब हम इन्हें प्रॉपर्टी में असाइन करते हैं। ध्यान दें कि डायनेमिक प्रश्न का उत्तर देते हुए हम अपने प्रोग्राम यहां चुन सकते हैं:

C.x = property(getx, setx, delx, "I'm the 'x' property.")

और उपयोग:

>>> o.x = 'foo'
>>> o.x
'foo'
>>> del o.x
>>> print(o.x)
None
>>> help(C.x)
Help on property:

    I'm the 'x' property.

सज्जाकार

के रूप में हम डेकोरेटर अंकन के साथ ऊपर किया हम भी ऐसा ही कर सकता है, लेकिन इस मामले में, हम चाहिए तरीकों सब एक ही नाम नाम (और मैं विशेषता के रूप में यह एक ही रखने की सलाह देते हैं), तो कार्यक्रम संबंधी काम इतनी के रूप में तुच्छ नहीं है यह उपरोक्त विधि का उपयोग कर रहा है:

@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

और इसके उपनिवेशित वर्ग और वर्ग को हटाने वाले के साथ संपत्ति ऑब्जेक्ट असाइन करें:

C.x = x

और उपयोग:

>>> help(C.x)
Help on property:

    I'm the 'x' property.

>>> o.x
>>> o.x = 'foo'
>>> o.x
'foo'
>>> del o.x
>>> print(o.x)
None

5

मैंने एक क्लास फैक्ट्री बनाने के लिए इस स्टैक ओवरफ्लो पोस्ट पर एक अनुकरणीय प्रश्न पूछा जिसने सरल प्रकार बनाए। इसका परिणाम यह था कि क्लास फैक्ट्री का कामकाजी संस्करण था। यहाँ जवाब का एक टुकड़ा है:

def Struct(*args, **kwargs):
    def init(self, *iargs, **ikwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)
        for i in range(len(iargs)):
            setattr(self, args[i], iargs[i])
        for k,v in ikwargs.items():
            setattr(self, k, v)

    name = kwargs.pop("name", "MyStruct")
    kwargs.update(dict((k, None) for k in args))
    return type(name, (object,), {'__init__': init, '__slots__': kwargs.keys()})

>>> Person = Struct('fname', 'age')
>>> person1 = Person('Kevin', 25)
>>> person2 = Person(age=42, fname='Terry')
>>> person1.age += 10
>>> person2.age -= 10
>>> person1.fname, person1.age, person2.fname, person2.age
('Kevin', 35, 'Terry', 32)
>>>

आप डिफ़ॉल्ट मूल्यों को बनाने के लिए इसका कुछ भिन्नता का उपयोग कर सकते हैं जो कि आपका लक्ष्य है (उस प्रश्न का उत्तर भी है जो इससे संबंधित है)।


4

सुनिश्चित नहीं है कि अगर मैं पूरी तरह से प्रश्न को समझता हूं, लेकिन आप __dict__अपनी कक्षा के अंतर्निहित समय के साथ इंस्टेंस गुणों को संशोधित कर सकते हैं :

class C(object):
    def __init__(self, ks, vs):
        self.__dict__ = dict(zip(ks, vs))


if __name__ == "__main__":
    ks = ['ab', 'cd']
    vs = [12, 34]
    c = C(ks, vs)
    print(c.ab) # 12

संक्षेप में मेरा सवाल यह जानना है कि क्या रनटाइम में एक नई संपत्ति बनाना संभव है। सर्वसम्मति नकारात्मक लगती है। आपका सुझाव निश्चित रूप से सरल और व्यावहारिक है। (वही अन्य जवाबों के लिए जो तानाशाह का उपयोग करता है )
एंथोनी कोंग

एक सरल उत्तर यह भी होगा: self.__dict__[key] = value
एलन कार्लसन

4

खोज इंजन से आने वालों के लिए, यहाँ दो चीजें हैं जो मैं देख रहा था जब गतिशील गुणों के बारे में बात कर रहे थे :

class Foo:
    def __init__(self):
        # we can dynamically have access to the properties dict using __dict__
        self.__dict__['foo'] = 'bar'

assert Foo().foo == 'bar'


# or we can use __getattr__ and __setattr__ to execute code on set/get
class Bar:
    def __init__(self):
        self._data = {}
    def __getattr__(self, key):
        return self._data[key]
    def __setattr__(self, key, value):
        self._data[key] = value

bar = Bar()
bar.foo = 'bar'
assert bar.foo == 'bar'

__dict__यदि आप गतिशील रूप से बनाए गए गुण लगाना चाहते हैं तो अच्छा है। __getattr__केवल तभी कुछ करना अच्छा होता है जब मूल्य की आवश्यकता होती है, जैसे डेटाबेस को क्वेरी करना। सेट / कॉम्बो कक्षा में संग्रहीत डेटा तक पहुंच को सरल बनाने के लिए अच्छा है (जैसे ऊपर दिए गए उदाहरण में)।

आप केवल एक गतिशील संपत्ति चाहते हैं, पर एक नजर है संपत्ति () में निर्मित समारोह।


4

आप property()रनटाइम पर एक नया उदाहरण नहीं जोड़ सकते हैं , क्योंकि गुण डेटा विवरणक हैं। इसके बजाय आपको गतिशील रूप से एक नया वर्ग बनाना होगा, या __getattribute__उदाहरणों पर डेटा विवरणकों को संसाधित करने के लिए अधिभार देना होगा।


ये गलत है। आप संपत्ति को वर्ग में जोड़ सकते हैं फिर इसे विधि से एक्सेस कर सकते हैं।
अहमद

2

परिभाषित करने का सबसे अच्छा तरीका परिभाषित करना है __slots__। इस तरह आपके उदाहरणों में नई विशेषताएँ नहीं हो सकती हैं।

ks = ['ab', 'cd']
vs = [12, 34]

class C(dict):
    __slots__ = []
    def __init__(self, ks, vs): self.update(zip(ks, vs))
    def __getattr__(self, key): return self[key]

if __name__ == "__main__":
    c = C(ks, vs)
    print c.ab

वह प्रिंट करता है 12

    c.ab = 33

देता है कि: AttributeError: 'C' object has no attribute 'ab'


2

बस एक और उदाहरण है कि वांछित प्रभाव कैसे प्राप्त किया जाए

class Foo(object):

    _bar = None

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        self._bar = value

    def __init__(self, dyn_property_name):
        setattr(Foo, dyn_property_name, Foo.bar)

तो अब हम सामान की तरह कर सकते हैं:

>>> foo = Foo('baz')
>>> foo.baz = 5
>>> foo.bar
5
>>> foo.baz
5

2

यहाँ एक समाधान है कि:

  • संपत्ति के नामों को तार के रूप में निर्दिष्ट करने की अनुमति देता है , इसलिए वे आपके प्रोग्राम में सूचीबद्ध होने के बजाय कुछ बाहरी डेटा स्रोत से आ सकते हैं।
  • जब क्लास को हर बार ऑब्जेक्ट बनाया जाता है , तब गुणों को जोड़ा जाता है।

वर्ग को परिभाषित करने के बाद, आप इसे गतिशील रूप से एक संपत्ति जोड़ने के लिए करते हैं:

setattr(SomeClass, 'propertyName', property(getter, setter))

यहाँ एक पूर्ण उदाहरण है, पायथन 3 में परीक्षण किया गया है:

#!/usr/bin/env python3

class Foo():
  pass

def get_x(self):
  return 3

def set_x(self, value):
  print("set x on %s to %d" % (self, value))

setattr(Foo, 'x', property(get_x, set_x))

foo1 = Foo()
foo1.x = 12
print(foo1.x)

1

आप एक शब्दकोश वस्तु का उपयोग करके वर्ग विशेषताओं को अद्यतन करने के लिए निम्नलिखित कोड का उपयोग कर सकते हैं:

class ExampleClass():
    def __init__(self, argv):
        for key, val in argv.items():
            self.__dict__[key] = val

if __name__ == '__main__':
    argv = {'intro': 'Hello World!'}
    instance = ExampleClass(argv)
    print instance.intro

1

यह ओपी को जो चाहिए था, उससे थोड़ा अलग है, लेकिन जब तक मुझे काम करने का हल नहीं मिला, तब तक मैंने अपना दिमाग तेज कर दिया, इसलिए मैं यहां अगले आदमी / लड़की के लिए डाल रहा हूं

मुझे गतिशील बसने वालों और गेटर्स को निर्दिष्ट करने के लिए एक तरीके की आवश्यकता थी।

class X:
    def __init__(self, a=0, b=0, c=0):
        self.a = a
        self.b = b
        self.c = c

    @classmethod
    def _make_properties(cls, field_name, inc):
        _inc = inc

        def _get_properties(self):
            if not hasattr(self, '_%s_inc' % field_name):
                setattr(self, '_%s_inc' % field_name, _inc)
                inc = _inc
            else:
                inc = getattr(self, '_%s_inc' % field_name)

            return getattr(self, field_name) + inc

        def _set_properties(self, value):
            setattr(self, '_%s_inc' % field_name, value)

        return property(_get_properties, _set_properties)

मैं समय से पहले अपने खेतों को जानता हूं इसलिए अपनी संपत्ति बनाने जा रहा हूं। नोट: आप यह प्रति उदाहरण नहीं कर सकते, ये गुण वर्ग पर मौजूद होंगे !!!

for inc, field in enumerate(['a', 'b', 'c']):
    setattr(X, '%s_summed' % field, X._make_properties(field, inc))

चलो अब यह सब परीक्षण ..

x = X()
assert x.a == 0
assert x.b == 0
assert x.c == 0

assert x.a_summed == 0  # enumerate() set inc to 0 + 0 = 0
assert x.b_summed == 1  # enumerate() set inc to 1 + 0 = 1
assert x.c_summed == 2  # enumerate() set inc to 2 + 0 = 2

# we set the variables to something
x.a = 1
x.b = 2
x.c = 3

assert x.a_summed == 1  # enumerate() set inc to 0 + 1 = 1
assert x.b_summed == 3  # enumerate() set inc to 1 + 2 = 3
assert x.c_summed == 5  # enumerate() set inc to 2 + 3 = 5

# we're changing the inc now
x.a_summed = 1 
x.b_summed = 3 
x.c_summed = 5

assert x.a_summed == 2  # we set inc to 1 + the property was 1 = 2
assert x.b_summed == 5  # we set inc to 3 + the property was 2 = 5
assert x.c_summed == 8  # we set inc to 5 + the property was 3 = 8

क्या यह भ्रामक है? हाँ, खेद है कि मैं किसी भी वास्तविक वास्तविक उदाहरण के साथ नहीं आ सका। इसके अलावा, यह हल्के दिल के लिए नहीं है।


यदि मुझे सही ढंग से याद है, तो मुझे एक STATIC प्रकार की संपत्ति / गतिशील रूप से जोड़े गए जी / सेटर बनाने के लिए अपने सभी परीक्षण के दौरान एक रास्ता मिल गया। मुझे अपने पिछले सभी के माध्यम से जाना होगा - लेकिन सभी उदाहरणों के बीच साझा की जाने वाली चीज़ को जोड़ने में सक्षम होना निश्चित रूप से संभव है। प्रति-आवृत्ति प्रक्रिया बनाने के लिए ... मुझे पूरा यकीन है कि आप ऐसा कर सकते हैं कि एक उदाहरण में कुछ और न हो। मुझे सत्यापित करना होगा, लेकिन मैं भी कुछ इस तरह से भाग गया (अपने पहले प्रयासों में मैंने एक गलती की जिसके कारण कार्यों का निर्माण हुआ, लेकिन सभी उदाहरणों में दोष के कारण उनके पास नहीं था)
Acecool

साथ ही, हर संभव समाधान का स्वागत है क्योंकि यह ज्ञान का भंडार है। यह अलग-अलग तरीकों से देखने के लिए भी रोमांचक है कि विभिन्न लोग किसी समस्या का समाधान बनाते हैं। मेरा समाधान बहुत कुछ करता है, आपने इसे साझा करने के लिए कुछ सरल तरीके से नीचे कर दिया है। मैंने अपना एक छोटा संस्करण भी किया - यह इस विषय में कहीं होना चाहिए - और मुझे एहसास हुआ कि यह कोई ऐसा नहीं है जिसे मैंने पोस्ट किया है: -) ...
Acecool

0

यह काम करने लगता है (लेकिन नीचे देखें):

class data(dict,object):
    def __init__(self,*args,**argd):
        dict.__init__(self,*args,**argd)
        self.__dict__.update(self)
    def __setattr__(self,name,value):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
    def __delattr__(self,name):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)

यदि आपको अधिक जटिल व्यवहार की आवश्यकता है, तो अपने उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें।

संपादित करें

निम्नलिखित संभवतः बड़े डेटासेट के लिए अधिक मेमोरी-कुशल होगा:

class data(dict,object):
    def __init__(self,*args,**argd):
        dict.__init__(self,*args,**argd)
    def __getattr__(self,name):
        return self[name]
    def __setattr__(self,name,value):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be set"%(name,self.__class__.__name__)
    def __delattr__(self,name):
        raise AttributeError,"Attribute '%s' of '%s' object cannot be deleted"%(name,self.__class__.__name__)

0

अपने प्रश्न के मुख्य जोर का जवाब देने के लिए, आप एक अपरिवर्तनीय डेटा स्रोत के रूप में एक तानाशाह से केवल पढ़ने के लिए विशेषता चाहते हैं:

लक्ष्य एक मॉक क्लास बनाना है जो db परिणाम की तरह व्यवहार करता है।

इसलिए, उदाहरण के लिए, यदि कोई डेटाबेस क्वेरी एक तानाशाही अभिव्यक्ति का उपयोग करके वापस आती है, {'ab':100, 'cd':200} , तो मुझे देखना होगा

>>> dummy.ab
100

मैं दिखाता हूँ कि कैसे उपयोग करें namedtuple कि collectionsमॉड्यूल से

import collections

data = {'ab':100, 'cd':200}

def maketuple(d):
    '''given a dict, return a namedtuple'''
    Tup = collections.namedtuple('TupName', d.keys()) # iterkeys in Python2
    return Tup(**d)

dummy = maketuple(data)
dummy.ab

रिटर्न 100


0
class atdict(dict):
  def __init__(self, value, **kwargs):
    super().__init__(**kwargs)
    self.__dict = value

  def __getattr__(self, name):
    for key in self.__dict:
      if type(self.__dict[key]) is list:
        for idx, item in enumerate(self.__dict[key]):
          if type(item) is dict:
            self.__dict[key][idx] = atdict(item)
      if type(self.__dict[key]) is dict:
        self.__dict[key] = atdict(self.__dict[key])
    return self.__dict[name]



d1 = atdict({'a' : {'b': [{'c': 1}, 2]}})

print(d1.a.b[0].c)

और आउटपुट है:

>> 1

0

Kjfletch से विचार का विस्तार

# This is my humble contribution, extending the idea to serialize
# data from and to tuples, comparison operations and allowing functions
# as default values.

def Struct(*args, **kwargs):
    FUNCTIONS = (types.BuiltinFunctionType, types.BuiltinMethodType, \
                 types.FunctionType, types.MethodType)
    def init(self, *iargs, **ikwargs):
        """Asume that unamed args are placed in the same order than
        astuple() yields (currently alphabetic order)
        """
        kw = list(self.__slots__)

        # set the unnamed args
        for i in range(len(iargs)):
            k = kw.pop(0)
            setattr(self, k, iargs[i])

        # set the named args
        for k, v in ikwargs.items():
            setattr(self, k, v)
            kw.remove(k)

        # set default values
        for k in kw:
            v = kwargs[k]
            if isinstance(v, FUNCTIONS):
                v = v()
            setattr(self, k, v)

    def astuple(self):
        return tuple([getattr(self, k) for k in self.__slots__])

    def __str__(self):
        data = ['{}={}'.format(k, getattr(self, k)) for k in self.__slots__]
        return '<{}: {}>'.format(self.__class__.__name__, ', '.join(data))

    def __repr__(self):
        return str(self)

    def __eq__(self, other):
        return self.astuple() == other.astuple()

    name = kwargs.pop("__name__", "MyStruct")
    slots = list(args)
    slots.extend(kwargs.keys())
    # set non-specific default values to None
    kwargs.update(dict((k, None) for k in args))

    return type(name, (object,), {
        '__init__': init,
        '__slots__': tuple(slots),
        'astuple': astuple,
        '__str__': __str__,
        '__repr__': __repr__,
        '__eq__': __eq__,
    })


Event = Struct('user', 'cmd', \
               'arg1', 'arg2',  \
               date=time.time, \
               __name__='Event')

aa = Event('pepe', 77)
print(aa)
raw = aa.astuple()

bb = Event(*raw)
print(bb)

if aa == bb:
    print('Are equals')

cc = Event(cmd='foo')
print(cc)

आउटपुट:

<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
<Event: user=pepe, cmd=77, arg1=None, arg2=None, date=1550051398.3651814>
Are equals
<Event: user=None, cmd=foo, arg1=None, arg2=None, date=1550051403.7938335>

0

हालांकि कई जवाब दिए गए हैं, लेकिन मैं ऐसा नहीं पा सका, जिससे मैं खुश हूं। मैंने अपने स्वयं के समाधान का पता लगाया जो propertyगतिशील मामले के लिए काम करता है । मूल प्रश्न का उत्तर देने के लिए स्रोत:

#!/usr/local/bin/python3

INITS = { 'ab': 100, 'cd': 200 }

class DP(dict):
  def __init__(self):
    super().__init__()
    for k,v in INITS.items():
        self[k] = v 

def _dict_set(dp, key, value):
  dp[key] = value

for item in INITS.keys():
  setattr(
    DP,
    item,
    lambda key: property(
      lambda self: self[key], lambda self, value: _dict_set(self, key, value)
    )(item)
  )

a = DP()
print(a)  # {'ab': 100, 'cd': 200}
a.ab = 'ab100'
a.cd = False
print(a.ab, a.cd) # ab100 False

0

मेरे लिए कुछ ऐसा काम करता है:

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

    def g(self):
        return self._x

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

    def d(self):
        del self._x

    def s2(self,x):
        self._x=x+x

    x=property(g,s,d)


c = C()
c.x="a"
print(c.x)

C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x)

उत्पादन

a
aa

-1

मैं हाल ही में इसी तरह की समस्या में भाग गया था, जो समाधान मैं उपयोग के साथ आया था __getattr__और __setattr__उन गुणों के लिए जिन्हें मैं इसे संभालना चाहता हूं, बाकी सब कुछ मूल पर पारित हो जाता है।

class C(object):
    def __init__(self, properties):
        self.existing = "Still Here"
        self.properties = properties

    def __getattr__(self, name):
        if "properties" in self.__dict__ and name in self.properties:
            return self.properties[name] # Or call a function, etc
        return self.__dict__[name]

    def __setattr__(self, name, value):
        if "properties" in self.__dict__ and name in self.properties:
            self.properties[name] = value
        else:
            self.__dict__[name] = value

if __name__ == "__main__":
    my_properties = {'a':1, 'b':2, 'c':3}
    c = C(my_properties)
    assert c.a == 1
    assert c.existing == "Still Here"
    c.b = 10
    assert c.properties['b'] == 10

मैंने इस पर ध्यान दिया, हालांकि आप तकनीकी रूप से अपने गेटटर और सेटर हेल्पर्स की सूची से गुजर रहे हैं। इस वजह से, प्रत्येक कॉल धीमी होगी क्योंकि आप इसे सीधे एक्सेस करने के बजाय, पहले किसी सूची से देख रहे हैं। जब तक अजगर आपके लिए इसे ऑटो-मैप नहीं करता; यह हो सकता है, लेकिन मैंने यह सुनिश्चित करने के लिए अभी तक बेंचमार्क नहीं किया है, लेकिन यह कोशिश करने से पहले मेरे लिए एक चिंता का विषय है। दूसरा, ऐसा करने से, आपको सहायकों को दूसरे तरीके से परिभाषित करना होगा। आप एक बड़े शब्दकोश, या बहुत सी अतिरिक्त पंक्तियों को समाप्त किए बिना डेटा-प्रकारों और / या मूल्यों को लॉक नहीं कर सकते।
ऐसकूल

यानी: मुझे या तो एक बेस क्लास बनाना होगा, जो मैं अपने सभी बच्चों को बढ़ाता हूँ, जो सिस्टम का उपयोग करते हैं, या मुझे हर चीज़ में s / getattr मैजिक फ़ंक्शंस को जोड़ना होगा और सिस्टम को हर बार डुप्लिकेट करना होगा। संपत्तियों की घोषणा का अर्थ यह भी है कि आपको उन्हें एक तरह से सेट करना होगा, और यदि आप कोई अतिरिक्त समर्थन चाहते हैं, जैसा कि मैंने डेटा-टाइप और या मान सुरक्षा के रूप में सूचीबद्ध किया है, ताकि डेटा को सौंपा और अन्य सहायकों को अनुमति देने या रोका जा सके। , फिर आपको उन्हें कोड करना होगा। दी गई, आप सिस्टम को व्यवहार में समान बना सकते हैं, लेकिन यह समाप्त हो जाता है जहां आप थोड़ा अलग और थोक घोषित करते हैं।
ऐस्कूल

-1

यहाँ प्रोग्रामेटिक रूप से प्रॉपर्टी ऑब्जेक्ट बनाने का सरल उदाहरण है।

#!/usr/bin/python3

class Counter:
    def __init__(self):
        cls = self.__class__
        self._count = 0
        cls.count = self.count_ref()

    def count_get(self):
        print(f'count_get: {self._count}')
        return self._count

    def count_set(self, value):
        self._count = value
        print(f'count_set: {self._count}')

    def count_del(self):
        print(f'count_del: {self._count}')

    def count_ref(self):
        cls = self.__class__
        return property(fget=cls.count_get, fset=cls.count_set, fdel=cls.count_del)

counter = Counter()

counter.count
for i in range(5):
    counter.count = i
del counter.count

'''
output
======
count_get: 0
count_set: 0
count_set: 1
count_set: 2
count_set: 3
count_set: 4
count_del: 4
'''

-2

एक संपत्ति को गतिशील रूप से संलग्न करने का एकमात्र तरीका एक नया वर्ग बनाना है और अपनी नई संपत्ति के साथ इसका उदाहरण है।

class Holder: p = property(lambda x: vs[i], self.fn_readonly)
setattr(self, k, Holder().p)

1
यह काम नहीं करता है। यह संपत्ति का परिणाम बताएगा, संपत्ति का नहीं।
mjallday

यह गलत है। मैं क्लास को इनिशियलाइज़ करने के बिना अपने सिस्टम के साथ डायनेमिक गुण संलग्न करता हूं। प्रारंभ x = उदाहरण () होने के नाते, फिर x में गुण जोड़ते हैं।
ऐसकूल

यदि आप मेरे कोड को देखते हैं, तो आप देखेंगे कि मैं क्लास का उपयोग करता हूं उदाहरण: पास, फिर कक्षा का उदाहरण (उदाहरणबेस): ... तो मैं उदाहरण के लिए गुणों को संलग्न करता हूं, क्योंकि नाम तब मौजूद है, और उदाहरण के बाद से इसका विस्तार होता है। इसकी हर चीज तक पहुंच है। मैं एक्सेसर हेल्पर के लिए __ वर्जन का उपयोग करता हूं, एक्सेसर ऑब्जेक्ट्स के लिए सीधी एक्सेस करने में सक्षम होने के लिए, मैं संग्रहीत डेटा (कच्चे) के लिए _ का उपयोग करता हूं जो कोई नहीं हो सकता है, और वास्तविक संपत्ति के लिए कोई अंडरस्कोर नहीं है जो कि गेट्टर के माध्यम से जाता है। मैं गत्यात्मक फ़ंक्शन को गतिशील रूप से जोड़े गए फ़ंक्शन का उपयोग करके कॉल कर सकता हूं, या संपत्ति का उपयोग कर सकता हूं। सभी पहले init'd बिना।
Acecool

नोट: मैंने इसका उल्लेख किया है - लेकिन परिभाषा के लिए मेरी परिभाषा का अर्थ है संदर्भ नामस्थान में मौजूद है - यानी: वर्ग उदाहरण (ऑब्जेक्ट): पास ... यह मौजूद है, लेकिन इसे आरंभीकृत नहीं किया गया है। आरंभीकरण का अर्थ है ब्लाह = उदाहरण (); अब इस वस्तु को 'डुप्लिकेट' कर दिया गया है और इसका निर्माण किया गया है, फिर ब्लाह में एक संदर्भ के रूप में संग्रहीत किया जाता है। --- यदि आप ऐसा करते हैं, तो गतिशील रूप से जोड़े गए फ़ंक्शन / गुण केवल उदाहरण में होने चाहिए - मेरे पास यह समस्या तब भी थी जब फ़ंक्शन मौजूद थे, ऐसे मामले भी थे जहां मुझे एक त्रुटि मिली, जिसमें उन्होंने कहा नहीं था। या तो ब्लॉकिंग एरर ने क्रिएशन को रोक दिया, या एसिंक्स एक्जीक्यूशन को।
Acecool

कुछ अन्य नोट्स: यह गतिशील रूप से गुण बनाने के लिए संभव है, और इस तरह से कार्य करता है जो केवल उदाहरण के लिए मौजूद हैं। आप उन्हें भी बना सकते हैं ताकि वे वस्तु के लिए मौजूद हों (जो कि ज्यादातर मामलों में आप चाहते हैं)। और ऐसे मामले हैं जिनमें जोड़े गए तत्व 'स्थिर' हैं, अर्थात समान संदर्भ, और लौटाए गए मान सभी उदाहरणों में साझा किए जाते हैं - यदि आप एक क्षेत्र में अपडेट करते हैं, तो सभी समान
मिलते हैं

-6

बहुत सारे आपूर्ति किए गए उत्तरों के लिए प्रति व्यक्ति इतनी सारी लाइनों की आवश्यकता होती है, जैसे / और / या - मैं कई गुणों के लिए आवश्यक पुनरावृत्ति के कारण एक बदसूरत या थकाऊ कार्यान्वयन पर क्या विचार करूंगा, आदि मैं उबलती चीजों को नीचे रखना / उन्हें सरल करना पसंद करता हूं जब तक कि वे नहीं करते। अब या तब तक सरलीकृत नहीं किया जा सकता जब तक कि ऐसा करने के लिए बहुत उद्देश्य नहीं है।

संक्षेप में: पूर्ण किए गए कार्यों में, यदि मैं कोड की 2 पंक्तियों को दोहराता हूं, तो मैं आमतौर पर इसे एक ही लाइन हेल्पर फ़ंक्शन में बदल देता हूं, और इसी तरह ... मैं गणित या विषम तर्कों को सरल करता हूं जैसे (start_x, start_y, end_x, end_y) (x, y, w, h) अर्थात x, y, x + w, y + h (कभी-कभी मिनट / अधिकतम की आवश्यकता होती है या यदि w / h नकारात्मक होते हैं और कार्यान्वयन इसे पसंद नहीं करता है, तो मैं x / से घटा दूंगा) y और abs w / h। आदि ..)।

आंतरिक गेटर्स / सेटर को ओवरराइड करना एक अच्छा तरीका है, लेकिन समस्या यह है कि आपको हर वर्ग के लिए, या उस आधार पर क्लास को पेरेंट करने की आवश्यकता है ... यह मेरे लिए काम नहीं करता है जैसा कि मैं करना चाहता हूं। वंशानुक्रम, बाल नोड्स, आदि के लिए बच्चों / माता-पिता को चुनने के लिए स्वतंत्र।

मैंने एक समाधान बनाया है जो डेटा को आपूर्ति करने के लिए डिक्ट डेटा-प्रकार का उपयोग किए बिना प्रश्न का उत्तर देता है क्योंकि मुझे लगता है कि डेटा दर्ज करने के लिए थकाऊ होना चाहिए, आदि ...

मेरे समाधान के लिए आपको अपनी कक्षा के ऊपर 2 अतिरिक्त लाइनें जोड़ने की आवश्यकता है, जिस वर्ग के लिए आप गुण जोड़ना चाहते हैं, उसके लिए एक आधार वर्ग बनाएं, फिर प्रति पंक्ति 1 पंक्ति और आपके पास डेटा को नियंत्रित करने के लिए कॉलबैक जोड़ने का विकल्प है, डेटा परिवर्तन होने पर आपको सूचित करें डेटा को सीमित करें जो मूल्य और / या डेटा-प्रकार, और बहुत कुछ के आधार पर सेट किया जा सकता है।

आपके पास _object.x, _object.x = value, _object.GetX (), _object.SetX (मान) का उपयोग करने का विकल्प है और वे समान रूप से नियंत्रित किए जाते हैं।

इसके अतिरिक्त, मान केवल गैर-स्थैतिक डेटा हैं जो वर्ग उदाहरण के लिए दिए गए हैं, लेकिन वास्तविक संपत्ति को वर्ग को सौंपा गया है, जिसका अर्थ है कि जिन चीजों को आप दोहराना नहीं चाहते हैं, उन्हें दोहराए जाने की आवश्यकता नहीं है ... आपको डिफ़ॉल्ट मान प्रदान कर सकता है, इसलिए हर बार इसे प्राप्त करने वाले को इसकी आवश्यकता नहीं होती है, हालांकि डिफ़ॉल्ट डिफ़ॉल्ट मान को ओवरराइड करने का एक विकल्प होता है, और एक अन्य विकल्प होता है, इसलिए डिफ़ॉल्ट डिफ़ॉल्ट रिटर्न को ओवरराइड करके कच्चे संग्रहित मूल्य को वापस करता है (नोट: यह विधि इसका मतलब है कि कच्चे मूल्य को केवल तब सौंपा जाता है जब कोई मूल्य निर्धारित किया जाता है, अन्यथा यह कोई नहीं है - जब मूल्य रीसेट होता है, तो यह कोई नहीं देता है, आदि))

कई सहायक कार्य भी हैं - पहला गुण जो जोड़ा जाता है, उदाहरण मानों को संदर्भित करने के लिए वर्ग में 2 या इतने ही सहायक जोड़े जाते हैं ... वे ResetAccessors (_key, ..) वेरिएग दोहराए जाते हैं (सभी को पहले नाम वाले टीएस का उपयोग करके दोहराया जा सकता है ) और SetAccessors (_key, _value) को दक्षता में सहयोगी के रूप में मुख्य वर्ग में जोड़े जाने के विकल्प के साथ - जो योजना बनाई गई हैं: एक साथ समूह एक्सेसर्स का एक तरीका है, इसलिए यदि आप एक बार में कुछ रीसेट करते हैं, तो हर बार , आप उन्हें एक समूह को असाइन कर सकते हैं और हर बार नामित कुंजी को दोहराने के बजाय समूह को रीसेट कर सकते हैं, और बहुत कुछ।

उदाहरण / कच्चे संग्रहित मूल्य को कक्षा में संग्रहीत किया जाता है , कक्षा। एक्सेसर क्लास को संदर्भित करता है जो संपत्ति के लिए स्थिर संस्करण / मान / फ़ंक्शन रखता है। _कक्षा। वह संपत्ति है जिसे सेटिंग / प्राप्त करने के दौरान इंस्टेंस क्लास के माध्यम से एक्सेस करने पर कहा जाता है।

Accessor _class .__ वर्ग को इंगित करता है, लेकिन क्योंकि यह आंतरिक है इसलिए इसे कक्षा में सौंपा जाना चाहिए, यही कारण है कि मैंने इसे असाइन करने के लिए __Name = AccessorFunc (...) का उपयोग करने का विकल्प चुना है, जो कई वैकल्पिक रूप से प्रति संपत्ति एक पंक्ति है। उपयोग करने के लिए तर्क (कुंजीकृत वैरग का उपयोग करना क्योंकि वे पहचानने और बनाए रखने के लिए आसान और अधिक कुशल हैं) ...

मैं बहुत सारे फ़ंक्शंस भी बनाता हूं, जैसा कि उल्लेख किया गया है, जिनमें से कुछ एक्सेसर फ़ंक्शन जानकारी का उपयोग करते हैं, इसलिए इसे कॉल करने की आवश्यकता नहीं है (क्योंकि यह इस समय थोड़ा असुविधाजनक है - अभी आपको _class का उपयोग करने की आवश्यकता है। (_class.instance) ) 'उदाहरण के लिए और स्वयं तक पहुंच बनाए रखने के लिए, AccessorFunc क्लास संदर्भ, और फ़ंक्शन परिभाषा के भीतर से अन्य जानकारी)।

यह बिल्कुल नहीं किया गया है, लेकिन यह एक शानदार फुट-होल्ड है। नोट: यदि आप गुण बनाने के लिए __Name = AccessorFunc (...) का उपयोग नहीं करते हैं, तो आपके पास __ कुंजी तक पहुंच नहीं होगी, भले ही मैं इसे init फ़ंक्शन के भीतर परिभाषित करता हूं। यदि आप करते हैं, तो कोई मुद्दे नहीं हैं।

इसके अलावा: ध्यान दें कि नाम और कुंजी अलग-अलग हैं ... नाम 'औपचारिक' है, जिसका उपयोग फ़ंक्शन नाम निर्माण में किया जाता है, और कुंजी डेटा संग्रहण और पहुंच के लिए है। यानी _class.x जहां लोअरकेस x कुंजी है, नाम अपरकेस एक्स होगा ताकि गेटएक्स () गेटेक्स () के बजाय फ़ंक्शन है जो थोड़ा विषम दिखता है। यह self.x को काम करने और उचित दिखने की अनुमति देता है, लेकिन GetX () और उचित देखने की भी अनुमति देता है।

मेरे पास एक उदाहरण वर्ग है जिसकी कुंजी / नाम समान है, और दिखाने के लिए अलग है। डेटा को आउटपुट करने के लिए बहुत सारे सहायक कार्य किए गए हैं (नोट: यह सब पूर्ण नहीं है) ताकि आप देख सकें कि क्या चल रहा है।

कुंजी का उपयोग करते हुए कार्यों की वर्तमान सूची: एक्स, नाम: एक्स आउटपुट के रूप में:

यह कोई व्यापक सूची नहीं है - कुछ ऐसे हैं जो पोस्टिंग के समय इस पर नहीं बने हैं ...

_instance.SetAccessors( _key, _value [ , _key, _value ] .. )                   Instance Class Helper Function: Allows assigning many keys / values on a single line - useful for initial setup, or to minimize lines.    In short: Calls this.Set<Name>( _value ) for each _key / _value pairing.
_instance.ResetAccessors( _key [ , _key ] .. )                                 Instance Class Helper Function: Allows resetting many key stored values to None on a single line.                                           In short: Calls this.Reset<Name>() for each name provided.


Note: Functions below may list self.Get / Set / Name( _args ) - self is meant as the class instance reference in the cases below - coded as this in AccessorFuncBase Class.

this.GetX( _default_override = None, _ignore_defaults = False )                 GET:            Returns    IF ISSET: STORED_VALUE .. IF IGNORE_DEFAULTS: None  .. IF PROVIDED: DEFAULT_OVERRIDE ELSE: DEFAULT_VALUE       100
this.GetXRaw( )                                                                 RAW:            Returns    STORED_VALUE                                                                                                     100
this.IsXSet( )                                                                  ISSET:          Returns    ( STORED_VALUE != None )                                                                                         True

this.GetXToString( )                                                            GETSTR:         Returns    str( GET )                                                                                                       100
this.GetXLen( _default_override = None, _ignore_defaults = False )              LEN:            Returns    len( GET )                                                                                                       3
this.GetXLenToString( _default_override = None, _ignore_defaults = False )      LENSTR:         Returns    str( len( GET ) )                                                                                                3
this.GetXDefaultValue( )                                                        DEFAULT:        Returns    DEFAULT_VALUE                                                                                                    1111

this.GetXAccessor( )                                                            ACCESSOR:       Returns    ACCESSOR_REF ( self.__<key> )                                                                                    [ AccessorFuncBase ] Key: x : Class ID: 2231452344344 : self ID: 2231448283848        Default: 1111       Allowed Types: {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}     Allowed Values: None
this.GetXAllowedTypes( )                                                        ALLOWED_TYPES:  Returns    Allowed Data-Types                                                                                               {"<class 'int'>": "<class 'type'>", "<class 'float'>": "<class 'type'>"}
this.GetXAllowedValues( )                                                       ALLOWED_VALUES: Returns    Allowed Values                                                                                                   None

this.GetXHelpers( )                                                             HELPERS:        Returns    Helper Functions String List - ie what you're reading now...                                                     THESE ROWS OF TEXT
this.GetXKeyOutput( )                                                           Returns information about this Name / Key                                                                                                   ROWS OF TEXT
this.GetXGetterOutput( )                                                        Returns information about this Name / Key                                                                                                   ROWS OF TEXT

this.SetX( _value )                                                             SET:            STORED_VALUE Setter - ie Redirect to __<Key>.Set                                                                            N / A
this.ResetX( )                                                                  RESET:          Resets STORED_VALUE to None                                                                                                 N / A

this.HasXGetterPrefix( )                                                        Returns Whether or Not this key has a Getter Prefix...                                                                                      True
this.GetXGetterPrefix( )                                                        Returns Getter Prefix...                                                                                                                    Get

this.GetXName( )                                                                Returns Accessor Name - Typically Formal / Title-Case                                                                                       X
this.GetXKey( )                                                                 Returns Accessor Property Key - Typically Lower-Case                                                                                        x
this.GetXAccessorKey( )                                                         Returns Accessor Key - This is to access internal functions, and static data...                                                             __x
this.GetXDataKey( )                                                             Returns Accessor Data-Storage Key - This is the location where the class instance value is stored..                                         _x

कुछ डेटा आउटपुट है:

यह एक बिल्कुल नए वर्ग के लिए है, जिसका उपयोग डेमो क्लास के नाम के अलावा किसी भी डेटा को सौंपे बिना किया जाता है (इसलिए इसका आउटपुट हो सकता है) जो कि _foo है, जिस वैरिएबल नाम का मैंने उपयोग किया है ...

_foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016

    Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |

    Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    x:        1111                | _x:       None                     | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    y:        2222                | _y:       None                     | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    z:        3333                | _z:       None                     | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Blah:     <class 'int'>       | _Blah:    None                     | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Width:    1                   | _Width:   None                     | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Height:   0                   | _Height:  None                     | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    Depth:    2                   | _Depth:   None                     | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |


this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
this.IsXSet( ):       False     this.GetX( ):        1111                     this.GetXRaw( ):       None                     this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       4    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
this.IsYSet( ):       False     this.GetY( ):        2222                     this.GetYRaw( ):       None                     this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       4    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
this.IsZSet( ):       False     this.GetZ( ):        3333                     this.GetZRaw( ):       None                     this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       4    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
this.IsBlahSet( ):    False     this.GetBlah( ):     <class 'int'>            this.GetBlahRaw( ):    None                     this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    13   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
this.IsWidthSet( ):   False     this.GetWidth( ):    1                        this.GetWidthRaw( ):   None                     this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   1    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
this.IsDepthSet( ):   False     this.GetDepth( ):    2                        this.GetDepthRaw( ):   None                     this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
this.IsHeightSet( ):  False     this.GetHeight( ):   0                        this.GetHeightRaw( ):  None                     this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

और यह सभी _foo गुणों (नाम को छोड़कर) को उसी क्रम में निम्नलिखित मान निर्दिष्ट करने के बाद है: 'string', 1.0, True, 9, 10, False

this.IsNameSet( ):    True      this.GetName( ):     _foo                     this.GetNameRaw( ):    _foo                     this.GetNameDefaultValue( ):    AccessorFuncDemoClass    this.GetNameLen( ):    4    this.HasNameGetterPrefix( ):    <class 'str'>                                this.GetNameGetterPrefix( ):    None
this.IsXSet( ):       True      this.GetX( ):        10                       this.GetXRaw( ):       10                       this.GetXDefaultValue( ):       1111                     this.GetXLen( ):       2    this.HasXGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetXGetterPrefix( ):       None
this.IsYSet( ):       True      this.GetY( ):        10                       this.GetYRaw( ):       10                       this.GetYDefaultValue( ):       2222                     this.GetYLen( ):       2    this.HasYGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetYGetterPrefix( ):       None
this.IsZSet( ):       True      this.GetZ( ):        10                       this.GetZRaw( ):       10                       this.GetZDefaultValue( ):       3333                     this.GetZLen( ):       2    this.HasZGetterPrefix( ):       (<class 'int'>, <class 'float'>)             this.GetZGetterPrefix( ):       None
this.IsBlahSet( ):    True      this.GetBlah( ):     string Blah              this.GetBlahRaw( ):    string Blah              this.GetBlahDefaultValue( ):    <class 'int'>            this.GetBlahLen( ):    11   this.HasBlahGetterPrefix( ):    <class 'str'>                                this.GetBlahGetterPrefix( ):    None
this.IsWidthSet( ):   True      this.GetWidth( ):    False                    this.GetWidthRaw( ):   False                    this.GetWidthDefaultValue( ):   1                        this.GetWidthLen( ):   5    this.HasWidthGetterPrefix( ):   (<class 'int'>, <class 'bool'>)              this.GetWidthGetterPrefix( ):   None
this.IsDepthSet( ):   True      this.GetDepth( ):    9                        this.GetDepthRaw( ):   9                        this.GetDepthDefaultValue( ):   2                        this.GetDepthLen( ):   1    this.HasDepthGetterPrefix( ):   None                                         this.GetDepthGetterPrefix( ):   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
this.IsHeightSet( ):  True      this.GetHeight( ):   9                        this.GetHeightRaw( ):  9                        this.GetHeightDefaultValue( ):  0                        this.GetHeightLen( ):  1    this.HasHeightGetterPrefix( ):  <class 'int'>                                this.GetHeightGetterPrefix( ):  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

_foo         --- MyClass: ---- id( this.__class__ ): 2231452349064 :::: id( this ): 2231448475016

    Key       Getter Value        | Raw Key   Raw / Stored Value       | Get Default Value             Default Value            | Get Allowed Types             Allowed Types                                                              | Get Allowed Values            Allowed Values                                                                                                                                                                                                                   |

    Name:     _foo                | _Name:    _foo                     | __Name.DefaultValue( ):       AccessorFuncDemoClass    | __Name.GetAllowedTypes( )     <class 'str'>                                                              | __Name.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    x:        10                  | _x:       10                       | __x.DefaultValue( ):          1111                     | __x.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __x.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    y:        10                  | _y:       10                       | __y.DefaultValue( ):          2222                     | __y.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __y.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    z:        10                  | _z:       10                       | __z.DefaultValue( ):          3333                     | __z.GetAllowedTypes( )        (<class 'int'>, <class 'float'>)                                           | __z.GetAllowedValues( )       Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Blah:     string Blah         | _Blah:    string Blah              | __Blah.DefaultValue( ):       <class 'int'>            | __Blah.GetAllowedTypes( )     <class 'str'>                                                              | __Blah.GetAllowedValues( )    Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Width:    False               | _Width:   False                    | __Width.DefaultValue( ):      1                        | __Width.GetAllowedTypes( )    (<class 'int'>, <class 'bool'>)                                            | __Width.GetAllowedValues( )   Saved Value Restrictions Levied by Data-Type                                                                                                                                                                                     |
    Height:   9                   | _Height:  9                        | __Height.DefaultValue( ):     0                        | __Height.GetAllowedTypes( )   <class 'int'>                                                              | __Height.GetAllowedValues( )  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |
    Depth:    9                   | _Depth:   9                        | __Depth.DefaultValue( ):      2                        | __Depth.GetAllowedTypes( )    Saved Value Restricted to Authorized Values ONLY                           | __Depth.GetAllowedValues( )   (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                                                                                                                                                                                                   |

ध्यान दें कि प्रतिबंधित डेटा-प्रकार या मूल्य प्रतिबंधों के कारण, कुछ डेटा असाइन नहीं किया गया था - यह डिज़ाइन द्वारा है। सेटर खराब डेटा-प्रकार या मान को असाइन करने से रोकता है, यहां तक ​​कि डिफ़ॉल्ट मान के रूप में असाइन किए जाने से भी (जब तक कि आप डिफ़ॉल्ट सुरक्षा सुरक्षा व्यवहार को ओवरराइड नहीं करते)

कोड यहाँ पोस्ट नहीं किया गया है क्योंकि उदाहरण और स्पष्टीकरण के बाद मेरे पास कमरा नहीं था ... इसके अलावा क्योंकि यह बदल जाएगा।

कृपया ध्यान दें: इस पोस्टिंग के समय, फ़ाइल गड़बड़ है - यह बदल जाएगा। लेकिन, यदि आप इसे उदात्त पाठ में चलाते हैं और इसे संकलित करते हैं, या इसे पायथन से चलाते हैं, तो यह एक टन सूचना को संकलित और थूक देगा - AccessorDB भाग नहीं किया गया है (जिसका उपयोग प्रिंट गेटर्स और GetKeyOutput सहायक को अद्यतन करने के लिए किया जाएगा। एक समारोह में परिवर्तित होने के साथ-साथ कार्य, शायद एक ही समारोह में डाल दिया और नाम बदल दिया - इसके लिए देखो ..)

अगला: इसे चलाने के लिए सब कुछ आवश्यक नहीं है - नीचे टिप्पणी की गई बहुत सारी सामग्री डीबगिंग के लिए उपयोग की जाने वाली अधिक जानकारी के लिए है - जब आप इसे डाउनलोड करते हैं तो यह वहां नहीं हो सकता है। यदि यह है, तो आपको अधिक जानकारी प्राप्त करने के लिए असुविधाजनक और recompile करने में सक्षम होना चाहिए।

मैं MyClassBase की आवश्यकता के लिए एक काम के आसपास देख रहा हूँ: पास, MyClass (MyClassBase): ... - यदि आप एक समाधान के बारे में जानते हैं - इसे पोस्ट करें।

कक्षा में आवश्यक एकमात्र चीज __ लाइनें हैं - स्ट्रेट डिबगिंग के लिए है जैसा कि init है - उन्हें डेमो क्लास से हटाया जा सकता है, लेकिन आपको नीचे कुछ लाइनों को हटाने या टिप्पणी करने की आवश्यकता होगी (_foo / 2/3) ) ..

शीर्ष पर द स्ट्रिंग, डिक्ट और यूटील कक्षाएं मेरी पायथन लाइब्रेरी का एक हिस्सा हैं - वे पूर्ण नहीं हैं। मैंने लाइब्रेरी से अपनी ज़रूरत की कुछ चीजों की नकल की, और मैंने कुछ नए बनाए। पूर्ण कोड पूरी लाइब्रेरी से लिंक होगा और इसमें अपडेटेड कॉल प्रदान करने और कोड हटाने के साथ-साथ इसमें शामिल होगा (वास्तव में, केवल एक ही कोड डेमो क्लास और प्रिंट स्टेटमेंट होगा - AccessorFunc सिस्टम को लाइब्रेरी में स्थानांतरित कर दिया जाएगा)। ..

फ़ाइल का हिस्सा:

##
## MyClass Test AccessorFunc Implementation for Dynamic 1-line Parameters
##
class AccessorFuncDemoClassBase( ):
    pass
class AccessorFuncDemoClass( AccessorFuncDemoClassBase ):
    __Name      = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Name',      default = 'AccessorFuncDemoClass',  allowed_types = ( TYPE_STRING ),                    allowed_values = VALUE_ANY,                 documentation = 'Name Docs',        getter_prefix = 'Get',  key = 'Name',       allow_erroneous_default = False,    options = { } )
    __x         = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'X',         default = 1111,                     allowed_types = ( TYPE_INTEGER, TYPE_FLOAT ),       allowed_values = VALUE_ANY,                 documentation = 'X Docs',           getter_prefix = 'Get',  key = 'x',          allow_erroneous_default = False,    options = { } )
    __Height    = AccessorFuncBase( parent = AccessorFuncDemoClassBase, name = 'Height',    default = 0,                        allowed_types = TYPE_INTEGER,                       allowed_values = VALUE_SINGLE_DIGITS,       documentation = 'Height Docs',      getter_prefix = 'Get',  key = 'Height',     allow_erroneous_default = False,    options = { } )

यह सौंदर्य AccessorFuncs / callbacks / data-type / व्यावसायिक प्रवर्तन, आदि के साथ गतिशील रूप से जोड़े गए गुणों के साथ नई कक्षाएं बनाने के लिए अविश्वसनीय रूप से आसान बनाता है।

अभी के लिए, यह लिंक है (यह लिंक दस्तावेज़ में परिवर्तनों को प्रतिबिंबित करना चाहिए।): https://www.dropbox.com/s/6gzi44i7dh58v61/dynamic_properties_accessorfuncs_and_more.py?topl=0

इसके अलावा: यदि आप उदात्त पाठ का उपयोग नहीं करते हैं, तो मैं इसे नोटपैड ++, एटम, विज़ुअल कोड, और अन्य की सलाह देता हूं क्योंकि उचित थ्रेडिंग कार्यान्वयन के कारण यह बहुत अधिक तेजी से उपयोग कर रहा है ... मैं एक आईडीई जैसे कोड पर भी काम कर रहा हूं। इसके लिए मैपिंग सिस्टम - एक नज़र डालें: https://bitbucket.org/Acecool/acecoolcodemappingsystem/src/master/ (पहले पैकेज मैनेजर में रेपो जोड़ें, फिर प्लगिन स्थापित करें - जब संस्करण 1.0.0 तैयार है, तो मैं जोड़ूंगा यह मुख्य प्लगइन सूची में है ...)

मुझे उम्मीद है कि यह समाधान मदद करता है ... और, हमेशा की तरह:

सिर्फ इसलिए कि यह काम करता है, इसे सही नहीं बनाता है - जोश 'Acecool' मोजर


मैं एक त्वरित प्रदर्शन जोड़ना चाहता था कि कक्षा कैसी दिखती है, इसलिए आपको कोड फ़ाइल खोलने की आवश्यकता नहीं है, लेकिन टिप्पणियां इसका समर्थन नहीं करती हैं ..
Acecool

जाहिर तौर पर इससे काफी नफरत हो रही है, जो भ्रामक है। यह वही करता है जो ओपी पूछ रहा है - गतिशील रूप से किसी वस्तु में गुण जोड़ना। यह सहायक कार्यों को भी जोड़ता है, जिसमें शामिल होने की आवश्यकता नहीं है - शायद इसीलिए यह नफरत हो रही है - और यह भी सुनिश्चित करता है कि डेवलपर के पास संपत्ति (.x) तक पहुंचने का एक आसान तरीका है जिसे गेट्टर के माध्यम से संसाधित किया जाता है। कच्चा मान (._x) जो कि कोई नहीं हो सकता है जब .x डिफ़ॉल्ट या कुछ और लौटाता है, और सहायक का उपयोग करने, चीजों को बदलने, आदि का उपयोग करने का एक तरीका है। (.__ x) ....
Acecool
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.