写在前面
写本系列的目的(自用)是回顾已经学过的知识、记录新学习的知识或是记录心得理解,方便自己以后快速复习,减少遗忘。python之前学过但学得不牢,尤其是列表、元组、字典、面向对象编程部分及python一些库的使用,因此基础部分只是简单罗列语法,快速复习一下。遇到其他问题再额外补充。Python是函数多且杂,在学习阶段并不需要知道所有函数,只需要熟悉python的语法,在未来碰到特定函数时查询即可。
Part 1 基础知识
该部分主要通过python3菜鸟教程来进行复习,记录笔记。
三、条件控制
python的条件控制语句很简单,和C++区别不大。
1、if语句
if语句的关键字是if-elif-else,每个条件都要使用冒号:,基本语法是:
if condition_1:
statement_1
elif condition_2:
statement_2
else:
statement_3
elif和else可以没有。以下是一个简单的实例:
var = 20
if var < 0:
print("var是负数")
elif var == 0:
print("var是0")
else:
print("var是正数")
if语句同样可以嵌套,将if...elif...else 结构放在另外一个 if...elif...else 结构中
score = 90
if score >= 80:
if score >= 90:
print("A")
else:
print("B")
else:
print("C")
2、match...case
python中没有switch...case,但在python3中添加了match...case。下面是示例
status = 404
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
其中,case _:类似于C++中的default,当其他 case 都无法匹配时,匹配这条,保证永远会匹配成功。也不需要break。另外,一个case也可以设置多个匹配条件,用 | 隔开。
case 401|403|404:
return "Not allowed"
四、循环语句
1、while循环
while循环的一般语句为:
while 判断条件(condition):
执行语句(statements)……
同样需要注意冒号和缩进,并且在python中没有do while语句,下面为求1到100的和的示例:
n = 100
sum = 0
counter = 1
while counter <= n:
sum += counter
counter+=1
2、for循环
Python for 循环可以遍历任何可迭代对象,如一个列表或者一个字符串。和C++的STL迭代器比较像。一般格式为:
for <variable> in <sequence>:
<statements>
else:
<statements>
下面为for循环的实例:
sites = ["Baidu", "Google", "Runoob", "Taobao"]
for site in sites:
print(site)
除了遍历列表,也可以遍历字符串:
word = 'Baidu'
for letter in word:
print(letter)
除此之外,还可以配合range()函数使用,这里先介绍一下range()函数。range()函数是一个内置函数,用于生成不可变的整数序列,通常在for循环中控制迭代次数。
range()函数有三种调用方式:
1、range(stop):生成从0开始到stop-1的整数序列。
2、range(start, stop):生成从start开始到stop-1的整数序列。
3、range(start, stop, step):生成从start开始,step为步长,到stop-1的整数序列。类似于切片输出。
配合python的for循环可以这样使用,打印输出1~5的数字:
for number in range(1, 6):
print(number)
3、for...else
for...else语句用于在循环结束后执行一段代码:
for x in range(6):
print(x)
else:
print("Finished!")
这段代码在输出0~6后会再输出Finished!
4、break和continue
在循环中使用break会直接跳出循环,而使用continue会直接进入下一层循环。下面看一个示例:
n = 5
while n > 0:
n -= 1
if n == 2:
break
print(n)
'''这段代码的输出是
4
3
之后就因为break跳出循环了
'''
n = 5
while n > 0:
n -= 1
if n == 2:
continue
print(n)
'''这段代码的输出是
4
3
1
0
因为continue跳过了输出n = 2的代码,直接进入了下一轮循环
'''
5、pass语句
pass语句是空语句,为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句,比如,你需要定义一个函数、类或者条件分支,但暂时不想编写具体实现时,可以用pass占位:
def my_function():
pass # 函数体为空,不执行任何操作
class MyClass:
pass # 类定义为空
if x > 10:
pass # 占位,后续再添加逻辑
在python中,代码块(如函数、类、循环)必须包含至少一条语句,若为空就会导致语法错误,使用pass就可以避免这个问题。
五、函数
1、定义并调用一个函数
函数代码块以def开头,后接函数标识符名称及()。函数内容以冒号:起始,并且缩进。return表示结束函数,选择性地返回一个值给调用方,不带return表示返回None
def hello():
print("hello world!")
hello()
也可以更复杂点
def max(a, b)
if a > b:
return a
else:
return b
a = 4
b = 5
c = 1
print(max(a, b))
print(max(b, c))
2、参数传递
在python中,变量是没有类型的:
a = [1, 2, 3]
a = "hello"
[1, 2, 3]是list类型,hello是String类型,而a其实没有类型。它仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
不可变类型:类似C++的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
(1)python传不可变对象
def change(a):
print(id(a))
a = 10
print(id(a))
a = 1
print(id(a))
change(a)
'''输出是
4379369136
4379369136
4379369424
'''
形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的 id。
(2)python传可变对象
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:
def change(mylist):
mylist.append([1,2,3])
print(mylist)
return
mylist = [4,5,6]
change(mylist)
print(mylist)
'''输出为
[4, 5, 6, [1, 2, 3]]
[4, 5, 6, [1, 2, 3]]
'''
3、参数
在调用函数时可以有4种参数类型:必须参数,关键字参数,默认参数,不定长参数。
(1)必须参数
函数定义中必须提供的参数,调用时必须按顺序传入对应的值,否则会引发类型错误。
def add(a, b): # a 和 b 是必需参数
return a + b
add(3, 5) # 正确:提供两个参数
# add(3) # 错误:缺少参数 b,TypeError
(2)关键字参数
调用函数时通过参数名=值的形式传递的参数,可打破参数的位置顺序,提高代码可读性
def person_info(name, age):
print(f"Name: {name}, Age: {age}")
# 使用关键字参数调用
person_info(age=30, name="Alice") # 正确:顺序可调整
person_info(name="Bob", age=25) # 等价写法
(3)默认参数
调用函数时,如果设置了默认参数且没有传递参数,则会使用默认参数。
def printinfo(name , age = 30)
print("名字:", name)
print("年龄:", age)
printinfo("Alice") #没有传入年龄,使用默认参数30
printinfo("Bob", 20) #传入了年龄,使用20
(4)不定长参数
不定长参数允许函数接收任意数量的参数,无需在定义时明确指定参数的个数。Python 支持两种不定长参数:位置不定长参数(*args)和 关键字不定长参数(**kwargs)。
先来看位置不定长参数,通过在参数名前加*定义,接收任意数量的位置参数,并将它们封装为一个元组。
def function(*args):
for arg in args:
print(arg)
function(1, 2, 3) # 输出: 1 2 3
function('a', 'b', 'c', 'd') # 输出: a b c d
再来看关键字不定长参数,通过在参数名前加**定义,接收任意数量的关键字参数,并将它们封装为一个字典。
def function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
function(name="Alice", age=30) # 输出: name: Alice, age: 30
function(city="New York", country="USA", population=8.4)
# 输出: city: New York,country:USA,population:8.4
4、匿名函数
匿名函数也称lambda函数,是一种无需显式定义名称的小型、一次性函数。基本语法如下:
lambda arguments: expression
其中,arguments是参数列表,expression为单一表达式,其结果为函数返回值。例如,以下是一个简单的匿名函数:
add = lambda x, y : x+y
print(add(3, 5))
匿名函数无需命名,可以直接作为参数传递,例如应用到map()函数上。map()函数是一个内置函数,用于将一个函数应用到可迭代对象的每个元素上。基本语法是map(function, iterable)
下面来看一个例子:
numbers = [1, 2, 3]
squares = list(map(lambda x: x**2, numbers))
'''这里,匿名函数是lambda x : x**2
map()函数的作用是将每个元素都作用到函数上,这里的元素列表是numbers,也就是将每个number传入匿名函数
list()的作用是将得到的数据转换为列表'''
print(squares) # 输出: [1, 4, 9]
除了map()外,还有filter()和reduce()都能很方便地配合匿名函数使用
filter():根据函数的返回值筛选元素,返回满足条件的元素组成的迭代器。例如:
# 筛选偶数
numbers = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 输出: [2, 4]
reduce():将函数应用于可迭代对象的前两个元素,然后将结果与下一个元素继续计算,直到完成所有元素的累积。例如:
Part 2
一、Python推导式
Python 推导式是一种独特的数据处理方式,可以从一个数据序列构建另一个新的数据序列的结构体。适用于生成列表、字典、集合和生成器。
1、列表推导式
列表推导式的核心结构为:
[expression for item in iterable]
其中,expression是对每个元素的操作或转换,item是从可迭代对象中取出的元素,iterable是被遍历的可迭代元素。例如,生成0到4的平方列表:
squares = [x**2 for x in range(5)]
print(squares) #输出[0,1,4,9,16]
从这里就能理解expression了,这里我们选择的是对原列表中小于4的数取平方并组成新列表。除此之外,还可以添加条件过滤,如下:
[expression for item in iterable if condition]
先直接看一个示例:
names = ['Bob','Tom','alice','Jerry','Wendy','Smith']
new_names = [name.upper() for name in names if len(name)>3]
print(new_names)
'''结果是
['ALICE', 'JERRY', 'WENDY', 'SMITH']
'''
这里的expression是name.upper(),将每个元素的字母大写。条件是len(name)>3,也就是名字长度大于3个字符。那么新列表就是,在原列表中,长度大于三的大写名字组成的新列表。
2、字典推导式
字典推导式的核心结构为:
{key_expression: value_expression for item in iterable}
其中key_expression是生成字典键的表达式,value_expressions是生成字典值的表达式。item是从可迭代对象中取出的元素,iterable是被遍历的可迭代对象。下面是一个简单的示例:
listdemo = ['Google','Runoob', 'Taobao']
newdict = {key:len(key) for key in listdemo}
print(newdict)
'''结果
{'Google': 6, 'Runoob': 6, 'Taobao': 6}
'''
可以看出,listdemo是key_expression,也就是新列表的键值来自于listdemo,value_expressions是len(key)。除此之外,还可以添加条件过滤,如下:
{key_expression: value_expression for item in iterable if condition}
numbers = [1,2,3,4,5]
new = {x : x**2 for x in numbers if x%2 == 0}
print(new)
'''输出
{2:4, 4:16}
'''
最后,还有一个应用场景,交换字典的键和值:
original = {'a':1, 'b':2}
new = {value : key for key, value in original}
print(new)
3、集合推导式
集合推导式的核心结构是:
{expression for item in iterable}
下面看一个示例,生成数字的平方集合(注意集合会自动去重):
square = {x**2 for x in [1, 2, 2, 3]}
print(square)
'''结果是
{1, 4, 9}
'''
也可以添加条件过滤:
{expression for item in iterable if condition}
示例如下,生成偶数的平方集合:
numbers = [1, 2, 3, 4, 5, 6]
new = {x**2 for x in numbers if x%2 == 0}
print(new)
'''结果是,注意集合元素无序
{16, 4, 36}
'''
4、元组推导式
没有直接的元组推导式,元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型,快速生成一个满足指定需求的元组。如果不加转换为元组,就会成为生成器(生成器见下)。
tuple_result = tuple(x**2 for x in range(5)) # 直接转换为元组
print(tuple_result) # 输出: (0, 1, 4, 9, 16)
二、迭代器与生成器
1、迭代器
迭代是 Python 最强大的功能之一,是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。需要注意的是,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
(1)迭代器的创建与使用
迭代器的两个基本方法是:iter()和next()
其中,iter()是创建迭代器,next(it)会返回迭代器当前指向的元素,并将迭代器移动到下一个位置,类似后置++。
my_list = [1, 2, 3]
it = iter(my_list) # 创建迭代器
print(next(it)) # 输出: 1
print(next(it)) # 输出: 2
print(next(it)) # 输出: 3
# print(next(it)) # 报错: StopIteration
迭代器对象也可以通过常规for语句进行遍历:
list = [1, 2, 3, 4]
it = iter(list)
for x in it:
print(x, end = " ")
'''输出
1 2 3 4
'''
(2)自定义迭代器类
可以通过实现__iter__() 和 __next__()方法创建自定义迭代器。如果有了解过面向对象编程,就会知道,和C++相同,Python也有构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候执行。这里先放上自定义迭代器的代码,可以在学习面向对象的时候回顾。
class Counter:
def __init__(self, max_num): # 有参构造函数,起到初始化的作用,这里设置迭代器最大值,初始值
self.max = max_num # 最大值由用户传入
self.current = 0 #初始值为0
def __iter__(self):
return self # 返回迭代器自身
def __next__(self):
if self.current < self.max:
value = self.current
self.current += 1
return value
else:
raise StopIteration # 迭代结束
# 使用自定义迭代器
counter = Counter(3) # 迭代器的最大值设置为3
for num in counter:
print(num) # 输出: 0 1 2
其中,StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
2、生成器
生成器是一种特殊的迭代器,它允许你以更简洁的方式创建迭代器。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。使用了yield的函数被称为生成器。
(1)生成器函数
生成器函数是通过yield关键字定义的函数,每次调用next()时会暂停并保存当前状态,下次调用时从暂停处继续执行,见以下示例:
def fibonacci(): #相当于创建了一个迭代器,迭代器的数字遵从斐波那契数列
a, b = 0, 1
while True:
yield a # 这句代码暂停并返回当前值
a, b = b, a + b # 下次调用从这里继续
# 使用生成器
fib = fibonacci()
print(next(fib)) # 输出: 0
print(next(fib)) # 输出: 1
print(next(fib)) # 输出: 1
#也可以通过for循环访问
for value in fib:
print(value)
(2)生成器表达式
生成器表达式类似于列表推导式,但是使用圆括号,返回一个生成器对象。基本语法如下:
gen = (expression for item in iterable if condition)
示例如下:
squares = (x**2 for x int range(5)) #生成器中包含0 1 4 9 16
print(next(squares)) # 输出 0
print(next(squares)) # 输出 1