oct*_*ref 18 python import module
>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3
>>> import math
>>> math.pi
3
Run Code Online (Sandbox Code Playgroud)
初步问题:为什么我不能math.pi
回来?
我以为import
会将所有已定义的变量和函数导入当前范围.如果变量名已经存在于当前范围内,那么它将替换它.
是的,它确实取代了它:
>>> pi = 3
>>> from math import *
>>> pi
3.141592653589793
Run Code Online (Sandbox Code Playgroud)
然后我想也许这个math.pi = 3
任务实际上改变了math class
(或者它是math module
?)的属性,这是import math
导入的.
我是正确的:
>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> from math import *
>>> pi
3
Run Code Online (Sandbox Code Playgroud)
所以,似乎:
如果你这样做import x
,那么它x
就像一个类似的东西进口.如果您对x.property进行更改,则更改将在模块中保留,以便每次再次导入时,它都是修改后的版本.
真实的问题:
import
这样实现?为什么不让每一个import math
进口都是新鲜的,未修改的副本math
?为什么要让进口math
开放改变? math.pi
做完之后有没有办法解决math.pi = 3
(math.pi = 3.141592653589793
当然除外)? import math
比较优先from math import *
.但是这种行为让我担心如果我这样做,其他人可能会修改我导入的模块......我该import
怎么做?use*_*ica 13
Python只创建任何给定模块的一个副本.重复导入模块会重复使用原始模块.这是因为如果模块A和B导入C和D,导入E和F等,C和D将被加载两次,E和F将被加载4次,等等.除了最琐碎的依赖之外图表,你需要花费几分钟加载冗余模块,然后内存不足.此外,如果A导入的B和B导入A,您将陷入递归循环,再次耗尽内存而不做任何有用的操作.
解决方案:不要拧紧其他模块的内容.如果你这样做,这是一个翻译范围的变化.有时你会想要这样做,所以Python会让你,但这通常是一个坏主意.
Jos*_*Lee 10
可以多次导入模块.一个import
声明只是加载从参考sys.modules
.如果import
语句也从磁盘重新加载模块,那将非常慢.修改这样的模块是非常不寻常的,只能在罕见的记录情况下完成,因此无需担心.
如何重新加载模块:
>>> import imp
>>> imp.reload(math)
<module 'math' (built-in)>
>>> math.pi
3.141592653589793
Run Code Online (Sandbox Code Playgroud)
导入行为旨在允许模块具有状态.例如,运行初始化代码的模块可能具有基于初始化时发生的各种不同的行为(一个很好的例子是os模块,它根据你所使用的操作系统透明地加载不同版本的路径子模块) .通常的行为是允许许多不同的代码访问模块而不重复运行初始化.此外,模块的功能类似于其他语言中的静态类 - 它们可以维护状态,通常用作全局变量的替代:例如,您可以使用语言环境模块来设置本地文化变量(货币格式等) - 调用locale.setlocale在代码的一部分和local.getlocale中 在另一个是制作全局变量的一个很好的替代方案.
当然,你的例子指出了这个弱点.其中一个经典的python原则是
我们都是成年人
该语言并未提供您在Java或C#中找到的大量隐私管理功能,这些功能可让作者锁定模块或类的内容.如果您感觉恶意(或只是自杀),您可以完成您的示例中完成的那种事情:将pi更改为等于3,或将函数转换为变量或各种其他令人讨厌的东西.这种语言并不是为了使这一点变得困难 - 编码员需要负责.
@Josh Lee的答案显示了如何使用reload,这是将模块刷新到基于磁盘的状态的正确方法.使用重新加载的智慧主要取决于模块中的初始化代码量,以及导入或由相关模块导入的其他模块的Web.
归档时间: |
|
查看次数: |
660 次 |
最近记录: |