Python核心丨模块化

本文介绍了Python中的模块化,包括简单模块化、项目模块化的概念和实现方式。讲解了如何组织文件结构,使用相对和绝对路径,以及在Python2和Python3中关于_init_.py的不同。还探讨了在大型项目中如何导入模块,并解释了if _name_ == '_main_'的作用,以确保模块既可以作为独立程序运行,又能在被导入时避免不必要的代码执行。
摘要由CSDN通过智能技术生成

模块化


简单模块化

最简单的模块化方式,是把函数、类、常量拆分到不同的文件,把它们放在同一个文件夹,然后使用from your_file import funcion_name,class_name的方式调用

# utils.py

def get_sum(a, b):
    return a + b
# class_utils.py

class Encoder(object):
    def encode(self, s):
        return s[::-1]

class Decoder(object):
    def decode(self, s):
        return ''.join(reversed(list(s)))
# main.py

from utils import get_sum
from class_utils import *

print(get_sum(1, 2))

encoder = Encoder()
decoder = Decoder()

print(encoder.encode('abcde'))
print(decoder.decode('edcba'))

########## 输出 ##########

3
edcba
abcde

get_sum()函数定义在utils.py

Encoder和Decoder类则在class_utils.py

在main函数直接调用from import,就可以将需要的东西import过来

当文件多了之后,就需要建一些子文件夹

# utils/utils.py

def get_sum(a, b):
    return a + b
# utils/class_utils.py

class Encoder(object):
    def encode(self, s):
        return s[::-1]

class Decoder(object):
    def decode(self, s):
        return ''.join(reversed(list(s)))
# src/sub_main.py

import sys
sys.path.append("..")

from utils.class_utils import *

encoder = Encoder()
decoder = Decoder()

print(encoder.encode('abcde'))
print(decoder.decode('edcba'))

########## 输出 ##########

edcba
abcde

文件结构

.
├── utils
│   ├── utils.py
│   └── class_utils.py
├── src
│   └── sub_main.py
└── main.py

main.py调用子目录的模块时,只需要使用.代替/来表示子目录,utils.utils表示utils自文件下的utils.py模块。

sys.path.appden(’…’)表示将当前程序所在位置向上提了一级。

版本区别:

Python2规范中,需要在文件夹下新键一个_init_.py,内容可以为空。

Python3规范中,_init_.py并不是必须的。

项目模块化

相对路径和绝对路径的概念

Linux系统中,每个文件都有一个绝对路径,以 / 开头,来表示从根目录到叶子节点的路径。

例:/home/ubuntu/Desktop/test.py,这种表示方法叫做绝对路径。

对于任意两个文件,都有一条通路可以从一个文件走到另一个文件。

例:/home/ubuntu/Downloads/example.json。从test.py访问到example.json,需要写成../Downloads/example.json,其中..表示上一层目录。这种表示方法叫做相对路径。

Python文件在运行的时候,都会有一个运行时位置,最开始时即为这个文件所在的文件夹。这个路径是可以被改变的。

大型工程中尽可能使用绝对位置

实例

项目结构

.
├── proto
│   ├── mat.py
├── utils
│   └── mat_mul.py
└── src
    └── main.py
# proto/mat.py

class Matrix(object):
    def __init__(self, data):
        self.data = data
        self.n = len(data)
        self.m = len(data[0])
# utils/mat_mul.py

from proto.mat import Matrix

def mat_mul(matrix_1: Matrix, matrix_2: Matrix):
    assert matrix_1.m == matrix_2.n
    n, m, s = matrix_1.n, matrix_1.m, matrix_2.m
    result = [[0 for _ in range(n)] for _ in range(s)]
    for i in range(n):
        for j in range(s):
            for k in range(m):
                result[i][k] += matrix_1.data[i][j] * matrix_2.data[j][k]

    return Matrix(result)
# src/main.py

from proto.mat import Matrix
from utils.mat_mul import mat_mul


a = Matrix([[1, 2], [3, 4]])
b = Matrix([[5, 6], [7, 8]])

print(mat_mul(a, b).data)

########## 输出 ##########

[[19, 22], [43, 50]]

使用from proto.mat 的方式import Matrix。这种是直接从项目根目录中导入,并依次向下导入模块mat.py中的Matrix。

Python解释器在遇到import的时候,会在一个特定的列表中寻找模块。

特定的列表拿取方式

import sys  

print(sys.path)

########## 输出 ##########

['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages']

它的第一项为空,就是将第一项设置为项目根目录的绝对地址。这样,无论怎么运行main.py,import函数在执行的时候,都会去项目根目录中找相应的包。

if _name_ == ‘_main_’

项目结构

.
├── utils.py
├── utils_with_main.py
├── main.py
└── main_2.py
# utils.py

def get_sum(a, b):
    return a + b

print('testing')
print('{} + {} = {}'.format(1, 2, get_sum(1, 2)))
# utils_with_main.py

def get_sum(a, b):
    return a + b

if __name__ == '__main__':
    print('testing')
    print('{} + {} = {}'.format(1, 2, get_sum(1, 2)))
# main.py

from utils import get_sum

print('get_sum: ', get_sum(1, 2))

########## 输出 ##########

testing
1 + 2 = 3
get_sum: 3
# main_2.py

from utils_with_main import get_sum

print('get_sum: ', get_sum(1, 2))

########## 输出 ##########

get_sum_2: 3

import在导入文件的时候,会自动把所有暴露在外边的代码全都执行一遍。因此,如果要把一个东西封装成模块,又想让它可以执行的话,必须将要执行的代码放在if _name_ == '_main_'下面

其实__name__作为Python的魔术内置参数,本质上是模块对象的一个属性,当使用import语句时,__name__就会被赋值为该模块的名字,自然就不等于__main__了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值