当前位置: 首页 > news >正文

python导入语句的几点说明

python导入语句的几点说明

在 Python 中,import 和 from ... import ... 构成了 导入语句(import statement)。它们属于 Python 的语法结构,用于模块和包的导入。

(1)import 语句的完整语法

import module_name [as alias]

其中:

module_name: 要导入的模块名称。

as alias(可选): 为模块指定一个别名,方便后续使用。

示例:

import math as m  # 导入 math 模块并命名为 m
print(m.sqrt(16))  # 使用别名 m 调用 sqrt 函数

(2)from ... import ... 语句的完整语法

from module_name import name1 [, name2, ...] [as alias]

其中:

odule_name: 要导入的模块名称。

name1, name2, ...: 模块中要导入的具体对象(如函数、类或变量),可以列出多个,用逗号分隔。

as alias(可选): 为导入的对象指定一个别名。

示例:

from math import sqrt, pi  # 从 math 模块中导入 sqrt 和 pi
print(sqrt(16))  # 直接使用 sqrt 函数
print(pi)  # 直接使用 pi 变量

(3)from ... import * 语句的语法

其中:

*: 表示从模块中导入所有公开的内容(即不以下划线 _ 开头的内容)。

注意:这种方式可能容易导致命名冲突,通常不推荐在大型项目中使用。

示例:

from math import *  # 导入 math 模块中的所有内容
print(sqrt(16))  # 直接使用 sqrt 函数
print(pi)  # 直接使用 pi 变量

特别说明

根据具体需求选择合适的导入方式或组合使用,可以提高代码的可读性和效率。

import 导入整个模块,需要使用模块名来调用其中的内容。

from ... import 导入模块中的特定内容,可以直接使用,无需模块名前缀。

☆ import module_name 的优缺点

优点:

命名空间清晰:

使用 import module_name 的方式会将所有内容封装在模块的命名空间中(如 math.sqrt),避免了全局命名空间的污染。

如果多个模块中有同名的函数或变量,这种方式可以有效避免冲突。

可读性更高:

明确指出了函数或变量来自哪个模块,便于理解和维护代码。

例如:

import math
print(math.sqrt(16))  # 显式表明 sqrt 来自 math 模块

易于调试:

如果需要检查某个模块的功能,可以直接通过模块名访问其内容,而不需要记住每个单独导入的对象。

缺点:

需要显式地通过模块名访问对象,可能会导致代码稍微冗长。

☆ from module_name import name 的优缺点

优点:

简洁性:

导入后可以直接使用对象名称,无需通过模块名访问,代码更简洁。

例如

from math import sqrt
print(sqrt(16))  # 直接调用 sqrt 函数

减少冗余:

如果只需要使用模块中的少数几个功能,这种方式可以避免频繁输入模块名。

缺点:

命名冲突风险:

如果多个模块中有同名的函数或变量,可能会导致命名冲突。

例如

from math import pi
from another_module import pi  # 可能覆盖 math 中的 pi

可读性降低:

不容易看出某个函数或变量来自哪个模块,可能增加代码的理解难度。

全局命名空间污染:

将模块中的对象直接导入到全局命名空间中,可能导致命名混乱。

☆ from module_name import * 的问题

全局命名空间污染:将模块中的所有公开内容导入到全局命名空间中,容易引发命名冲突。

降低可读性:无法明确知道哪些函数或变量来自哪个模块。

不推荐使用:除非是交互式解释器中用于快速测试,否则应避免在正式代码中使用。

综合之,推荐使用的方式

优先推荐:import module_name

适当使用:from module_name import name

避免使用:from module_name import *

全局命名空间污染

“全局命名空间污染”是指在程序的全局作用域中导入了过多的变量、函数或类,从而可能导致命名冲突或命名混乱。这种情况通常发生在使用 from module_name import * 或频繁使用 from module_name import name 的方式时。

全局命名空间

全局命名空间是程序中所有全局变量、函数和类的集合。

在 Python 中,当你定义一个变量或导入一个模块时,它们会被添加到当前的作用域中。

如果你在全局作用域中导入了过多的内容,可能会导致命名冲突或难以追踪某个名称的来源。

命名空间污染的例子

假设你有两个模块 module1.py 和 module2.py,它们都定义了一个名为 value 的变量:

module1.py:
value = 10

module2.py:
value = 20

如果你在主程序中使用 from ... import * 导入这两个模块:

from module1 import *
from module2 import *

print(value)  # 注意输出什么?

在这种情况下,value 的值会是 20,因为 module2 中的 value 覆盖了 module1 中的 value。这会导致命名冲突,并且代码的行为可能不符合预期。

模块

简单的来说,一个Python代码文件就是一个模块。例如,文件 utils.py 对应模块 utils。

在模块文件的顶层(不在函数、类内部)定义的所有标识符(变量、函数、类、导入的子模块等),均会成为模块对象的属性。例如

# 文件 utils.py
PI = 3.14                     # 属性 utils.PI
def calculate():              # 属性 utils.calculate
    return "Calculating..."

class Converter:              # 属性 utils.Converter
    def convert(self, value):
        return value * 2

import json                 # 导入标准库模块json。属性 utils.json

在另一个文件(如 my_main.py)中,外部可通过 模块名.属性名 直接访问这些属性:

# 文件 my_main.py
import utils

# 访问变量 PI
print("Value of PI:", utils.PI)  # 输出: Value of PI: 3.14

# 访问函数 calculate
result = utils.calculate()
print("Result of calculate:", result)  # 输出: Result of calculate: Calculating...

# 访问类 Converter
converter_instance = utils.Converter()     # 实例化类
converted_value = converter_instance.convert(5)
print("Converted value:", converted_value)  # 输出: Converted value: 10

