अजगर में उत्परिवर्तित टपल का अस्तित्व?


121

क्या कोई नेमप्ले में संशोधन कर सकता है या एक वैकल्पिक वर्ग प्रदान कर सकता है ताकि यह परस्पर वस्तुओं के लिए काम करे?

मुख्य रूप से पठनीयता के लिए, मैं कुछ ऐसा नामांक के समान चाहूंगा जो यह करता है:

from Camelot import namedgroup

Point = namedgroup('Point', ['x', 'y'])
p = Point(0, 0)
p.x = 10

>>> p
Point(x=10, y=0)

>>> p.x *= 10
Point(x=100, y=0)

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


3
यह भी देखें: stackoverflow.com/q/5131044 । क्या कोई कारण है कि आप सिर्फ एक शब्दकोश का उपयोग नहीं कर सकते हैं?
सेंसहिन

@senshin लिंक के लिए धन्यवाद। मैं इसमें बताए गए कारण के लिए एक शब्दकोश का उपयोग नहीं करना पसंद करता हूं। यह प्रतिक्रिया भी code.activestate.com/recipes/… से जुड़ी हुई है , जो कि मैं उसके बाद बहुत करीब हूं।
अलेक्जेंडर

साथ के विपरीत namedtupleहै, ऐसा लगता है कि आप कोई जरूरत सूचकांक द्वारा गुण संदर्भित करने के लिए, यानी इतना सक्षम होना चाहिए p[0]और p[1]संदर्भ के लिए वैकल्पिक तरीके होगा xऔर yक्रमशः, सही है?
मार्टीन्यू

आदर्श रूप में, हाँ, नाम के अलावा एक सादे टपल की तरह अनुक्रमित, और एक टपल की तरह अनपैक। यह ActiveState नुस्खा करीब है, लेकिन मेरा मानना ​​है कि यह ऑर्डरडीड के बजाय एक नियमित शब्दकोश का उपयोग करता है। code.activestate.com/recipes/500261
अलेक्जेंडर

2
एक उत्परिवर्तित नामावली को एक वर्ग कहा जाता है।
gbtimmon

जवाबों:


132

एक परस्पर विकल्प है collections.namedtuple- रिकॉर्डक्लास

इसमें समान API और मेमोरी फ़ुटप्रिंट है namedtupleऔर यह असाइनमेंट का समर्थन करता है (यह और भी तेज़ होना चाहिए)। उदाहरण के लिए:

from recordclass import recordclass

Point = recordclass('Point', 'x y')

>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)

अजगर 3.6 और उच्चतर recordclass(0.5 के बाद से) के लिए समर्थन प्रकार:

from recordclass import recordclass, RecordClass

class Point(RecordClass):
   x: int
   y: int

>>> Point.__annotations__
{'x':int, 'y':int}
>>> p = Point(1, 2)
>>> p
Point(x=1, y=2)
>>> print(p.x, p.y)
1 2
>>> p.x += 2; p.y += 3; print(p)
Point(x=3, y=5)

एक अधिक पूर्ण उदाहरण है (इसमें प्रदर्शन तुलना भी शामिल है)।

चूँकि 0.9 recordclassपुस्तकालय एक और प्रकार - recordclass.structclassकारखाना कार्य प्रदान करता है। यह उन कक्षाओं का उत्पादन कर सकता है, जिनके उदाहरण- __slots__आधारित उदाहरणों की तुलना में कम मेमोरी पर कब्जा करते हैं । यह विशेषता मानों वाले उदाहरणों के लिए महत्वपूर्ण हो सकता है, जिसका संदर्भ चक्र होने का इरादा नहीं है। यदि आपको लाखों उदाहरण बनाने की आवश्यकता है, तो यह मेमोरी उपयोग को कम करने में मदद कर सकता है। यहाँ एक उदाहरण है


