首页 > 子类化内置类型

子类化内置类型

Python 2.2之后内置类型开始可以子类化了

但是,CPython中的内置类型不会调用用户重写的类的特殊方法。

PyPy的文档中描述了这个问题。subclasses-of-built-in-types

正式情况下,CPython 并没有官方规定内置类型的子类中重写的方法是否会被隐式调用。基本上,这些用户重写的方法不会被同一对象的其他内置方法调用。例如,在dict的子类中重写的 `__getitem__()` 方法不会被内置的 `get()` 方法调用。以上情况在CPython和PyPy中都是一致的。在内置函数或方法是否会调用另一个对象的重写方法而不是self上,两者会出现差异。PyPy经常会在Cpython不调用的情况下调用。

两个例子:

ex1:

class D(dict):def __getitem__(self, key):return "%r from D" % (key,)class A(object):passa = A()
a.__dict__ = D()
a.foo = "a's own foo"
print a.foo
# CPython => a's own foo
# PyPy => 'foo' from D

ex2:

glob = D(foo="base item")
loc = {}
exec "print foo" in glob, loc
# CPython => base item
# PyPy => 'foo' from D

原生类型的这种行为违背了面向对象编程的一个基本原则:始终应该从实例(self)所属的类开始搜索方法,即使在超类实现的类中调用也是如此。(不过 __missing__ 方法是个特例。)

在CPython的实现结构中,内建方法大部分会忽略用户重写的特殊方法,所以产生了UserDict,UserString,UserList来解决这个问题。

In : class NewDict(dict):
...:     def __getitem__(self, key):
...:         return 42
...:     
In : d = NewDict(a=1)
In : d
Out: {'a': 42}
In : d2 = {}
In : d2.update(d)       #CPython中的update会忽略NewDict中的__getitem__方法
In : d2
Out: {'a': 1}

因此用户如果自己定义的类应该继承collections模块中的类。而不是子类化内置类。

*《流畅的Python》 12.1

转载于:https://www.cnblogs.com/leisurelylicht/p/zi-lei-hua-nei-zhi-lei-xing-subclassesofbuiltintyp.html

更多相关:

  • 来源:公众号|计算机视觉工坊(系投稿)作者:仲夏夜之星「3D视觉工坊」技术交流群已经成立,目前大约有12000人,方向主要涉及3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、...

  • 点云PCL免费知识星球,点云论文速读。文章:Real-Time LIDAR-Based Urban Road and Sidewalk Detection for Autonomous Vehicles作者:Ern˝o Horváth  , Claudiu Pozna ,and Miklós Unger编译:点云PCL代码:http...

  • 文章:Semantic Histogram Based Graph Matching for Real-Time Multi-Robot Global Localization in Large Scale Environment作者:Xiyue Guo, Junjie Hu, Junfeng Chen, Fuqin Deng, T...

  • 点云PCL免费知识星球,点云论文速读。文章:Robust Place Recognition using an Imaging Lidar作者:Tixiao Shan, Brendan Englot, Fabio Duarte, Carlo Ratti, and Daniela Rus编译:点云PCL(ICRA 2021)开源代码:...

  • 文章:A Survey of Calibration Methods for Optical See-Through Head-Mounted Displays作者:Jens Grubert , Yuta Itoh, Kenneth Moser编译:点云PCL本文仅做学术分享,如有侵权,请联系删除。欢迎各位加入免费知识星球,获取PD...

  • initializeGL函数由于是初始化,所以只调用一次 而resizeGL和paintGL会多次调用 resizeGL在正常的情况下,触发的条件是,窗口大小发生变化时,resizeGL被调用,之后会触发paint事件,从而调用paintGL()事件处理器。 paintGL在正常的情况下,只要你移动窗口的位置,就会马上触发pain...

  • 思考:在析构函数中delete this指针,运行下面代码会产生什么样的结果呢? #include   using namespace std;    class A{  public:  A(){  cout<<"A()"<

  • (1)如果用定时器的话,初始的时候注册一个定时器的回调函数,原型是 glutTimerFunc(unsigned int millis, void (*func)(int value), int value);         参数对应关系为:glutTimerFunc(毫秒数, 回调函数指针, 区别值); (2)写自己的回调函数 v...

  • 0x00 前置信息 VLC是一个非常庞大的工程,我从它的架构及流程入手进行分析,涉及到一些很细的概念先搁置一边,日后详细分析。 0x01 源码结构(Android Java相关的暂未分析) # build-android-arm-linux-androideabi/:第三方库。 # modules/:模块代码。 # modules/...