大一下 软工计算1实验(国产版CS61A)笔记 20240407
(参考自https://www.cnblogs.com/lcyfrog/p/17020967.html#cs61a%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-week1)
1.多重赋值语句
在Python语言中,a1, a2 = b1, b2 是一种多重赋值语句,它允许你在一行代码中同时为多个变量赋值。这种赋值是同时发生的,也就是说,b1 和 b2 的值在赋值给 a1 和 a2 之前就已经被确定了。
这里的关键是理解赋值操作的顺序性。赋值语句 a1, a2 = b1, b2 并不会先计算 b2 然后将它的值赋给 a1,再计算 b1 然后将它的值赋给 a2。实际上,b1 和 b2 的计算是并行的,它们的值被同时确定,然后分别赋给 a1 和 a2。
这意味着,如果 b1 和 b2 本身依赖于某些可能会改变的值或者它们之间有依赖关系,这些依赖关系在赋值操作发生时就已经固定下来了。
例如:
定义两个列表
list1 = [1, 2]
list2 = [3, 4]
多重赋值
a1, a2 = list1[0], list2[1]
print(a1) 输出: 1
print(a2) 输出: 4
在这个例子中,我们有两个列表 list1 和 list2。我们使用多重赋值语句将 list1 的第一个元素赋给 a1,将 list2 的第二个元素赋给 a2。这个操作是同时发生的,不会影响 list1 和 list2 中的元素。
即使 list1 和 list2 在这个赋值操作之后发生了变化,a1 和 a2 存储的值也不会改变,因为它们的值在赋值时就已经确定。
这种多重赋值的语法在Python中非常常见,它可以使代码更加简洁和易读。然而,使用时需要注意,确保理解了变量之间的依赖关系,以及赋值操作的并行性。
2.exp
在Python中,exp 函数通常指的是计算数学中的指数函数,即e(自然对数的底数)的幂。这个函数在math模块中可用,需要先导入math模块才能使用。
下面是如何使用math.exp的示例:
import math
计算e的x次幂
x = 1.0
result = math.exp(x) # 计算e^x,当x=1时,结果为e
print(result) # 输出结果
在这个例子中,我们首先导入了math模块,然后定义了一个变量x并赋值为1.0。接着,我们使用math.exp函数计算e的x次幂,并将结果存储在变量result中。最后,我们打印出结果。
3.**
在Python中,**是一个特殊的运算符,主要用于两种情况:幂运算和参数解包。
**作为幂运算符: **可以用于计算一个数的幂。例如,2 ** 3将会计算2的3次方,结果是8。
幂运算示例
result = 2 ** 3 # 结果为8
print(result)
4.python中的数据抽象
数据抽象是编程中的一个核心概念,它指的是隐藏对象的实现细节,只暴露出一个清晰的接口和行为给使用者。在Python中,数据抽象通常通过类和对象来实现,允许开发者定义自定义类型和与这些类型相关的方法,同时隐藏内部的实现逻辑。
数据抽象的主要目的是提高代码的可读性、可维护性和可复用性。通过数据抽象,开发者可以将复杂的问题分解成更小、更易于管理的部分,并且可以确保这些部分的实现细节不会干扰到其他部分。
以下是一个简单的数据抽象示例,我们定义一个表示矩形的类,并提供计算面积的方法,而不暴露矩形长和宽的具体实现细节:
class Rectangle:
def init(self, length, width):
self._length = length # 私有属性,表示矩形的长度
self._width = width # 私有属性,表示矩形的宽度
def area(self):
"""计算并返回矩形的面积"""
return self._length * self._width
def set_length(self, length):
"""设置矩形的长度"""
self._length = length
def set_width(self, width):
"""设置矩形的宽度"""
self._width = width
使用Rectangle类创建一个矩形对象
rect = Rectangle(5, 3)
计算并打印矩形的面积,不需要知道面积是如何计算的
print("The area of the rectangle is:", rect.area()) # 输出: The area of the rectangle is: 15
修改矩形的尺寸,并通过接口与内部实现交互
rect.set_length(10)
rect.set_width(5)
print("The new area of the rectangle is:", rect.area()) # 输出: The new area of the rectangle is: 50
在这个例子中,Rectangle类封装了矩形的长和宽,并提供了area、set_length和set_width方法来与矩形交互。使用者可以通过这些方法来获取矩形的面积或修改其尺寸,而不需要了解矩形是如何在内部存储这些信息的。
通过这种方式,数据抽象允许我们创建模块化和可重用的代码,同时也使得代码更加安全,因为私有属性不能被外部代码直接访问,从而防止了潜在的错误和不一致性。
PS:为啥 类 Rectangle中的init要有self参数?
在Python中,类的__init__方法是一个特殊的方法,它在创建类的新实例时被自动调用。self参数是__init__方法的第一个参数,它是一个对当前对象实例的引用。
当你创建一个类的新对象时,Python会自动将新创建的对象作为第一个参数传递给__init__方法,这个参数就是self。这样,你就可以在__init__方法内部访问和设置对象的属性或执行其他初始化操作。
在Rectangle类的例子中,self参数允许我们在构造函数中引用对象自身,以便设置或获取属性。例如:
class Rectangle:
def __init__(self, length, width):
self._length = length # 设置对象的_length属性
self._width = width # 设置对象的_width属性
这里,self._length和self._width是对象的私有属性,通过使用self,我们将这些属性绑定到了对象上。当我们创建Rectangle类的实例时,每个实例都会有自己的_length和_width属性,这些属性可以通过self来访问和修改。
如果没有self参数,Python就不知道如何将对象自身传递给__init__方法,也就无法正确地初始化对象。self参数是约定俗成的,你可以使用其他名称代替它,但遵循self的命名约定可以使你的代码更容易被其他Python开发者理解和维护。
PPS:为啥要有init函数?
在Python中,__init__函数是一个特殊方法,也称为构造器。它在创建类的新实例时自动被调用,用于初始化对象的状态。对于计算矩形面积的类来说,__init__函数用于设置矩形的初始尺寸和可能的其他属性,这样在使用对象之前,它就已经准备好了所需的所有信息。
例如,假设我们有一个名为Rectangle的类,用于表示矩形并计算其面积,__init__函数可能会像这样:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
在这个例子中,__init__函数接受三个参数:self,length和width。self是对象本身的引用,而length和width是矩形的尺寸。函数内部,我们将这些值赋给了对象的属性,这样它们就可以在类的其他方法中使用。
当我们创建Rectangle类的新实例时,我们传递长度和宽度作为参数:
rect = Rectangle(10, 5)
这时,__init__函数被调用,创建了一个具有长度为10和宽度为5的矩形对象。之后,我们可以调用area方法来计算矩形的面积:
print(rect.area()) # 输出: 50
__init__函数是类的重要组成部分,因为它定义了对象在开始时应具有的状态。如果没有__init__函数,我们就无法在对象创建时设置其属性,这将限制对象的功能和可用性。通过使用__init__函数,我们可以确保对象在创建时就具有正确的初始状态,从而可以执行其设计好的功能。
5.python中的 嵌套列表中的元素迭代
在Python中,嵌套列表是指一个列表中包含其他列表作为元素的情况。迭代嵌套列表通常涉及到使用多层循环,即外部循环遍历外层列表的元素,而内部循环遍历内层列表的元素。下面是一个例子,说明如何迭代嵌套列表中的所有元素:
# 假设我们有一个嵌套列表,表示一个课程的学生名单
courses = [
["Alice", "Bob", "Charlie"],
["David", "Eve"],
["Frank", "Grace", "Helen", "Ivan"]
]
# 使用外部循环遍历每个课程的学生名单
for students in courses:
# 使用内部循环遍历每个学生的名字
for student in students:
print(student)
# 输出:
# Alice
# Bob
# Charlie
# David
# Eve
# Frank
# Grace
# Helen
# Ivan
在这个例子中,courses是一个包含三个子列表的嵌套列表,每个子列表代表一个课程的学生名单。我们使用一个for循环来遍历外层列表(即每个课程的名单),然后在每个课程的循环内部,我们使用另一个for循环来遍历学生的名字。
这种嵌套循环的方法允许我们逐个访问嵌套列表中的所有元素。每次外部循环迭代时,我们获取一个新的学生名单列表,然后内部循环遍历这个列表中的每个学生。
除了使用嵌套循环,你还可以使用迭代和序列解包来简化嵌套列表的迭代过程:
# 使用嵌套的for循环和序列解包来迭代每个学生的名字
for course, students in enumerate(courses):
print(f"Course {course + 1}:")
for student in students:
print(f" - {student}")
# 输出:
# Course 1:
# - Alice
# - Bob
# - Charlie
# Course 2:
# - David
# - Eve
# Course 3:
# - Frank
# - Grace
# - Helen
# - Ivan
在这个例子中,我们使用enumerate函数来获取每个课程的索引和学生名单。然后我们使用两个for循环,第一个循环遍历课程,第二个循环遍历每个课程中的学生名单。我们还使用序列解包来分别获取学生的名字,并在打印时添加了一些格式化信息。
这些例子展示了如何在Python中迭代嵌套列表中的元素,无论是使用嵌套循环还是结合enumerate和序列解包,都可以有效地访问和处理嵌套列表中的数据。
6.python中range的语法
range() 是 Python 中的一个内置函数,它生成一个不可变的数字序列。range() 函数非常常用,尤其是在循环中作为迭代器使用。以下是 range() 函数的基本语法:
range(start, stop[, step])
start(可选): 序列的起始值,默认值为0。stop: 序列的结束值,但不包括这个值。step(可选): 序列中每个数字之间的步长,默认值为1。
下面是一些使用 range() 函数的例子:
-
默认参数(从
0开始,步长为1):for i in range(5): # 生成序列:0, 1, 2, 3, 4 print(i) -
指定
start和stop:for i in range(2, 6): # 生成序列:2, 3, 4, 5 print(i) -
指定
start、stop和step:for i in range(0, 10, 2): # 生成序列:0, 2, 4, 6, 8 print(i) -
负数步长(递减序列):
for i in range(5, -1, -1): # 生成序列:5, 4, 3, 2, 1,0 print(i)
需要注意的是,range() 生成的序列是一个惰性序列,也就是说,它不会立即生成所有的值,而是在需要时才生成每个值。这使得 range() 非常适合用于生成大范围的数字序列,因为它不会占用大量内存。
此外,如果你需要一个实际的列表而不是惰性序列,可以使用 list() 函数将 range() 的结果转换成列表:
numbers = list(range(5)) # 将生成的序列转换为列表 [0, 1, 2, 3, 4]
range() 函数是 Python 编程中的基础工具之一,掌握它的使用对于编写高效的循环结构至关重要。
7.python中的序列解包
在Python中,序列解包(Sequence Unpacking)是一种在多个变量赋值时自动从序列(如列表、元组)中提取值的机制。这种特性允许我们在一个表达式中同时获取序列中的多个元素,并将它们分别赋值给多个变量。
序列解包通常用在函数返回多个值、从列表或元组中提取数据、以及在迭代时解包多个元素的场景中。下面是一个使用序列解包的例子:
# 假设我们有一个列表,包含一个点的x和y坐标
coordinates = [10, 20]
# 使用序列解包将列表中的值分别赋给两个变量
x, y = coordinates
print(x) # 输出: 10
print(y) # 输出: 20
在这个例子中,我们有一个名为coordinates的列表,它包含两个元素。通过使用x, y = coordinates这样的语法,我们将列表中的元素分别赋值给了变量x和y。这个过程就是序列解包的一个例子。
序列解包也可以用于更复杂的数据结构,例如从嵌套列表中解包数据:
# 假设我们有一个嵌套列表,表示矩阵
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# 使用序列解包同时获取矩阵的行
row1, row2, row3 = matrix
print(row1) # 输出: [1, 2, 3]
print(row2) # 输出: [4, 5, 6]
print(row3) # 输出: [7, 8, 9]
在这个例子中,我们使用序列解包来同时获取矩阵的每一行,并将其分别存储在row1、row2和row3变量中。
序列解包还可以与迭代结合使用,例如在for循环中解包多个元素:
# 假设我们有一个包含多个坐标点的列表
points = [(1, 2), (3, 4), (5, 6)]
# 使用for循环和序列解包来迭代每个点的坐标
for x, y in points:
print(f"Point at ({x}, {y})")
# 输出:
# Point at (1, 2)
# Point at (3, 4)
# Point at (5, 6)
在这个例子中,我们使用for循环遍历了一个包含坐标点的列表。每次迭代时,我们使用序列解包将元组中的值分别赋给变量x和y,然后打印出来。
序列解包是Python中一个非常有用的功能,它使得代码更加简洁和易于阅读。通过这种方式,我们可以轻松地从序列中提取数据,并将其分配给多个变量。
8.python中数学的直接运用(类似于集合)
eg:
代码
odds=[1,3,5]
a=[x+1 for x in odds]
print(a)
输出[2,4,6]
9.python中的闭包
闭包(Closure)是Python中的一个高级概念,它指的是一个函数能够记住并访问其创建时的作用域中的变量,即使这个函数在其原始作用域之外被调用。闭包通常在定义函数的时候形成,当一个嵌套的内部函数引用了外部函数的局部变量时,就形成了闭包。
闭包的关键特性是它可以捕获外部函数作用域中的变量,即使外部函数已经执行完毕。这使得闭包非常适合用于创建带有“记住状态”的函数,或者在函数式编程中实现高阶函数。
以下是一个简单的闭包示例:
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
# 创建一个闭包
closure = outer_function(10)
# 调用闭包,即使outer_function已经执行完毕
print(closure(5)) # 输出: 15
在这个例子中,outer_function是一个接受参数x的函数,它定义了一个内部函数inner_function。inner_function接受参数y并返回x + y的结果。outer_function返回inner_function的引用,而不是直接执行它。
当我们调用outer_function(10)时,x被设置为10,并且inner_function被创建,它记住了x的值。然后我们将inner_function赋值给变量closure,这个变量现在持有闭包的引用。
即使outer_function已经执行完毕,我们仍然可以通过调用closure(5)来使用闭包。在这个调用中,inner_function访问了它被创建时的x的值(即10),并将其与传入的参数5相加,返回结果15。
闭包在Python中有许多用途,包括但不限于实现装饰器、延迟计算、函数工厂以及封装状态等。通过使用闭包,你可以编写出更加简洁、高效和灵活的代码。
10.python中的字典
在Python中,字典(Dictionary)是一种内置的数据结构,它存储了键值对(key-value pairs)。字典中的键是唯一的,而值则可以重复。字典提供了快速的查找、添加、删除和修改操作。以下是一个使用字典的例子,以及对字典常见操作的解释:
# 创建一个空字典
person = {}
# 添加键值对
person["name"] = "Alice"
person["age"] = 25
person["email"] = "alice@example.com"
# 访问字典中的值
print(person["name"]) # 输出: Alice
print(person.get("age")) # 输出: 25,使用get方法,因为age可能不存在
print(person["email"]) # 输出: alice@example.com
# 修改字典中的值
person["age"] = 26
# 删除字典中的键值对
del person["email"]
# 检查键是否存在
if "name" in person:
print(f"The person's name is {person['name']}")
# 遍历字典中的键和值
for key, value in person.items():
print(f"{key}: {value}")
# 使用字典推导式创建新字典
even_ages = {person[key]: person[key] for key in person if isinstance(person[key], int)}
print(even_ages) # 输出: {"age": 26}
在这个例子中,我们首先创建了一个名为person的空字典。然后,我们使用键来添加一些信息,如姓名、年龄和电子邮件地址。我们可以使用键来访问和修改字典中的值。如果使用[]操作符访问不存在的键,Python将抛出KeyError异常,而使用get方法则可以返回None或者指定的默认值,而不会抛出异常。
我们还展示了如何删除字典中的键值对,以及如何检查一个键是否存在于字典中。此外,我们使用items()方法遍历字典中的所有键和值。
最后,我们使用字典推导式创建了一个新的字典even_ages,它只包含person字典中值为整数的键值对。
字典是Python中非常强大和灵活的数据结构,它在日常编程中被广泛使用,无论是用于存储配置信息、缓存数据还是作为其他数据结构的基础。
11.nonlocal
在Python中,nonlocal 关键字用于在嵌套函数中修改外部函数的局部变量。当在一个嵌套函数中需要修改外部函数的局部变量时,通常会使用 nonlocal 关键字。
考虑下面的示例代码:
python
def outer():
x = 10
def inner():
nonlocal x
x += 1
print("Inner x:", x)
inner()
print("Outer x:", x)
outer()
在这个例子中,inner 函数嵌套在 outer 函数内部,并且试图修改 outer 函数内的变量 x。在 inner 函数中,通过使用 nonlocal 关键字声明 x,可以告诉 Python 解释器 x 是外部函数 outer 中的局部变量,而不是在 inner 函数中创建的新变量。因此,当 inner 函数修改 x 的值时,它实际上修改的是 outer 函数中的 x。在这个例子中,输出将是:
Inner x: 11
Outer x: 11
如果没有在 inner 函数中使用 nonlocal x,那么 inner 函数将会创建一个新的局部变量 x,而不会修改 outer 函数中的 x,并且输出将会是:
Inner x: 11
Outer x: 10
因此,nonlocal 关键字允许我们在嵌套函数中修改外部函数的局部变量,而不是创建一个新的同名局部变量。

浙公网安备 33010602011771号