4
पसंद है। 'यह पुस्तकालय वास्तव में नामांकित टुपल के "परस्पर" विकल्प की समस्या के लिए एक अवधारणा का प्रमाण है। `
अलेक्जेंडर

1
recordclassधीमी है, और अधिक स्मृति लेता है, और एंटी-हापाला के नुस्खा के साथ तुलना में सी-एक्सटेंशन की आवश्यकता होती है और namedlist
ग्रांटज

recordclassइसका एक परिवर्तनशील संस्करण है collection.namedtupleजो इसे एपि, मेमोरी फुटप्रिंट, लेकिन सपोर्ट असाइनमेंट इनहेरिट करता है। namedlistस्लॉट्स के साथ वास्तव में अजगर वर्ग का उदाहरण है। यह अधिक उपयोगी है यदि आपको इंडेक्स द्वारा फ़ील्ड तक तेज़ पहुँच की आवश्यकता नहीं है।
इंटेलीमथ

recordclassउदाहरण के लिए अभिगम की सुविधा (अजगर 3.5.2) की तुलना में 2-3% धीमी हैnamedlist
intellimath

namedtupleकक्षा के निर्माण और सरल का उपयोग करते समय Point = namedtuple('Point', 'x y'), जेडी स्वत: पूर्ण विशेषताओं को दिखा सकता है, जबकि यह ऐसा नहीं है recordclass। यदि मैं लंबे सृजन कोड (आधारित RecordClass) का उपयोग करता हूं , तो जेडी Pointवर्ग को समझता है , लेकिन इसके निर्माता या विशेषताओं को नहीं ... क्या recordclassजेडी के साथ अच्छी तरह से काम करने का एक तरीका है ?
फिलामेकाय

34

type.SimpleNamespace पायथन 3.3 में पेश किया गया था और अनुरोधित आवश्यकताओं का समर्थन करता है।

from types import SimpleNamespace
t = SimpleNamespace(foo='bar')
t.ham = 'spam'
print(t)
namespace(foo='bar', ham='spam')
print(t.foo)
'bar'
import pickle
with open('/tmp/pickle', 'wb') as f:
    pickle.dump(t, f)

1
मैं कुछ वर्षों से ऐसा ही देख रहा हूं। जैसे dotmap बिंदु वाले dict पुस्तकालय के लिए महान प्रतिस्थापन
axwell

1
इसके लिए अधिक उर्जा की जरूरत है। यह वही है जो ओपी की तलाश में था, यह मानक पुस्तकालय में है, और इसका उपयोग करना सरल नहीं हो सकता है। धन्यवाद!
टॉम ज़िक

3
-1 ओपी ने अपने परीक्षणों से बहुत स्पष्ट कर दिया कि उसे क्या ज़रूरत है और SimpleNamespace6-10 परीक्षणों (सूचकांक द्वारा पहुंच, पुनरावृत्ति, पुनरावृत्ति, तानाशाही का आदेश दिया गया है, प्रतिस्थापन) और 12, 13 (फ़ील्ड, स्लॉट) तक विफल रहता है। ध्यान दें कि प्रलेखन (जो आप उत्तर में जुड़ा हुआ है) विशेष रूप से कहता है " SimpleNamespaceइसके प्रतिस्थापन के रूप में उपयोगी हो सकता है class NS: pass। हालांकि, namedtuple()इसके बजाय एक संरचित रिकॉर्ड प्रकार के उपयोग के लिए ।"
अली

1
-1 भी, SimpleNamespaceएक ऑब्जेक्ट बनाता है, न कि क्लास कंस्ट्रक्टर, और नेमप्ले के लिए एक प्रतिस्थापन नहीं हो सकता है। प्रकार की तुलना काम नहीं करेगी, और मेमोरी फ़ुटप्रिंट बहुत अधिक होगा।
RedGlyph

26

