{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" This article from the “Python Why? ” series , Please check out "},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?_biz=MzUyOTk2MTcwNg==&action=getalbum&albumid=1338406397180084225&subscene=0&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyOTk2MTcwNg%3D%3D%26mid%3D2247485945%26idx%3D1%26sn%3D02f1ac9a690f57accefeed7a1ea1247b%26chksm%3Dfa584e7ccd","title":""},"content":[{"type":"text","text":" All articles "}]},{"type":"text","text":" "}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" not long ago ,"},{"type":"codeinline","content":[{"type":"text","text":"Python cat "}]},{"type":"text","text":" I recommend a book to you 《 smooth Python》("},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/A4_DD2fvceNk1apn9MQcXA","title":""},"content":[{"type":"text","text":" Click to jump to read "}]},{"type":"text","text":"), That article has a lot of “ words of excessive praise ”, It seems to be rather vague ……"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" however ,《 smooth Python》 A book is worth reading again and again , You can learn from the old . Recently, I found a strange knowledge point in the book , So I'm going to talk about this topic ——"},{"type":"text","marks":[{"type":"strong"}],"text":" Subclassing built-in types can be problematic ?!"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/30/302d1748249e622aba2fcae6c86d59da.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1、 What are the built-in types ?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Before the official start , First of all, we need to popularize science :"},{"type":"text","marks":[{"type":"strong"}],"text":" Which are Python Built in type ?"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" According to the classification of official documents , Built in type (Built-in Types) It mainly includes the following contents :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6b/6b6bccd2ca82970a2c006c4280224959.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Detailed documentation :https://docs.python.org/3/library/stdtypes.html"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" among , There is a well-known "},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/0XpPaH53II5yO9Lfh80ZOw","title":""},"content":[{"type":"text","text":" Numeric type "}]},{"type":"text","text":"、 Sequence type 、 Text type 、 Mapping types and so on , And, of course, we've introduced [ Boolean type ](https://mp.weixin.qq.com/s/JVhXjQKcd8uds8yTUumZJw)、[... object ](https://mp.weixin.qq.com/s/SOSN_p74eDHv3tJnSJIZfg) wait ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In so much content , This article focuses only on those actions "},{"type":"codeinline","content":[{"type":"text","text":" Callable object "}]},{"type":"text","text":"(callable) Built in type , That is, with built-in functions (built-in function) On the surface, similar ones :"},{"type":"text","marks":[{"type":"strong"}],"text":"int、str、list、tuple、range、set、dict……"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" These types (type) It can be simply understood as a class in other languages (class), however Python There is no customary nomenclature for the hump , So it's easy to get misunderstood ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" stay Python 2.2 after , These built-in types can be subclassed (subclassing), That is, it can be inherited (inherit)."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2、 Subclassing of built-in types "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" as everyone knows , For a common object x,Python The public built-in function is needed to find its length in len(x), It is not like Java Object oriented languages like this , The object of the latter usually has its own x.length() Method .(PS: Analysis of these two design styles , Recommended reading "},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/pKQT5wvyaSNFvnJexiCC8w","title":""},"content":[{"type":"text","text":" This article "}]},{"type":"text","text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Now? , Suppose we want to define a list class , Hope it has its own length() Method , At the same time, keep all the features of a normal list ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The experimental code is as follows ( Just for demonstration ):"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# Define a list Subclasses of \nclass MyList(list):\n def length(self):\n return len(self)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" We make MyList This custom class inherits list, At the same time, a new definition of length() Method . thus ,MyList have append()、pop() Method, etc. , It also has length() Method ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# Add two elements \nss = MyList()\nss.append(\"Python\")\nss.append(\" cat \")\n\nprint(ss.length()) # Output :2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The other built-in types mentioned earlier , It can also be subclassed in this way , It shouldn't be hard to understand ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" By the way ,"},{"type":"text","marks":[{"type":"strong"}],"text":" What are the benefits of subclassing built-in types / What about the usage scenarios ?"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" There's an intuitive example , When we are in a custom class , When you need to use a list object frequently ( To add it / Remove elements 、 Pass on as a whole ……), In this case, if our class inherits from list, You can write directly self.append()、self.pop(), Or will self Pass as an object , So you don't have to define an extra list object , It will be concise in writing ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" There are other benefits / Use scenarios ? Welcome to leave a message for discussion ~~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3、 Subclassing of built-in types “ problem ”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Finally, it's time to enter the formal theme of this article :)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" generally , In our textbook cognition ,"},{"type":"text","marks":[{"type":"strong"}],"text":" Methods in subclasses override methods with the same name in the parent class , in other words , The search priority of subclass method is higher than that of parent method ."},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here's an example , Parent class Cat, Subclass PythonCat, There is one. say() Method , The function is to say the current object inner_voice:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# Python A cat is a cat \nclass Cat():\n def say(self):\n return self.inner_voice()\n def inner_voice(self):\n return \" meow \"\nclass PythonCat(Cat):\n def inner_voice(self):\n return \" Meow meow \""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When we create subclasses PythonCat The object is , its say() Methods will take precedence over the ones defined by themselves inner"},{"type":"text","marks":[{"type":"italic"}],"text":"voice() Method , instead of Cat Of the parent class inner"},{"type":"text","text":"voice() Method :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"my_cat = PythonCat()\n# The following results are in line with expectations \nprint(my_cat.inner_voice()) # Output : Meow meow \nprint(my_cat.say()) # Output : Meow meow "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" It's a convention of programming languages , It's a basic principle , Students who have learned the basics of object-oriented programming should know ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" However , When Python When implementing inheritance ,"},{"type":"text","marks":[{"type":"strong"}],"text":" It seems incomplete "},{"type":"text","text":" Will operate according to the above rules . It's divided into two situations :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In line with common sense : For using Python Implementation classes , They will follow “ The subclass precedes the parent ” Principles "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Contrary to common sense : For practical use C Implementation classes ( namely str、list、dict And so on, these built-in types ), When explicitly calling subclass methods , Will follow “ The subclass precedes the parent ” Principles ; however ,"},{"type":"text","marks":[{"type":"strong"}],"text":" When there is an implicit call ,"},{"type":"text","text":" They seem to follow “ The parent class precedes the child class ” Principles , That is, the usual inheritance rules will fail here "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" contrast PythonCat Example , It's equivalent to saying , Call directly my"},{"type":"text","marks":[{"type":"italic"}],"text":"cat.inner"},{"type":"text","text":"voice() when , Will get the right “ Meow meow ” result , But in calling my_cat.say() when , You get more than you expect “ meow ” result ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here is 《 smooth Python》 The example given in (12.1 chapter ):"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"class DoppelDict(dict): \n def __setitem__(self, key, value): \n super().__setitem__(key, [value] * 2)\n\ndd = DoppelDict(one=1) # {'one': 1}\ndd['two'] = 2 # {'one': 1, 'two': [2, 2]}\ndd.update(three=3) # {'three': 3, 'one': 1, 'two': [2, 2]}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1f/1f6a15647679a5ed2aaa2b865c01b24f.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In this case ,dd['two'] The subclass will be called directly \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Method , So the results are in line with expectations . If other tests are as expected , The end result will be {'three': [3, 3], 'one': [1, 1], 'two': [2, 2]}."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" However , Initialization and update() The direct calls are inherited from the parent class \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"init\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() and \\_\\_update\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"(), And then they "},{"type":"text","marks":[{"type":"strong"}],"text":" Implicitly "},{"type":"text","text":" call "},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Method , There is no subclass method called at this time , Instead, it calls the method of the parent class , The result is beyond expectation !"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" official Python This double rule approach , It's a little against common sense , If you don't pay attention to , It's easy to step on the pit if it's not done well ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" that , Why is there such an exception ?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4、 The true face of the built-in type method "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" We know that built-in types don't implicitly call subclass overlay methods , next , Namely "},{"type":"codeinline","content":[{"type":"text","text":"Python cat "}]},{"type":"text","text":" To get to the bottom of it : Why doesn't it call ?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"《"},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/A4_DD2fvceNk1apn9MQcXA","title":""},"content":[{"type":"text","text":" smooth Python"}]},{"type":"text","text":"》 There is no further questioning in the book , however , I tried to make a wild guess ( It should be verified from the source code ):"},{"type":"text","marks":[{"type":"strong"}],"text":" The methods of built-in types are all made with C The realization of language , In fact, they don't call each other , So there is no problem of lookup priority when calling ."},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" in other words , Ahead “\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"init\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() and \\_\\_update\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Will implicitly call "},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Method ” This statement is not accurate !"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" These magic methods are actually independent of each other !\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"init\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Have their own setitem Realization , It doesn't call the parent class \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"(), With Subclasses of course \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() It doesn't matter much ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To understand logically , Dictionary \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"init\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Method contains \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() The function of , So we thought the former would call the latter ,"},{"type":"text","marks":[{"type":"strong"}],"text":" This is the embodiment of habitual thinking ,"},{"type":"text","text":" However, the actual invocation relationship may be like this :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/7f/7f07249eaeb8d4a1262d850d590e7f3f.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The method on the left opens the door of the language interface and enters the world on the right , To fulfill all its missions there , It will not go back to the original interface to find the next instruction ( There is no red line path in the graph ). The reason is not simple , namely C Code calls between languages are more efficient , The implementation path is shorter , The implementation process is simpler ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Empathy ,dict Type of get() Methods and \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"getitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() There is no call relationship , If the subclass only covers \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"getitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Words , When a subclass calls get() When the method is used , It will actually use the parent class get() Method .(PS: On this point ,《 smooth Python》 And PyPy The description of the document is not accurate , They mistook get() Method will call \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"getitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"())"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" in other words ,Python The method of built-in type has no calling relationship itself , Even though they're at the bottom C When language is realized , There may be common logic or methods that can be reused ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" I think of it. “"},{"type":"link","attrs":{"href":"https://github.com/chinesehuazhou/python-whydo","title":""},"content":[{"type":"text","text":"Python Why? "}]},{"type":"text","text":"” The series has been analyzed 《[Python Why can support arbitrary truth value judgment ?](https://mp.weixin.qq.com/s/g6jZX0IdH9xpM7BMV3-ToQ)》. Before we write "},{"type":"codeinline","content":[{"type":"text","text":"if xxx"}]},{"type":"text","text":" when , It seems to implicitly call \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"bool\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() and \\_\\_len\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Magic methods , In fact, however, the procedure is based on POP"},{"type":"text","marks":[{"type":"italic"}],"text":"JUMP"},{"type":"text","text":"IF_FALSE Instructions , It goes straight into pure C Logic of code , There is no call to these magic methods !"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" therefore , Be aware of C After the special methods implemented are independent of each other , Let's go back to subclassing built-in types , There will be new discoveries :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/6792dd9d95d8a499d15a50e191891517.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Of the parent class \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"init\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Magic method will break the language interface to achieve their own mission , However, it is similar to subclasses of \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() There is no pathway , That is, the red line path in the figure is not reachable ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Special methods go their own way , thus , We'll come to a different conclusion from the previous one :"},{"type":"text","marks":[{"type":"strong"}],"text":" actually Python Strictly followed “ Subclass methods precede parent methods ” The principle of succession , It doesn't destroy common sense !"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Last but not least ,\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"missing\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() It's a special case .《 smooth Python》 Just a simple and vague sentence , Not too much unfolding ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" After preliminary experiments , I found that when subclasses define this method ,get() Read nonexistent key when , Normal return None; however \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"getitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() and dd['xxx'] Read nonexistent key when , Will be defined by subclass \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"missing\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() To deal with ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a1/a10b398fddb3b8febe00be5cf50e5a94.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" I haven't had time to analyze , Please leave me a message if you know the answer ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5、 Best practices for subclassing built-in types "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" in summary , There is no problem with subclassing built-in types , It's just that we don't recognize the special method (C Methods of language implementation ) The true face of , Will lead to the deviation of the result ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" that , This calls up a new question :"},{"type":"text","marks":[{"type":"strong"}],"text":" If you have to inherit a built-in type , What is the best practice ?"},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" First , If after inheriting a built-in type , It doesn't rewrite (overwrite) Its special method , There's no problem with subclassing ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" secondly , If you want to override a particular method after inheritance , Remember to rewrite all the methods you want to change , for example , If you want to change get() Method , Will rewrite get() Method , If you want to change \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"getitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() Method , It's going to be rewritten ……"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" however , If we just want to rewrite some logic ( namely C The language part ), If all the special methods used to use the logic have changed , For example, rewrite \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() The logic of , At the same time, initialize and update() Wait for the operation to change , So what to do ?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" We know that there is no reuse between special methods , That is to say, simply define new \\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"setitem\\"},{"type":"text","marks":[{"type":"italic"}],"text":"\\"},{"type":"text","text":"() It's not enough. , that , How can we influence multiple methods at the same time ?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"PyPy This unofficial Python The version found this problem , What it does is to make special methods of built-in types call , Establish a connection between them ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" official Python Of course, I'm aware of this problem , But it doesn't change the nature of the built-in type , It's about offering new solutions :UserString、UserList、UserDict……"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f7/f7a80b82545ac5f5f521c1c253eb837c.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Except for the name , They are basically equivalent to built-in types ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The basic logic of these classes is to use Python Realized , This is equivalent to the previous article C Some of the logic of the language interface has moved to Python Interface , Set up the call chain on the left side , In this way , It solves the reuse problem of some special methods ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In contrast to the previous example , After adopting a new way of inheritance , The result is as expected :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"from collections import UserDict\n\nclass DoppelDict(UserDict):\n def __setitem__(self, key, value): \n super().__setitem__(key, [value] * 2)\n\ndd = DoppelDict(one=1) # {'one': [1, 1]}\ndd['two'] = 2 # {'one': [1, 1], 'two': [2, 2]}\ndd.update(three=3) # {'one': [1, 1], 'two': [2, 2], 'three': [3, 3]}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" obviously ,** If you want to inherit str/list/dict Words , The best practice is to inherit "},{"type":"codeinline","content":[{"type":"text","text":"collections"}]},{"type":"text","text":" The classes provided by the library .** "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6、 Summary "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" I've written this much , It's time to do ending 了 ~~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In the previous article in this series ,Python Cats from the search order and speed of two aspects , Analysis of the “"},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/YtfPlE9JAIS3tpLBGFo5ag","title":""},"content":[{"type":"text","text":" Why built in functions / Built in types are not everything "}]},{"type":"text","text":"”, This article follows it in the same vein , It also reveals some mysterious and seemingly flawed behavior of the built-in type ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Although this article is from 《 smooth Python》 The inspiration from the book , But beyond the surface of language , We asked one more question “ Why? ”, Thus further analysis of the phenomenon behind the principle ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In short ,"},{"type":"text","marks":[{"type":"strong"}],"text":" Special methods for built-in types are created by C Language independent implementation of , They are Python There is no call relation in the language , So when subclassing a built-in type , A particular method that is overridden only affects the method itself , It doesn't affect the effect of other special methods ."},{"type":"text","text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" If we have a misconception about the relationship between particular methods , You might think Python Destroyed “ Subclass methods precede parent methods ” The basic principle of inheritance is .( unfortunately 《 smooth Python》 and PyPy They all have this wrong perception )"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In order to meet the general expectations of built-in types ,Python In the standard library UserString、UserList、UserDict These extension classes , It is convenient for programmers to inherit these basic data types ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" At the end : This paper belongs to “"},{"type":"link","attrs":{"href":"https://github.com/chinesehuazhou/python-whydo","title":""},"content":[{"type":"text","text":"Python Why? "}]},{"type":"text","text":"” series (Python Cat products ), The series focuses on Python The grammar of 、 Design and development , One by one “ Why? ” This is the starting point , Try to show Python The charm of . If you have other topics of interest , Welcome to fill in 《[Python One hundred thousand why ?](https://mp.weixin.qq.com/s/jobdpO7BWWON0ruLNpn31Q) 》 In the questionnaire in ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/35/350d03c893259603e1280f82429061a6.jpeg","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" official account 【"},{"type":"text","marks":[{"type":"strong"}],"text":"Python cat "},{"type":"text","text":"】, Series of excellent articles , Yes Python Why series 、 Meow philosophy Cat Series 、Python Advanced Series 、 Good book recommendation series 、 Technical writing 、 High quality English recommendation and translation, etc , Welcome to pay attention ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}