Python中的包和模块 module, package

1. 概述

模块化编程是指将大型、繁杂的编程任务拆分为更小的、各自独立的、更易于管理的子任务或模块的过程。然后可以将各个模块拼凑在一起以创建更大的应用程序。

应用程序中模块化代码有几个优点:

  • 简单性:一个模块通常只关注问题的一小部分。这使得开发更容易,更不容易出错。

  • 可维护性:模块化设计为任务强制划分了逻辑边界。如果模块之间以最小化相互依赖的方式编写,那么对单个模块的修改对程序其他部分产生影响的可能性就会降低。(甚至可以在不了解模块外的应用程序的情况下对模块进行更改。)

  • 可重用性:在单个模块中定义的功能可以被应用程序的其他部分轻松重用(通过适当定义的接口)。这消除了重复代码的需要。

  • 范围:模块通常定义一个单独的命名空间,这样可以避免程序不同作用域中变量之间的冲突。

 Python 中实现代码模块化的结构包括函数模块包, 本文介绍其中的模块和包.

1. 模块和包

1.1 模块-module

Python.org中定义模块如下

用作 Python 代码组织单元的对象。模块有一个包含任意 Python 对象的命名空间。模块通过import过程加载到 Python 中。

 事实上实践中创建一个模块是非常简单的, 一个以 .py 结尾的文件就是一个模块.模块中的变量, 函数都可以通过 import 语句被加载到其他模块来使用.

新建一个 module.py 文件, 内容如下, 我们定义了2个变量 var 和 array . 定义了1个函数func和1个类Demo.

var = "right."
array = [10, 20, 30]

def func(arg):
    print(f'arg = {arg}')

class Demo:
    pass

然后在当前目录打开Python交互式命令行.

In [1]: import module
In [2]: module.var
Out[2]: 'right.'
In [3]: module.array
Out[3]: [10, 20, 30]
In [4]: module.func('data')
arg = data
In [5]: demo = module.Demo()
In [6]: demo
Out[6]: <module.Demo at 0x1ec5e0a81c8>

通过 import module 将module模块加载到当前作用域, 可以通过  module.  语法来使用module中的变量和函数和类. 

1.2 包-package

Python.org 词汇表定义如下:

可以包含子模块或递归子包的 Python 模块。从技术上讲,包是具有__path__属性的 Python 模块。

包提供了更高层次的组织代码的方法, 包可以把模块进行分组分层结构, 可以把包理解成一个包含多个模块的文件夹.

创建一个包同样非常简单, 只需要将几个模块放到一个文件夹目录中, 然后在目录中创建一个__init__.py文件, 即可将这个文件夹转化成一个包.

如上例即创建了一个包含2个模块 module1 和 module2 的包 package. 

导入包中的模块, 需要带上包的名称. 或者使用 from ... import ... 语法

In [1]: import package
In [2]: import package.mudule1
In [3]: from package import mudule2

包中可以包含任意深度嵌套子包, 大型项目中, 可以创建复杂的目录结构来组织代码.

 

2 导入语句 import

 2.1 部分导入

有些时候我们只需要模块中的某一个对象, 可以选择不导入整个模块的方式, 使用部分导入 from <module> import <name>

In [1]: from math import pi

In [2]: pi
Out[2]: 3.141592653589793

2.2 ☹️全部导入

使用  from <module> import *  可以一次将模块下所有对象导入到当前空间.使用这个方法将我们之前创建的module.py模块导入.

In [1]: from module import *
In [2]: var
Out[2]: 'right.'
In [3]: array
Out[3]: [10, 20, 30]
In [4]: func('data')
arg = data
In [5]: demo = Demo()
In [6]: demo
Out[6]: <module.Demo at 0x24aaa748248>

使用module中的对象, 可以看到不再需要用module.var, 而是直接使用var.

实际使用中尽量杜绝这种使用方式, 因为这样做会污染当前的命名空间, 导致无意中覆盖现有名称, 而且会降低代码的可读性, 当使用了多条from ... import *  语句之后, 无法判断使用的对象来自于哪个模块.

2.3 导入别名  import  as

有些时候导入的模块在本模块已经存在同名文件, 为了避免被覆盖, 可以使用别名将导入重新命名.

In [1]: import json

In [2]: def json(s):
   ...:     print(s)

