设为首页 - 加入收藏
广告 1000x90
您的当前位置:黄大仙救世网www78345 > 解释器 > 正文

同样的python代码通过python文件运行正常但是直接在解释器里面逐

来源:未知 编辑:admin 时间:2019-07-25

  同样的python代码通过python文件运行正常,但是直接在解释器里面逐行写的时候报语法错误,这是为什么呢?

  同样的python代码通过python文件运行正常,但是直接在解释器里面逐行写的时候报语法错误,这是为什么呢?

  我还没入门的,这个问题是在学习HeadFirstpython(中文版)这本书的108和112页的时候发现的,108页print(man)和print(other)这两行代码如果在IDLE里面接着输入报语法错误,但是如果...

  我还没入门的,这个问题是在学习HeadFirst python(中文版) 这本书的108和112页的时候发现的,108页print(man)和print(other)这两行代码如果在IDLE里面接着输入报语法错误,但是如果将代码完整写入py文件再运行就正常。112页后面的try/except部分也是一样的情况。

  可选中1个或多个下面的关键词,搜索相关资料。也可直接点“搜索资料”搜索整个问题。

  展开全部对于Python而言,存储好的脚本文件(Script file)和在Console中的交互式(interactive)命令,执行方式不同。对于脚本文件,解释器将其当作整个代码块执行,而对于交互性命令行中的每一条命令,解释器将其当作单独的代码块执行。而Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,如果存在,会将其重用(这句话不够严谨,后面会详谈)。所以在你给出的例子中,文件执行时(同一个代码块)会把a、b两个变量指向同一个对象;而在命令行执行时,a、b赋值语句分别被当作两个代码块执行,所以会得到两个不同的对象,因而is判断返回False。

  这个问题远超我想象中的复杂。我本来以为我能用两分钟搞定这种每日一水的问题,结果我花了一个小时搜来搜去,读来读去,还跑去群里跟人讨论了一阵,都没能找到答案。

  大概两个小时以后,我找到了相对正确的答案,把自己已经弄懂的部分强答一番,并邀请一些大神,希望能看到更为准确的回答。

  这个问题的博大精深在于,能从中扯出许多小问题来,虽然这些东西很细枝末节,很trick,在日常编程中不怎么用的到,更不怎么需要额外关注,但是理解这些问题,对于我们理解Python的对象机制乃至内存处理机制有很大的帮助。

  我从头开始说,大概会分以下几个部分来谈,每个部分其实都能展开很广,这次就把与问题相关的知识简单一提:

  (虽然我觉得按照我寻找答案的过程讲,可能对认知更有帮助,但是理清头绪的话可能更好理解,之后会找时间为这个问题写篇文章好好记录一下)

  声明:以下所讲机制,与Python不同版本的具体实现有关(implement specific)可能不同。

  首先我们要记住一句话,一切皆对象。Python中把任何一种Type都当作对象来处理。其中有一些类型是不可变的,比如:

  这个还是好理解的,在初始化赋值一个字符串后,我们没有办法直接修改它的值。但是数字呢?数字这种变来变去的又怎么理解。

  可以看出,a的值虽然从10变成了11,但是a这个变量指向内存中的位置发生了变化,也就是说我们并没有对a指向的内存进行操作,而是对a进行了重新赋值。

  个人感觉,有性能上的考虑(比如对一些固定不变的元素给予固定的存储位置,整数这样操作比较方便,字符串的话涉及一些比较也会减少后续操作的时间),也有一些安全上的考虑(比如列表中的值会改变,元组不会)。这个我也不太精通,就不展开谈了。

  前面已经提过一次,Python中一切皆对象。对象包含三个要素,id、type、value。

  当两个变量指向了同一个对象时,is会返回True(即is比较的是两个变量的id);

  当两个变量的值相同时,==会返回True(即==比较的是两个变量的value)。

  但是第二个就不那么好理解了,尤其是配合下面这个(假定我们已经知道命令行中的语句执行是单独执行两次不会相互影响,后面会具体解释):

  为什么a、b分别赋值1000时is比较返回False,可以分别赋值100就会返回True?

  Python程序的结构——代码块&Python的内存管理——新建对象时的操作

  先来看最让我们困惑的,也就是题主给出的示例吧(接下来用float演示,int是同样的情况):

  其实从结果论出发,我们很容易猜到结论,就像题主自己也猜了个差不多——缓存机制不同。毕竟is比较的就是对象的id,也就是对象在内存中的位置,也就是是不是同一个对象。

  既然脚本文件的执行结果是True,那么,他俩就是同一个对象;既然命令行执行的结果是False,那么他俩就不是同一个对象。(这他喵的不是废话吗!)

  所以我开始了漫长的找原理的过程……然而网上这方面提及的实在太少。尤其是大家的大部分讨论都是int的小整数缓存机制;就算讨论到了float,也不实际解决我们的问题。

  其实我都快要放弃了,漫无目的地翻stackoverflow推荐的相关问题时终于找到了一个类似的情况,但是人家并不是比较的脚本文件和命令行执行,而是比较的函数体和赋值语句:

  同样的代码,拆开就是False,放函数里就是True!是不是很像我们遇到的情况了。

  代码块作为一个执行单元,一个模块、一个函数体、一个类定义、一个脚本文件,都是一个代码块。

  至此问题解决……了吗?视作一个代码块,就意味着要把相同value的赋值指向相同的对象吗?

  通过compile()函数和dis模块的code_info()函数来检测我们执行的命令的信息。

  把10.0 10.0 10.1分别赋值给a,b,c,可以看出结果中其实只保存了一个10.0,也就是a,b共用了这个数值。

本文链接:http://heargear.net/jieshiqi/646.html

相关推荐:

网友评论:

栏目分类

现金彩票 联系QQ:24498872301 邮箱:24498872301@qq.com

Copyright © 2002-2011 DEDECMS. 现金彩票 版权所有 Power by DedeCms

Top