随着 Python 项目的增大,各个模块间的依赖关系将会越来越复杂
如果不合理组织文件模块结构,规划好层级关系,很容易就出现 循环导入(A import B, B import A)
而不幸的是 Python 的包导入机制并没有帮我们检测循环导入(而 Golang 在编译阶段会报错)
一方面我们可以重构(动态一时爽,重构火葬场),借助优秀的设计模式来降低模块间的耦合(最根本)
而另一方面我们可以借助一些小技巧稍微改动代码结构来避免循环导入(治标不治本)
随着 Python 项目的增大,各个模块间的依赖关系将会越来越复杂
如果不合理组织文件模块结构,规划好层级关系,很容易就出现 循环导入(A import B, B import A)
而不幸的是 Python 的包导入机制并没有帮我们检测循环导入(而 Golang 在编译阶段会报错)
一方面我们可以重构(动态一时爽,重构火葬场),借助优秀的设计模式来降低模块间的耦合(最根本)
而另一方面我们可以借助一些小技巧稍微改动代码结构来避免循环导入(治标不治本)
由于CPython的优化,有时会发生字符串驻留(intern)
即在某些情况下尝试使用现有的不可变对象而不是每次都创建一个新对象
这些驻留的对象在内部使用类似字典的结构(驻留池)进行驻留
在被驻留之后,许多变量可能指向内存中的相同字符串对象,从而节省内存
下面的代码片段中,字符串是被隐式驻留的,何时隐式驻留字符串取决于字符串本身的特点
也就是说字符串是否会被隐式驻留是有条件的
(至于显式驻留,后面会讲到,以下的 CPython 源码剖析全部基于 CPython3.6)
当我们实例化某个类时,如:a = A()
, Python 先调用 __new__(cls[, ...])
来生成实例
然后传递给 __init__(self[, ...])
的 self,从而在 __init__(self[, ...])
中完成初始化
因此 __new__()
负责创建实例对象,而 __init__()
负责初始化该实例对象:
都知道 Python 有强大的动态语言特性,得益于它“无处不对象”的语言设计思想
那么这些对象的源头来自哪里?这背后一定有它的出发点。
相信很多人一下就想到元类(metaclass
)那种复杂的东西,且慢,心急吃不了热豆腐
在深入研究元类编程之前,一些基本的但也是最重要的语言知识一定要弄清楚,否则会一头雾水
在此之前,明白 Python 中 type
与 object
的关系至关重要,它俩才是 Python 中一切对象的出发点。