इस कार्य के लिए बहुत ही पायथनिक विकल्प के रूप में, पायथन-3.7 के बाद से, आप ऐसे dataclassesमॉड्यूल का उपयोग कर सकते हैं जो न केवल एक परिवर्तनशील की तरह व्यवहार करता हैNamedTuple करते हैं क्योंकि वे सामान्य वर्ग की परिभाषाओं का उपयोग करते हैं वे अन्य वर्गों की विशेषताओं का भी समर्थन करते हैं।

PEP-0557 से:

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

एक क्लास डेकोरेटर प्रदान किया जाता है जो PEP 526 में परिभाषित प्रकार एनोटेशन के साथ चर के लिए एक वर्ग परिभाषा का निरीक्षण करता है , "वैरिएंट एनोटेशन के लिए सिंटैक्स"। इस दस्तावेज़ में, ऐसे चर को फ़ील्ड कहा जाता है। इन क्षेत्रों का उपयोग करते हुए, डेकोरेटर वर्ग में उत्पन्न विधि परिभाषाओं को जोड़ता है ताकि उदाहरण आरंभीकरण, एक repr, तुलना विधियों, और वैकल्पिक रूप से अन्य तरीकों को निर्दिष्ट किया जा सके जैसा कि विनिर्देश अनुभाग में वर्णित है । इस तरह की क्लास को डेटा क्लास कहा जाता है, लेकिन क्लास के बारे में वास्तव में कुछ खास नहीं है: डेकोरेटर क्लास में उत्पन्न तरीकों को जोड़ता है और उसी क्लास को वापस करता है जो उसे दिया गया था।

यह सुविधा PEP-0557 में पेश की गई है जिसे आप इसके बारे में अधिक जानकारी प्रदान कर सकते हैं प्रदान किए गए प्रलेखन लिंक पर।

उदाहरण:

In [20]: from dataclasses import dataclass

In [21]: @dataclass
    ...: class InventoryItem:
    ...:     '''Class for keeping track of an item in inventory.'''
    ...:     name: str
    ...:     unit_price: float
    ...:     quantity_on_hand: int = 0
    ...: 
    ...:     def total_cost(self) -> float:
    ...:         return self.unit_price * self.quantity_on_hand
    ...:    

डेमो:

In [23]: II = InventoryItem('bisc', 2000)

In [24]: II
Out[24]: InventoryItem(name='bisc', unit_price=2000, quantity_on_hand=0)

In [25]: II.name = 'choco'

In [26]: II.name
Out[26]: 'choco'

In [27]: 

In [27]: II.unit_price *= 3

In [28]: II.unit_price
Out[28]: 6000

In [29]: II
Out[29]: InventoryItem(name='choco', unit_price=6000, quantity_on_hand=0)

1
यह ओपी में परीक्षणों के साथ बहुत स्पष्ट किया गया था कि क्या जरूरत है और dataclass6-10 परीक्षणों में विफल रहता है (सूचकांक द्वारा पहुंच, पुनरावृत्ति, पुनरावृत्ति, हुक्म का आदेश दिया, जगह-जगह प्रतिस्थापन) और पायथन 3.7 में 12, 13 (फ़ील्ड, स्लॉट) .1।
अली

1
हालांकि यह विशेष रूप से नहीं हो सकता है कि ओपी क्या देख रहा था, यह निश्चित रूप से मेरी मदद कर रहा है :)
मार्टिन सीआर

25

11 नवंबर, 2016 को पायथन 2.7 और पायथन 3.5 दोनों के साथ नवीनतम नामसूची 1.7 आपके सभी परीक्षण पास करता हैयह एक शुद्ध अजगर कार्यान्वयन है, जबकि recordclassएक सी एक्सटेंशन है। बेशक, यह आपकी आवश्यकताओं पर निर्भर करता है कि सी एक्सटेंशन पसंद है या नहीं।

आपके परीक्षण (लेकिन नीचे नोट भी देखें):

