前两天做了网易的一道选择题:
问题描述:
python是用C语言写成的,根据名字空间特性,以下代码经过python编译器编译后,一共得到()个PyCodeObject对象。
class A:
pass
def Fun():
pass
a = A()
Fun()
复制代码
....啥是PyCodeObject???
说来话不是很长
这里分享一些学习的details。比如我在找寻A问题的原因,但是这时候B.C.D三个问题,越看越乱,最后:放弃。尝试着彻底一些解决问题,就会慢慢上道。
Okay BB了这么多,我想说的就是做事情要彻底,因为彻底之后会带来美妙的空虚,不是黄段子,是崔健的歌(蓝色骨头)...
从头开始 解释性语言?编译型语言?
编译型语言和解释型语言: 举个例子你创作了一本书,这时候你想找翻译帮你翻译成英锅历史方便你成为网红。那么你的秘书找来了两个翻译,翻译且打印:
1.编译型翻译(语言):从头开始一直给你翻译到你作品的最终一个标点符号,然后开始打印,1就可以歇了
2.解释型翻译(语言):就好像你妈在床头给你讲故事一样,翻译一句一句或者一段一段的,一句一句,然后一句一句一段一段打印,2一直陪着你
分析两种方法优劣:
1运行效率高,一次成型电梯洋房拎包入住,按你胃,就是一旦翻译完事,执行效率就很高了。
比如你让1给你翻译的时候,你发现呀我有一个字写错了,但是如果是1完成的话必须等他翻译完,然后再改好再让他翻译一遍。那如果是2翻译呢,一段一段一行一行,只需要重新翻译那一行就好了啊?
小总结:
要把你的code转化为电脑能看懂的语言,那么有两种计划
1.编译,像C一样,一旦编译成机器语言,直接给机器执行就好了,所以说执行效率很高很高
2.解释,省去了编译的过程,一行一行解释直接运行,像ruby这样的
WTF,说这么久都没说Python,那么python是什么?
Python与Java(基于虚拟机的语言)一样都是先编译再解释的语言,为什么说它编译过,很简单你打开尼德pycharm随便写一个.py文件运行成功就会发现文件夹中多出来一个.pyc文件,c就代表着complie啊,并且使用terminal运行.py文件,你得输入python xxx.py,对啊,这个词就是在唤醒解释器睡你MB起来嗨啊,给爸爸翻译别睡了呆子~
关于语言的区别先说到这里,接下来琢磨琢磨Python
pyc与PyCodeObject
先做一个小测试,我在本机写了如下代码,运行成功后,我想看看我该文件下是否有pyc文件
我擦?WTF为什么没有呢?
接着我们在新建一个.py文件把之前的memo文件中的say方法import一下
啊? 为什么pyc文件又出来了?
原因: PyCodeObject实际上是,python编译器在内存中编译成的结果,pyc文件可以看成是PyCodeObject在磁盘上的持久化,没有出pyc文件的原因是因为python解释器认为重用的代码块才值得搞pyc执行前在内存中看看是否在PyCodeObject中,如果在就不需要读取磁盘本地的pyc文件了。 过程如下
那么回到最初的问题,貌似圈子绕的有点大了
解答这个问题前,先说明一个概念--Code Block:
Python编译器在对Python源码进行编译的时候,对代码中的一个Code Block,会创建一个PyCodeObject对象与这段代码对应。
如何确定多少代码算一个Code Block?
Python中确定Code Block的规则:当进入一个新的名字空间或作用域时,就算进入了一个新的Code Block了。
即:一个名字空间对应一个Code Block,它会对应一个PyCodeObject。
现在暂且认为名字空间就是符号的上下文环境,是名字到对象的映射。
在Python中,类、函数和module都对应着一个独立的名字空间,因此都会对应一个PyCodeObject对象。
class A:
pass
def Fun():
pass
a = A()
Fun()
复制代码
Python编译器对上面的code源码编译之后,会创建3个PyCodeObject对象:第一个是对应整.py文件代表的Code Block,第二个是对应Class A代表的Code Block,第三个是对应f代表的Code Block。
正确答案查了一下是三个,小手一抖 三分到手,That's all thx~