वहाँ तानाशाही और संग्रह से उपवर्ग का एक तरीका है।


26

आइए उदाहरण के लिए मान लें कि मैं उपवर्ग करना चाहता हूं dictऔर सभी कुंजियों को पूंजीकृत करना है:

class capdict(dict):
    def __init__(self,*args,**kwds):
        super().__init__(*args,**kwds)
        mod = [(k.capitalize(),v) for k,v in super().items()]
        super().clear()
        super().update(mod)
    def __getitem__(self,key):
        return super().__getitem__(key.capitalize())
    def __setitem__(self,key,value):
        super().__setitem__(key.capitalize(),value)
    def __delitem__(self,key):
        super().__detitem__(key.capitalize())

यह एक हद तक काम करता है,

>>> ex = capdict(map(reversed,enumerate("abc")))
>>> ex
{'A': 0, 'B': 1, 'C': 2}
>>> ex['a']
0

लेकिन, ज़ाहिर है, केवल उन तरीकों के लिए जिन्हें मैंने याद किया था, उदाहरण के लिए

>>> 'a' in ex
False

वांछित व्यवहार नहीं है।

अब, "कोर" वाले से प्राप्त होने वाले सभी तरीकों को भरने का आलसी तरीका अंदर मिलाया जाएगा collections.abc.MutableMapping। केवल, यह यहाँ काम नहीं करता है। मुझे लगता है क्योंकि प्रश्न ( __contains__उदाहरण में) के तरीके पहले से ही प्रदान किए गए हैं dict।

वहाँ मेरे केक होने और इसे खाने का एक तरीका है? कुछ जादू MutableMappingकेवल उन तरीकों को देखने के लिए हैं जिन्हें मैंने ओवरराइड किया है ताकि यह उन पर आधारित दूसरों को पुन: लागू करता है?


आपको उपयोग करने की आवश्यकता नहीं हो सकती है MutableMapping। केस असंवेदनशील शब्दकोश देखें ।
— मार्टिन्यू

@ स्मार्टिन्यू धन्यवाद, जैसा कि मैंने कहा कि यह केवल एक उदाहरण था।
— पॉल पैंजर

आप उपयोग कर सकते हैं os._Environ।
— पीटर वुड

जवाबों:


26

आप क्या कर सकते हैं:

यह संभवत: अच्छी तरह से (यानी नहीं साफ डिजाइन) बाहर काम नहीं है, लेकिन आप से विरासत सकता MutableMapping से पहले और उसके बाद dict दूसरा।

तब MutableMapping आपके द्वारा लागू की गई विधियों का उपयोग करेगा (क्योंकि वे लुकअप श्रृंखला में पहले हैं):

>>> class D(MutableMapping, dict):
        def __getitem__(self, key):
            print(f'Intercepted a lookup for {key!r}')
            return dict.__getitem__(self, key)


>>> d = D(x=10, y=20)
>>> d.get('x', 0)
Intercepted a lookup for 'x'
10
>>> d.get('z', 0)
Intercepted a lookup for 'z'
0

बेहतर तरीका:

सबसे साफ दृष्टिकोण (समझने और परीक्षण करने में आसान) सिर्फ म्यूटेबल मैपिंग से विरासत में मिला है और फिर आधार डेटा स्टोर (विरासत के बजाय संरचना के साथ) के रूप में नियमित रूप से तानाशाही का उपयोग करके आवश्यक तरीकों को लागू करना है:

>>> class CapitalizingDict(MutableMapping):
        def __init__(self, *args, **kwds):
            self.store = {}
            self.update(*args, **kwds)
        def __getitem__(self, key):
            key = key.capitalize()
            return self.store[key]
        def __setitem__(self, key, value):
            key = key.capitalize()
            self.store[key] = value
        def __delitem__(self, key):
            del self.store[key]
        def __len__(self):
            return len(self.store)
        def __iter__(self):
            return iter(self.store)
        def __repr__(self):
            return repr(self.store)


>>> d = CapitalizingDict(x=10, y=20)
>>> d
{'X': 10, 'Y': 20}
>>> d['x']
10
>>> d.get('x', 0)
10
>>> d.get('z', 0)
0
>>> d['w'] = 30
>>> d['W']
30

धन्यवाद! मैं शपथ ले सकता था मैंने दोनों आदेशों की कोशिश की ... ब्याज से बाहर, जब मैं superस्पष्ट dictएस के लिए "एस कर सकता हूं" विधि का उपयोग करता है तो यह lenरिटर्न को छोड़कर काम करने के लिए प्रकट होता है 0। कहाँ से आ रहा है?
— पॉल पैंजर

2
सुपर () कॉल __len _ () __ से mro में अगले तक जाता है (D, MutableMapping, dict):। वह MutableMappiing .__ लेन __ () विधि है जो हमेशा 0 लौटाता है। इसे सीधे बुलाया जाना नहीं था - इसे हमेशा ओवरराइड माना जाता है। इसलिए आपको dict.__len__(self)सीधे कॉल करना होगा । और यह एक कारण है कि मैंने कहा "यह संभावना अच्छी तरह से काम नहीं करेगी"; ;-)
— रेमंड हेटिंगर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.