2016-07-13 7 views
5

मुझे एक वर्ग बनाने की आवश्यकता है जो विस्तारित हो और नीचे दी गई छवि में गूंगा उदाहरण द्वारा चित्रित एक रोचक समस्या में भाग गया।उपclassing dict; dict.update अविश्वसनीय मूल्य देता है - पायथन बग?

subclassing_dict_problem

क्यों d.update() वर्ग के __getitem__ अनदेखी कर रहा है?

संपादित करें: यह python2.7 में है जिसमें संग्रह शामिल नहीं है। उपयोगकर्ता डिक्शन सोच रहा है UserDict.UserDict समकक्ष है मैंने कोशिश की, और यह करीब आता है, लेकिन फिर भी दिलचस्प व्यवहार करता है।

updated to use UserDict

+0

[पाइथन: संभवतः "पूरी तरह से" एक उपकरण को ओवरराइड करने के लिए कैसे करें] (http: // stackoverflow।कॉम/प्रश्न/33876 9 1/पायथन-कैसे-से-पूरी तरह से ओवरराइड-ए-डॉक) – styvane

+0

मेरा प्रश्न यह नहीं है कि इस के आसपास कैसे जाना है, लेकिन यह क्यों हो रहा है। मैंने अपना काम पूरा करने के लिए MutableMapping subclassing समाप्त हो गया, लेकिन यह अजीब, अनियंत्रित व्यवहार की तरह लगता है। – Kirk

+0

[अंतर्निर्मित प्रकार के उप-वर्ग] (https://pypy.readthedocs.io/en/latest/cpython_differences.html#subclasses-of-built-in-types) – styvane

उत्तर

6

यह open-closed-principle का एक उदाहरण (कक्षा विस्तार के लिए खुला है, लेकिन संशोधन के लिए बंद कर दिया गया है)। यह अच्छी बात है क्योंकि यह उप-वर्गों को अनजाने में दूसरों में व्यवहार परिवर्तनों को ट्रिगर करने और कक्षाओं के आविष्कारों को तोड़ने के बिना किसी विधि को ओवरराइड करने की अनुमति देता है।

हम इसे शुद्ध पायथन कोड में भी करते हैं; उदाहरण के लिए, inside the pure python ordered dict code, __init__() से update() से कक्षा स्थानीय कॉल name mangling का उपयोग करके किया जाता है। यह एक उप-वर्ग को update()without accidentally breaking__init__() ओवरराइड करने की अनुमति देता है।

कभी-कभी, यह असुविधाजनक है। इसका मतलब है कि एक उप-वर्ग को प्रत्येक विधि को ओवरराइड करना होता है जिसका व्यवहार वे बदलना चाहते हैं जिसमें get(), update(), और अन्य शामिल हैं। हालांकि, ऑफसेटिंग लाभ (आंतरिक आविष्कारों की सुरक्षा, अमूर्तता से लीक करने से कार्यान्वयन विवरण को रोकने, और उपयोगकर्ताओं को यह मानने की अनुमति है कि वे एक-दूसरे से स्वतंत्र हैं)।

इस शैली (शुरुआत से ग्विडो द्वारा चुने गए) बिल्टिन प्रकारों के लिए डिफ़ॉल्ट है (अन्यथा हम हमेशा के लिए आविष्कार उल्लंघन से लड़ रहे होंगे) और कुछ शुद्ध पायथन कक्षाओं के लिए।

डिफ़ॉल्ट रूप से प्रस्थान होने पर हम दस्तावेज़ करते हैं। उदाहरण के लिए, cmd moduleframework design pattern का उपयोग करता है, जिससे उपयोगकर्ता विभिन्न do_action() विधियों को परिभाषित करता है। इसके अलावा, कुछ http मॉड्यूल समान कार्य करते हैं, विशेष रूप से यह दस्तावेज करते हैं कि उपयोगकर्ता का do_GET() method कहा जाता है और इस तरह आप अनुकूलित HTTP ईवेंट हैंडलर को संलग्न करते हैं।

विशेष रूप से प्रलेखित विधि हुक के अभाव में

(यानी, एक subclasser विधि स्वतंत्रता अनुमान चाहिए या dict.__missing__() तरह के तरीकों को ऊपर सूचीबद्ध। अन्यथा, कैसे हैं आप को पता है कि क्या __getitem__() कॉल हुड के नीचे get() या इसके विपरीत?

Fwiw, इस अजगर लिए अद्वितीय नहीं है। यह वस्तु उन्मुख प्रोग्रामिंग में काफ़ी ऊपर आता है। सही ढंग से तैयार किया गया कक्षाएं या तो दस्तावेज़ जड़ तरीकों कि अन्य तरीकों के व्यवहार को प्रभावित या वे स्वतंत्र होने के लिए माना जाता है।

वहाँ इसके लिए एक एफएक्यू होने की आवश्यकता हो सकती है, लेकिन यहां कुछ भी टूटा या गलत नहीं है (पायथन एच के अलावा से चुनने के लिए बहुत सारे नियम प्रकारों का उपयोग करना)। अगर कोई गलती से मानता है या मानता है कि __getitem__() को अन्य एक्सेसर विधियों द्वारा बुलाया जाना चाहिए, तो वे बहुत जल्दी पता लगाते हैं कि धारणा गलत है (यानी यदि वे कोड पर भी न्यूनतम परीक्षण चलाते हैं)।

संबंधित मुद्दे