from __future__ import print_function
import pickle
import sys
from namedlist import namedlist

Point = namedlist('Point', 'x y')
p = Point(x=1, y=2)

print('1. Mutation of field values')
p.x *= 10
p.y += 10
print('p: {}, {}\n'.format(p.x, p.y))

print('2. String')
print('p: {}\n'.format(p))

print('3. Representation')
print(repr(p), '\n')

print('4. Sizeof')
print('size of p:', sys.getsizeof(p), '\n')

print('5. Access by name of field')
print('p: {}, {}\n'.format(p.x, p.y))

print('6. Access by index')
print('p: {}, {}\n'.format(p[0], p[1]))

print('7. Iterative unpacking')
x, y = p
print('p: {}, {}\n'.format(x, y))

print('8. Iteration')
print('p: {}\n'.format([v for v in p]))

print('9. Ordered Dict')
print('p: {}\n'.format(p._asdict()))

print('10. Inplace replacement (update?)')
p._update(x=100, y=200)
print('p: {}\n'.format(p))

print('11. Pickle and Unpickle')
pickled = pickle.dumps(p)
unpickled = pickle.loads(pickled)
assert p == unpickled
print('Pickled successfully\n')

print('12. Fields\n')
print('p: {}\n'.format(p._fields))

print('13. Slots')
print('p: {}\n'.format(p.__slots__))

पायथन 2.7 पर आउटपुट

1. फील्ड वैल्यू का म्यूटेशन  
पी: 10, 12

2. स्ट्रिंग  
p: बिंदु (x = 10, y = 12)

3. प्रतिनिधित्व  
बिंदु (x = 10, y = 12) 

4. आकार  
पी का आकार: 64 

5. क्षेत्र के नाम से प्रवेश  
पी: 10, 12

6. अनुक्रमणिका द्वारा पहुँच  
पी: 10, 12

7. धमनी अनपैकिंग  
पी: 10, 12

8. मैं ऊष्मायन  
पी: [१०, १२]

9. आदेश दिया गया  
p: ऑर्डरडीडिक्ट ([('x', 10), ('y', 12)])

10. Inplace प्रतिस्थापन (अपडेट?)  
p: बिंदु (x = 100, y = 200)

11. अचार और अनपिक  
सफलतापूर्वक चुना गया

12. फील्ड्स  
p: ('x', 'y')

13. स्लॉट  
p: ('x', 'y')

पायथन 3.5 के साथ एकमात्र अंतर यह है कि यह namedlistछोटा हो गया है, आकार 56 है (पायथन 2.7 रिपोर्ट 64)।

ध्यान दें कि मैंने इन-प्लेस प्रतिस्थापन के लिए आपका परीक्षण 10 बदल दिया है। namedlistएक है _replace()विधि है जो एक उथले नकल करता है, और क्योंकि वह मेरे लिए एकदम सही समझ में आता है namedtupleमानक पुस्तकालय में एक ही तरह से व्यवहार करता है। _replace()विधि के शब्दार्थ को बदलना भ्रामक होगा। मेरे विचार में _update()इन-प्लेस अपडेट के लिए विधि का उपयोग किया जाना चाहिए। या हो सकता है कि मैं आपके परीक्षण 10 के इरादे को समझने में असफल रहा?


महत्वपूर्ण बारीकियों है। namedlistदुकान सूची उदाहरण में महत्व देता है। बात यह है कि है cpythonकी listवास्तव में एक गतिशील सरणी है। डिज़ाइन के अनुसार, यह सूची के म्यूटेशन को सस्ता बनाने के लिए आवश्यकता से अधिक मेमोरी आवंटित करता है।
इंटेलीमथ

1
@intellimath नाम सूची में मिसनोमर का एक सा है। यह वास्तव listमें डिफ़ॉल्ट रूप से __slots__अनुकूलन का उपयोग नहीं करता है। जब मैंने मापा, तो मेमोरी का उपयोग इससे कम था recordclass: पायथन 2.7 पर छह क्षेत्रों के लिए 96 बाइट्स बनाम 104 बाइट्स
ग्रां प्री