# 访问导入的标准库模块 json
data = '{"key": "value"}'
parsed_data = utils.json.loads(data)
print("Parsed JSON data:", parsed_data)  # 输出: Parsed JSON data: {'key': 'value'}

运行了 main.py,输出将会是:

Value of PI: 3.14
Result of calculate: Calculating...
Converted value: 10
Parsed JSON data: {'key': 'value'}

Python会为每个文件建立一个模块对象,模块对象包含所有顶层定义的标识符(变量、函数、类等),这些标识符就是模块对象的属性。一个模块也可以说是一个命名空间。所以可以这样说:一个文件就是一个模块对象,也是一个命名空间。

命名空间是一组名称(变量名、函数名、类名等)到对象的映射。模块的命名空间就是模块对象中所包含的所有名称。

在一个代码文件的顶层(也就是不在函数或类的主体内——不在def或class之内)每一个赋值了的变量名都会变成该模块的属性。

例如,假设模块文件M.py的顶层有一个像X = 1这样的赋值语句,而变量名X会变成M的属性,我们可在模块外以M.X的方式对它进行引用。变量名X对M.py内其他代码而言也会变成全局变量。

假设 M.py 内容如下:

X = 1           # 模块属性 M.X
def func():     # 模块属性 M.func
    return "Hello from M"
class MyClass:  # 模块属性 M.MyClass
    pass

外部通过 import M 后,可通过 M.X、M.func、M.MyClass 访问这些属性。在另一个文件中可以这样使用:

import M

print(M.X)  # 输出: 1
print(M.func())  # 输出: Hello from M

局部命名空间:当进入函数或类时,会创建一个新的局部命名空间,局部变量不会污染模块的全局命名空间。

局部变量不会污染全局命名空间的示例如下

示例 1:函数中的局部变量,源码如下:

X = 10  # 全局变量

def my_function():
    X = 20  # 局部变量
    print("Inside function:", X)

my_function()
print("Outside function:", X)

输出:

Inside function: 20
Outside function: 10

解释:

X = 10 是一个全局变量。

在 my_function 内部,X = 20 定义了一个局部变量 X,它与全局变量 X 是完全独立的。

函数内部对 X 的修改不会影响全局变量 X。

示例 2:类中的局部变量,源码如下:

X = 10  # 全局变量

class MyClass:
    X = 20  # 类属性
    def my_method(self):
        X = 30  # 局部变量
        print("Inside method:", X)

obj = MyClass()
obj.my_method()
print("Class attribute:", MyClass.X)
print("Global variable:", X)

输出:

Inside method: 30
Class attribute: 20
Global variable: 10

解释:

X = 10 是全局变量。

MyClass.X = 20 是类属性,属于类的命名空间。

在 my_method 方法中,X = 30 是局部变量,只在方法的作用域内有效。

这三个 X 分别位于不同的命名空间中,互不干扰。

为什么局部变量不会污染全局命名空间?

Python 使用作用域规则(LEGB规则)来查找变量:

L(Local):首先在当前函数或类的局部命名空间中查找。

E(Enclosing):如果找不到,则查找外部嵌套函数的命名空间(闭包作用域)。

G(Global):如果仍然找不到,则查找模块的全局命名空间。

B(Built-in):最后查找内置命名空间。

因此,局部变量仅在局部命名空间中有效,不会影响全局命名空间。

附录

python之import语句的用法https://blog.csdn.net/cnds123/article/details/118437585

python复杂程序的组织讲座(修订) https://blog.csdn.net/cnds123/article/details/108614392

python中的自定义模块及其使用 https://blog.csdn.net/cnds123/article/details/107087019

Python的模块(module)和包(package) https://blog.csdn.net/cnds123/article/details/127222567

Python青少年简明教程:模块 https://blog.csdn.net/cnds123/article/details/141606921

Python第三方模块(库、包)安装、卸载与查看及常见问题解决(修订)https://blog.csdn.net/cnds123/article/details/104393385

查看Python安装路径几种方法https://blog.csdn.net/cnds123/article/details/101546889

相关文章:

  • OpenCV计算摄影学(14)实现对比度保留去色(Contrast Preserving Decolorization)的函数decolor()
  • TypeError: Cannot create property ‘xxx‘ on string ‘xxx‘
  • HTTP 与 HTTPS 协议:从基础到安全强化
  • C语言学习知识点总结(适合新手/考试复习)
  • 项目--高并发CPP内存池,低配版本
  • 【人工智能】Deepseek 与 Kimi 联袂:重塑 PPT 创作,开启智能演示新纪元
  • springBoot集成声明式和编程式事务的方式
  • Python基于Django的图书馆管理系统【附源码、文档说明】
  • RangeError: Invalid array length
  • linux0.11内核源码修仙传第五章——内存初始化(主存与缓存)
  • 高颜值多端适用软件:兼具屏保功能,PC 端登录可用
  • 数据结构(队列)
  • DeepSeek-R1本地化部署(Mac)
  • 【原创】springboot+vue实验室预约管理系统设计与实现
  • 增删改查 数据下载 一键编辑 删除
  • SpringSecurity认证授权完整流程
  • 城市霓虹灯夜景拍照后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • instr,locate是否使用索引实验
  • DeepSeek【部署 03】客户端应用ChatBox、AnythingLLM及OpenWebUI部署使用详细步骤
  • 并发编程——累加器
  • 教人怎么做网页的网站/成都网络营销公司
  • 网站建设 起飞/如何购买域名
  • 电子商务专业网站设计/韩国热搜榜
  • 做的好的宠物食品网站/最近新闻热点
  • 北京手机网站建设公司排名/郑州网络运营培训
  • 搜索引擎和浏览器/河南郑州网站推广优化外包