python import xx和from xx import x 中的坑

先回顾一下理解程度

什么是不可变类型和可变类型?

  可变类型是,修改变量后 引用的内存地址不变,引用的内存中的内容发生变化(是针对变量名的引用来理解)。

# 在a.py中定义了一个test属性
test = [1, 2]
print(test ,id(test))
test.append('jack')
print(test, id(test))


结果
C:UsersjackendoffAppDataLocalProgramsPythonPython36-32python.exe D:/pycharm_project/test_import/a.py
[1, 2] 44687112
[1, 2, 'jack'] 44687112

Process finished with exit code 0
可变类型

  不可变类型,修改变量后,内存地址发生变化,引用的内容也发生变化(针对变量名的引用理解),(如int类型再内存中的存储id是固定的,不同的数字存储的位置是确定的)

# 在a.py中定义了一个test属性
test = 5
print(test, id(test))
test = 6
print(test, id(test))


结果
C:UsersjackendoffAppDataLocalProgramsPythonPython36-32python.exe D:/pycharm_project/test_import/a.py
5 1795613520
6 1795613536

Process finished with exit code 0
不可变类型

 

 下面写四个脚本,验证import的 导入对象的属性 是不可变类型的修改,jia.py是导入了b.py和c.py两个模块,并运行,(千万不要起abc.py,它是内置模块)

1 # 在a.py中定义了一个test属性
2 test = 2
3 print('in a')
a.py
import a
# 引用了a.py模块,是整个模块的引用
print('first print in b.py', a.test)
a.test = 3
print('second print in b.py', a.test)

''' 注意区分模块和包的含义
    模块就是一个x.py的程序
    包是包含许多xx.py程序的文件夹(该文件夹中必须有__init__.py程序)
'''
b.py
import a
# 引用了a.py模块
print('first print in c.py', a.test)

a.test = 4
print('second print in c.py', a.test)
c.py
# abc.py是python内置模块的名字,脚本名字别乱起
import b
import c
print('first print in jia.py', b.a.test)
print('second print in jia.py', c.a.test)
jia.py
C:UsersjackendoffAppDataLocalProgramsPythonPython36-32python.exe D:/pycharm_project/test_import/jia.py
in a
first print in b.py 2
second print in b.py 3
first print in c.py 3
second print in c.py 4
first print in jia.py 4
second print in jia.py 4

Process finished with exit code 0
jia.py的运行结果

 b.py中second print和c.py中first print输出都是3,说明b.py已经修改了模块的属性

下面再写四个脚本,验证from xx import x 能不能对模块的不可变类型属性修改,jia.py是导入了b.py和c.py两个模块,并运行。

# 在a.py中定义了一个test属性
test = 2
print('in a')
a.py
from a import *
# 引用了a.py模块,是整个模块的引用
print('first print in b.py', test)
test = 3
print('second print in b.py', test)
b.py
from a import *
# 引用了a.py模块
print('first print in c.py', test)

test = 4
print('second print in c.py', test)
c.py
# abc.py是python内置模块的名字,脚本名字别乱起
import b
import c
print('first print in jia.py', b.test)
print('second print in jia.py', c.test)
jia,py
C:UsersjackendoffAppDataLocalProgramsPythonPython36-32python.exe D:/pycharm_project/test_import/jia.py
in a
first print in b.py 2
second print in b.py 3
first print in c.py 2
second print in c.py 4
first print in jia.py 3
second print in jia.py 4

Process finished with exit code 0
jia.py的运行结果

 b.py中second print和c.py中first print输出一个是3一个是2,说明b.py没有修改了模块的属性

下面再写四个脚本,验证from xx import x 能不能对模块的可变类型属性修改,jia.py是导入了b.py和c.py两个模块,并运行。

# 在a.py中定义了一个test属性
test = [1, 2]
print('in a')
a.py
from a import *
# 引用了a.py模块,是整个模块的引用
print('first print in b.py', test)
test.append('b')
print('second print in b.py', test)

''' 注意区分模块和包的含义
    模块就是一个x.py的程序
    包是包含许多xx.py程序的文件夹(该文件夹中必须有__init__.py程序)
'''
b.py
from a import *
# 引用了a.py模块
print('first print in c.py', test)

test.append('c')
print('second print in c.py', test)
c.py
# abc.py是python内置模块的名字,脚本名字别乱起
import b
import c
print('first print in jia.py', b.test)
print('second print in jia.py', c.test)
jia.py
C:UsersjackendoffAppDataLocalProgramsPythonPython36-32python.exe D:/pycharm_project/test_import/jia.py
in a
first print in b.py [1, 2]
second print in b.py [1, 2, 'b']
first print in c.py [1, 2, 'b']
second print in c.py [1, 2, 'b', 'c']
first print in jia.py [1, 2, 'b', 'c']
second print in jia.py [1, 2, 'b', 'c']

Process finished with exit code 0
jia.py的运行结果

b.py中second print 和 c.py中first print 输出的都是[1, 2, 'b'],说明b.py已经修改了模块的属性

总结:使用import xx 可以修改模块对象的属性(无论属性是不是可变类型)

      使用from xx import x 只能修改模块对象的属性是可变类型的(不可变类型不能修改)

这也是为甚麽,尽量不要使用 from XX import * 的原因,会发生属性错误,

这也是为什么,导入模块需要写在程序开头的位置,并且先导入内置模块,再导入库模块,再导入自定义模块

原文地址:https://www.cnblogs.com/serpent/p/9454130.html