@GranJ हाँ। recorclassअधिक मेमोरी का उपयोग करता है क्योंकि यह tupleचर मेमोरी साइज के साथ एक समान वस्तु है।
इंटेलीमथ

2
बेनामी चढ़ाव किसी की मदद नहीं कर रहे हैं। उत्तर में क्या गलत है? क्यों होता है पतन?
अली

मुझे टाइपो के खिलाफ सुरक्षा से प्यार है जो इसे सम्मान प्रदान करता है types.SimpleNamespace। दुर्भाग्य से, पाइलिंट इसे पसंद नहीं करता है :-(
xverges

23

ऐसा लगता है कि इस सवाल का जवाब नहीं है।

नीचे बहुत करीब है, लेकिन यह तकनीकी रूप से पारस्परिक नहीं है। यह namedtuple()अद्यतन x मान के साथ एक नया उदाहरण बना रहा है :

Point = namedtuple('Point', ['x', 'y'])
p = Point(0, 0)
p = p._replace(x=10) 

दूसरी ओर, आप एक साधारण वर्ग बना सकते हैं, जिसका उपयोग करके __slots__अक्सर कक्षा उदाहरण की विशेषताओं को अद्यतन करने के लिए अच्छी तरह से काम करना चाहिए:

class Point:
    __slots__ = ['x', 'y']
    def __init__(self, x, y):
        self.x = x
        self.y = y

इस उत्तर को जोड़ने के लिए, मुझे लगता __slots__है कि यहाँ अच्छा उपयोग है क्योंकि यह स्मृति कुशल है जब आप बहुत सारे वर्ग उदाहरण बनाते हैं। केवल नकारात्मक पक्ष यह है कि आप नई श्रेणी विशेषताएँ नहीं बना सकते।

यहां एक प्रासंगिक धागा है जो मेमोरी दक्षता - डिक्शनरी बनाम ऑब्जेक्ट - जो अधिक कुशल है और क्यों है?

इस धागे के उत्तर में उद्धृत सामग्री एक बहुत ही संक्षिप्त व्याख्या है कि __slots__अधिक स्मृति कुशल क्यों है - पायथन स्लॉट्स


1
बंद, लेकिन क्लूनी। मान लें कि मैं एक + = असाइनमेंट करना चाहता था, तो मुझे ऐसा करने की आवश्यकता होगी: p._replace (x = px + 10) बनाम px + = 10
अलेक्जेंडर

1
हाँ, यह वास्तव में मौजूदा टपल को नहीं बदल रहा है, यह एक नया उदाहरण बना रहा है
kennes

7

निम्नलिखित पायथन 3 के लिए एक अच्छा समाधान है: एक न्यूनतम वर्ग का उपयोग __slots__और Sequenceआधार वर्ग; फैंसी त्रुटि का पता लगाने या ऐसा नहीं करता है, लेकिन यह काम करता है, और ज्यादातर एक परिवर्तनशील ट्यूपल की तरह व्यवहार करता है (टाइपकेच को छोड़कर)।

from collections import Sequence

class NamedMutableSequence(Sequence):
    __slots__ = ()

    def __init__(self, *a, **kw):
        slots = self.__slots__
        for k in slots:
            setattr(self, k, kw.get(k))

        if a:
            for k, v in zip(slots, a):
                setattr(self, k, v)

    def __str__(self):
        clsname = self.__class__.__name__
        values = ', '.join('%s=%r' % (k, getattr(self, k))
                           for k in self.__slots__)
        return '%s(%s)' % (clsname, values)

    __repr__ = __str__

    def __getitem__(self, item):
        return getattr(self, self.__slots__[item])

    def __setitem__(self, item, value):
        return setattr(self, self.__slots__[item], value)

    def __len__(self):
        return len(self.__slots__)

class Point(NamedMutableSequence):
    __slots__ = ('x', 'y')

उदाहरण:

>>> p = Point(0, 0)
>>> p.x = 10
>>> p
Point(x=10, y=0)
>>> p.x *= 10
>>> p
Point(x=100, y=0)

यदि आप चाहें, तो आपके पास कक्षा बनाने की एक विधि भी हो सकती है (हालांकि स्पष्ट वर्ग का उपयोग करना अधिक पारदर्शी है)

def namedgroup(name, members):
    if isinstance(members, str):
        members = members.split()
    members = tuple(members)
    return type(name, (NamedMutableSequence,), {'__slots__': members})

उदाहरण:

>>> Point = namedgroup('Point', ['x', 'y'])
>>> Point(6, 42)
Point(x=6, y=42)

अजगर 2 में आप यह थोड़ा समायोजित करने की आवश्यकता है - अगर आप से विरासत Sequence, वर्ग एक होगा__dict__ और __slots__काम करने से रोक देगा।

पायथन 2 में समाधान से विरासत में नहीं है Sequence, लेकिन object। यदि isinstance(Point, Sequence) == Trueवांछित है, तो आपको NamedMutableSequenceआधार वर्ग के रूप में पंजीकृत करना होगा Sequence:

Sequence.register(NamedMutableSequence)

3

आइए इसे गतिशील प्रकार के निर्माण के साथ लागू करें:

import copy
def namedgroup(typename, fieldnames):

    def init(self, **kwargs): 
        attrs = {k: None for k in self._attrs_}
        for k in kwargs:
            if k in self._attrs_:
                attrs[k] = kwargs[k]
            else:
                raise AttributeError('Invalid Field')
        self.__dict__.update(attrs)

    def getattribute(self, attr):
        if attr.startswith("_") or attr in self._attrs_:
            return object.__getattribute__(self, attr)
        else:
            raise AttributeError('Invalid Field')

    def setattr(self, attr, value):
        if attr in self._attrs_:
            object.__setattr__(self, attr, value)
        else:
            raise AttributeError('Invalid Field')

    def rep(self):
         d = ["{}={}".format(v,self.__dict__[v]) for v in self._attrs_]
         return self._typename_ + '(' + ', '.join(d) + ')'

    def iterate(self):
        for x in self._attrs_:
            yield self.__dict__[x]
        raise StopIteration()

    def setitem(self, *args, **kwargs):
        return self.__dict__.__setitem__(*args, **kwargs)

    def getitem(self, *args, **kwargs):
        return self.__dict__.__getitem__(*args, **kwargs)

    attrs = {"__init__": init,
                "__setattr__": setattr,
                "__getattribute__": getattribute,
                "_attrs_": copy.deepcopy(fieldnames),
                "_typename_": str(typename),
                "__str__": rep,
                "__repr__": rep,
                "__len__": lambda self: len(fieldnames),
                "__iter__": iterate,
                "__setitem__": setitem,
                "__getitem__": getitem,
                }

    return type(typename, (object,), attrs)

यह देखने के लिए विशेषताओं की जांच करता है कि क्या ऑपरेशन जारी रखने की अनुमति देने से पहले वे वैध हैं।

तो क्या यह लाइलाज है? यदि आप (और केवल अगर) निम्नलिखित करते हैं:

>>> import pickle
>>> Point = namedgroup("Point", ["x", "y"])
>>> p = Point(x=100, y=200)
>>> p2 = pickle.loads(pickle.dumps(p))
>>> p2.x
100
>>> p2.y
200
>>> id(p) != id(p2)
True

परिभाषा आपके नामस्थान में होनी चाहिए, और इसे खोजने के लिए अचार में लंबे समय तक मौजूद रहना चाहिए। इसलिए यदि आप इसे अपने पैकेज में होना चाहते हैं, तो यह काम करना चाहिए।

Point = namedgroup("Point", ["x", "y"])

यदि आप निम्नलिखित करते हैं, तो अचार विफल हो जाएगा, या परिभाषा को अस्थायी बना देगा (कार्य समाप्त होने पर स्कोप से बाहर चला जाता है, कहते हैं):

some_point = namedgroup("Point", ["x", "y"])

और हाँ, यह प्रकार निर्माण में सूचीबद्ध फ़ील्ड के क्रम को संरक्षित करता है।


यदि आप के __iter__साथ एक विधि जोड़ते हैं for k in self._attrs_: yield getattr(self, k), तो यह एक टपल की तरह अनपैकिंग का समर्थन करेगा।
Snapshoe

यह भी बहुत आसान जोड़ने के लिए है __len__, __getitem__और __setiem__तरीकों की तरह, सूचकांक द्वारा हो रही valus समर्थन करने के लिए p[0]। इन अंतिम बिट्स के साथ, यह सबसे पूर्ण और सही उत्तर की तरह लगता है (वैसे भी मेरे लिए)।
स्नैपशॉट

__len__और __iter__अच्छे हैं। __getitem__और __setitem__वास्तव में मैप किया जा सकता self.__dict__.__setitem__औरself.__dict__.__getitem__
MadMan2064

2

Tuples परिभाषा से अपरिवर्तनीय हैं।

हालाँकि आप एक शब्दकोश उपवर्ग बना सकते हैं जहाँ आप डॉट-नोटेशन के साथ विशेषताओं तक पहुँच सकते हैं;

In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:class AttrDict(dict):
:
:    def __getattr__(self, name):
:        return self[name]
:
:    def __setattr__(self, name, value):
:        self[name] = value
:--

In [2]: test = AttrDict()

In [3]: test.a = 1

In [4]: test.b = True

In [5]: test
Out[5]: {'a': 1, 'b': True}

2

यदि आप नेमप्लस के समान व्यवहार चाहते हैं, लेकिन नाममात्र की कोशिश करने योग्य हैं

ध्यान दें कि आपस में मिलाने के लिए यह टपल नहीं हो सकता है।


लिंक के लिए धन्यवाद। यह अब तक निकटतम जैसा दिखता है, लेकिन मुझे इसका और अधिक विस्तार से मूल्यांकन करने की आवश्यकता है। Btw, मैं पूरी तरह से अवगत हूँ tuples अपरिवर्तनीय हैं, यही वजह है कि मैं नेमटुपल जैसे समाधान की तलाश कर रहा हूं ।
अलेक्जेंडर

0

बशर्ते प्रदर्शन बहुत कम महत्व का हो, जैसे कोई मूर्खतापूर्ण हैक का उपयोग कर सकता है:

from collection import namedtuple

Point = namedtuple('Point', 'x y z')
mutable_z = Point(1,2,[3])

1
यह उत्तर बहुत अच्छी तरह से समझाया नहीं गया है। यदि आप सूचियों के परस्पर प्रकृति को नहीं समझते हैं तो यह भ्रामक लगता है। --- इस उदाहरण में ... फिर से असाइन करने के लिए z, आपको mutable_z.z.pop(0)फिर कॉल करना होगा mutable_z.z.append(new_value)। यदि आपको यह गलत लगता है, तो आप 1 से अधिक तत्व समाप्त कर देंगे और आपका प्रोग्राम अप्रत्याशित रूप से व्यवहार करेगा।
बक्सर

1
@byxor कि, या आप बस mutable_z.z[0] = newValue:। यह वास्तव में एक हैक है, जैसा कि कहा गया है।
Srg

ओह, मुझे आश्चर्य है कि मैंने इसे फिर से असाइन करने का अधिक स्पष्ट तरीका याद किया।
byxor

मुझे यह पसंद है, असली हैक।
WebOrCode
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.