最简单的模块化方式,你可以把函数、类、常量拆分到不同的文件,把它们放在同一个文 件夹,然后使用 from your_file import function_name, class_name 的方式调 用。之后,这些函数和类就可以在文件内直接使用了。
1 # utils.py
2
3 def get_sum(a, b):
4 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)))
1 # main.py 2
3 from utils import get_sum
4 from class_utils import *
5
6 print(get_sum(1, 2)) 7
8 encoder = Encoder()
9 decoder = Decoder()
10
11 print(encoder.encode('abcde'))
12 print(decoder.decode('edcba'))
13
14 ########## 输出 ########## 15
16 3
17 edcba
18 abcde
看看上面的示例代码,get_sum() 函数定义在 utils.py,Encoder 和 Decoder 类则在 class_utils.py,我们在 main 函数直接调用 from import ,就可以将我们需要的东西 import 过来。
但是这样就行了吗,不,慢慢的你会发现所有的文件都堆在一个文件夹下面也不是办法
然后就必须创建一些子文件夹
1 # utils/utils.py
2
3 def get_sum(a, b):
4 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)))
1 # src/sub_main.py 2
3 import sys
4 sys.path.append("..")
5
6 from utils.class_utils import * 7
8 encoder = Encoder()
9 decoder = Decoder()
而这一次,我们的文件结构是下面这样的:
1.
2 ├── utils
3 │ ├── utils.py
4 │ └── class_utils.py 5 ├── src
6 │ └── sub_main.py
7 └── main.py
很容易看出,main.py 调用子目录的模块时,只需要使用 . 代替 / 来表示子目录,utils.utils 表示 utils 子文件夹下的 utils.py 模块就行。
那如果我们想调用上层目录呢?注意,sys.path.append(“…”) 表示将当前程序所在位置 向上提了一级,之后就能调用 utils 的模块了。
核心就是 以项目的根目录作为最基本的目录,所有的模块调用,都要通过根目录 一层层向下索引的方式来 import
明白了这一点后,这次我们使用 PyCharm 来创建一个项目。这个项目结构如下所示:
2 ├── proto
3 │ ├── mat.py
├── utils
5 │ └── mat_mul.py
6 └── src
7 └── 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)
1 # src/main.py 2
3 from proto.mat import Matrix
4 from utils.mat_mul import mat_mul
5 6
7 a = Matrix([[1, 2], [3, 4]])
8 b = Matrix([[5, 6], [7, 8]])
9
10 print(mat_mul(a, b).data)
请注意 utils/mat_mul.py,你会发现,它 import Matrix 的方式是from proto.mat。这种做法,直接从项目根目录中导入,并依次向下导入 模块 mat.py 中的 Matrix,而不是使用 … 导入上一级文件夹。
是不是很简单呢?对于接下来的所有项目,你都能直接使用 Pycharm 来构建。把不同模块放 在不同子文件夹里,跨模块调用则是从顶层直接索引,一步到位,非常方便。
在Python中,if __name__ == '__main__'
是一个常见的代码块,用于确定当前模块是作为主程序运行还是作为导入模块使用。
当一个Python脚本文件被直接执行时,Python解释器会将该脚本文件的__name__
属性设置为'__main__'
,这是Python中的内置属性。如果一个模块是作为主程序运行,那么__name__
属性的值就是'__main__'
。
因此,当你使用 if __name__ == '__main__'
来判断时,它实际上检查的是当前模块是否是作为主程序执行的。如果是主程序执行,该条件语句块中的代码将被执行;如果是作为导入模块使用,该条件语句块中的代码将被跳过。
这个机制通常用于模块的测试和调试。通过将一些测试代码放在if __name__ == '__main__'
块中,你可以在模块被导入时避免这些测试代码被执行,只有在直接运行该模块时才会执行这些测试代码。
在 Python 中,浅拷贝(shallow copy)和深拷贝(deep copy)是用于创建对象副本的两种不同方式。
浅拷贝是指创建一个新对象,该对象的内容是原始对象中元素的引用。换句话说,浅拷贝创建了一个新的对象,但该对象中的元素仍然与原始对象共享。修改原始对象中的元素也会反映在浅拷贝对象中。在 Python 中,可以使用 copy
模块的 copy()
函数或者对象的 copy()
方法进行浅拷贝。
示例代码:
pythonCopy code
import copy
list1 = [1, 2, 3, [4, 5]]
list2 = copy.copy(list1)
# 修改原始对象
list1[3].append(6)
print(list1) # 输出: [1, 2, 3, [4, 5, 6]]
print(list2) # 输出: [1, 2, 3, [4, 5, 6]]
深拷贝是指创建一个新对象,该对象及其内容都是原始对象的完全独立副本。换句话说,深拷贝创建了一个与原始对象完全无关的新对象。修改原始对象中的元素不会影响深拷贝对象。在 Python 中,可以使用 copy
模块的 deepcopy()
函数或者对象的 deepcopy()
方法进行深拷贝。
示例代码:
pythonCopy code
import copy
list1 = [1, 2, 3, [4, 5]]
list2 = copy.deepcopy(list1)
# 修改原始对象
list1[3].append(6)
print(list1) # 输出: [1, 2, 3, [4, 5, 6]]
print(list2) # 输出: [1, 2, 3, [4, 5]]
浅拷贝只复制了对象的引用,而深拷贝创建了一个完全独立的对象副本。选择使用浅拷贝还是深拷贝取决于你的需求和数据结构的复杂性。
在 Python 中,参数传递方式既不是纯粹的值传递(pass by value)也不是纯粹的引用传递(pass by reference),而是通过对象的引用进行传递,通常称为对象的传递(pass by object)。
当你将一个对象作为参数传递给函数或赋值给另一个变量时,实际上是将该对象的引用传递给了函数或变量。这意味着函数或变量可以通过引用访问和修改原始对象。
值传递是指将对象的副本传递给函数或变量,函数或变量对副本的修改不会影响原始对象。对于不可变对象(例如数字、字符串和元组),参数传递是值传递的。这是因为不可变对象无法修改,每次传递时都会创建一个新的对象副本。
示例代码:
pythonCopy code
def update_value(num):
num += 1
print(num)
value = 10
update_value(value)
print(value) # 输出: 10
引用传递是指将对象的引用传递给函数或变量,函数或变量可以通过引用修改原始对象。对于可变对象(例如列表、字典和集合),参数传递是引用传递的。
示例代码:
pythonCopy code
def update_list(lst):
lst.append(4)
print(lst)
my_list = [1, 2, 3]
update_list(my_list)
print(my_list) # 输出: [1, 2, 3, 4]
需要注意的是,虽然对于可变对象来说是引用传递,但如果在函数内部重新分配对象或修改引用,不会影响原始对象或变量。
示例代码:
pythonCopy code
def update_list(lst):
lst = [4, 5, 6] # 在函数内部重新分配对象
print(lst)
my_list = [1, 2, 3]
update_list(my_list)
print(my_list) # 输出: [1, 2, 3]
综上所述,Python 中的参数传递是通过对象的引用进行的,对于不可变对象是值传递,对于可变对象是引用传递。这种特性使得在函数中修改可变对象成为可能,但需要注意对象重新分配和引用修改的影响