In [3]: json.dumps([1,2])
---------------------------------------------------------------------------
AttributeError: 'function' object has no attribute 'dumps'

如上例代码, json被本地函数覆盖, 调用json模块的dumps函数时报错.

将模块名重命名为js, 避免了名称与本地名称冲突

In [4]: import json as js

In [5]: js.dumps([1,2])
Out[5]: '[1, 2]'

另一个场景是, 导入的模块名称较长, 为了后续使用方便将其简写 

In [1]: import matplotlib as plt
In [2]: from pandas import dataframe as df

2.4 导入模块搜索路径

当解释器执行 import 语句时,  会尝试从一个路径的列表进行搜索.  列表中的路径有3个来源

  1. 当前运行python脚本的目录
  2. PYTHONPATH环境变量中包含的目录列表
  3. 在安装 Python 时配置的依赖于安装的目录列表

生成的搜索路径可在 Python 变量中访问,  可通过sys.path来查看

>>> import sys
>>> sys.path
['', 'C:\\Python39\\python39.zip', 'C:\\Python39\\DLLs', 'C:\\Python39\\lib',
'C:\\Python39', 
'C:\\Python39\\lib\\site-packages', 
'C:\\Python39\\lib\\site-packages\\win32', 
'C:\\Python39\\lib\\site-packages\\win32\\lib', 
'C:\\Python39\\lib\\site-packages\\Pythonwin']

2.5 相对导入 

使用之前的例子, 一个如下图结构的package包.  在 module 中需要使用subpackage.module1中的对象

 

尝试在 module 中 导入module2

import sys

for p in sys.path:
    print(p)

from package import module2
> python module.py
C:\Users\Desktop\package\subpackage
C:\Python39\python39.zip
C:\Python39\DLLs
C:\Python39\lib
...
ModuleNotFoundError: No module named 'package'

从打印的 sys.path 可以看到,  模块搜索路径在子目录subpackage下, 所以找不到package模块. 

2个解决方法, 

2.5.1 手动添加目录到 sys.path

将之前的代码, 增加一行 sys.path.insert(0, "C:\\Users\\Desktop")
, 手动将 package 所在目录 添加到 sys.path. 

import sys

sys.path.insert(0, "C:\\Users\\Desktop")

for p in sys.path:
    print(p)
from package import module2

​​​​​​​再次执行, 发现可以import 成功

> python module.py
C:\Users\Desktop
C:\Users\Desktop\package\subpackage
C:\Python39\python39.zip
C:\Python39\DLLs
C:\Python39\lib
...
right

2.5.2 ☹️​​​​​​​使用相对导入

todo

不建议使用相对导入

总结

本文解释了模块和包的概念, 

导入模块和包时, import 的常用使用方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#连接Oracle数据库可以使用Oracle Data Provider for .NET(ODP.NET)来实现。ODP.NET是Oracle官方提供的用于与Oracle数据库进行交互的.NET数据访问组件。 以下是连接Oracle数据库的基本步骤: 1. 首先,确保你的计算机上已经安装了Oracle客户端软件。你可以从Oracle官方网站下载并安装适合你操作系统的客户端软件。 2. 在C#项目中,添加对Oracle.DataAccess.dll的引用。这个DLL文件是ODP.NET的核心组件,它包含了与Oracle数据库交互所需的类和方法。 3. 在代码中,使用`using`关键字引入`Oracle.DataAccess.Client`命名空间。 4. 创建一个`OracleConnection`对象,并设置连接字符串。连接字符串包含了连接Oracle数据库所需的信息,如服务器地址、用户名、密码等。 ```csharp string connectionString = "Data Source=your_server_address;User Id=your_username;Password=your_password;"; OracleConnection connection = new OracleConnection(connectionString); ``` 5. 打开数据库连接。 ```csharp connection.Open(); ``` 6. 执行SQL语句或存储过程。可以使用`OracleCommand`对象来执行SQL语句,并通过`ExecuteReader`方法获取查询结果。 ```csharp string sql = "SELECT * FROM your_table"; OracleCommand command = new OracleCommand(sql, connection); OracleDataReader reader = command.ExecuteReader(); while (reader.Read()) { // 处理查询结果 } reader.Close(); ``` 7. 关闭数据库连接。 ```csharp connection.Close(); ``` 这是一个简单的连接Oracle数据库的示例,你可以根据自己的需求进行扩展和修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值