python语法
2024-07-27 16:46:36 2 举报
AI智能生成
python,python入门、python语言、python面试、人工智能面试、算法面试、大模型面试基础
作者其他创作
大纲/内容
背景
是解释型语言还是编译型语言?
Python 是一种 解释型 语言,但它也包含编译的步骤。这种特性通常被称为 解释型/编译型混合 或 半编译型。
解释型语言的特点
逐行执行:解释型语言在执行时,解释器会逐行读取代码,将其转换为机器码(或某种中间表示形式),然后执行。这意味着代码的执行是实时的,不需要事先编译成独立的可执行文件。
易于调试:由于代码是逐行执行的,因此错误可以立即被捕获和调试。
跨平台:解释型语言通常更容易在不同操作系统上运行,因为解释器会处理底层系统的差异。
Python 的执行过程
Python 的执行过程虽然包含了解释的步骤,但它也使用了编译的概念。具体来说:
编译:当你运行 Python 程序时,Python 解释器首先会读取源代码(.py 文件),并将其编译成字节码(.pyc 文件,如果启用了字节码缓存)。这个字节码不是特定于任何平台的机器码,而是一种中间表示形式,由 Python 虚拟机(PyVM)执行。
解释:Python 虚拟机(PyVM)读取字节码,并将其转换成机器码(或直接在解释器中执行,取决于实现),然后执行。这个过程是逐条指令进行的,类似于传统解释型语言的执行方式。
为什么说 Python 是解释型语言
虽然 Python 使用了编译步骤来生成字节码,但这个步骤主要是为了提高执行效率,减少重复编译相同代码的需要。从用户的角度来看,Python 程序仍然是以解释的方式执行的,即逐行读取和执行,无需事先编译成可执行文件。因此,Python 通常被归类为解释型语言。
总结
Python 是一种解释型语言,它通过编译源代码到字节码来提高执行效率,但最终的执行仍然是通过解释器逐行进行的。这种混合型的执行方式使得 Python 既具有解释型语言的灵活性和易调试性,又能在一定程度上提高执行效率。
解释型语言的特点
逐行执行:解释型语言在执行时,解释器会逐行读取代码,将其转换为机器码(或某种中间表示形式),然后执行。这意味着代码的执行是实时的,不需要事先编译成独立的可执行文件。
易于调试:由于代码是逐行执行的,因此错误可以立即被捕获和调试。
跨平台:解释型语言通常更容易在不同操作系统上运行,因为解释器会处理底层系统的差异。
Python 的执行过程
Python 的执行过程虽然包含了解释的步骤,但它也使用了编译的概念。具体来说:
编译:当你运行 Python 程序时,Python 解释器首先会读取源代码(.py 文件),并将其编译成字节码(.pyc 文件,如果启用了字节码缓存)。这个字节码不是特定于任何平台的机器码,而是一种中间表示形式,由 Python 虚拟机(PyVM)执行。
解释:Python 虚拟机(PyVM)读取字节码,并将其转换成机器码(或直接在解释器中执行,取决于实现),然后执行。这个过程是逐条指令进行的,类似于传统解释型语言的执行方式。
为什么说 Python 是解释型语言
虽然 Python 使用了编译步骤来生成字节码,但这个步骤主要是为了提高执行效率,减少重复编译相同代码的需要。从用户的角度来看,Python 程序仍然是以解释的方式执行的,即逐行读取和执行,无需事先编译成可执行文件。因此,Python 通常被归类为解释型语言。
总结
Python 是一种解释型语言,它通过编译源代码到字节码来提高执行效率,但最终的执行仍然是通过解释器逐行进行的。这种混合型的执行方式使得 Python 既具有解释型语言的灵活性和易调试性,又能在一定程度上提高执行效率。
独特之处:是一种使用空格缩进语法的语言
Python使用缩进来定义代码块,而不是括号。标准的Python缩进是4个空格,尽管制表符和任何其他空格大小都可以工作,只要它是一致的。请注意,代码块不需要任何终止。
基础语法
类型
集合 Set
是什么
集合是没有重复条目的列表
声明
a = set(["Jake", "John", "Eric"])
print(a)
b = set(["John", "Jill"])
print(b)
print(a)
b = set(["John", "Jill"])
print(b)
操作
交 intersection
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.intersection(b)) // {'John'}
print(b.intersection(a)) // {'John'}
print(a & b) // {'John'}
print(b & a) // {'John'}
b = set(["John", "Jill"])
print(a.intersection(b)) // {'John'}
print(b.intersection(a)) // {'John'}
print(a & b) // {'John'}
print(b & a) // {'John'}
并: S1.union(S2)、 S1 | S2
子主题
当然,并集(Union)是集合论中的一个基本操作,它涉及到两个或多个集合。对于S1和S2两个集合,它们的并集是指包含S1和S2中所有元素(去除重复元素)的集合。记作S1 ∪ S2。
并集的定义
设S1和S2是两个集合,则S1与S2的并集S1 ∪ S2是由所有属于S1或属于S2(或两者都属于)的元素所组成的集合。换句话说,如果x是S1或S2(或两者都是)的元素,那么x就是S1 ∪ S2的元素。
示例
假设S1 = {1, 2, 3}且S2 = {3, 4, 5},则S1 ∪ S2 = {1, 2, 3, 4, 5}。注意,即使元素3同时出现在S1和S2中,它在并集中也只被列出一次。
性质
交换律:S1 ∪ S2 = S2 ∪ S1。即并集运算满足交换性。
结合律:对于任意集合S1、S2和S3,(S1 ∪ S2) ∪ S3 = S1 ∪ (S2 ∪ S3)。即并集运算满足结合性。
空集:对于任意集合S,S ∪ ∅ = S,其中∅表示空集。即任何集合与空集的并集都是该集合本身。
幂集与并集:对于任意集合S,其幂集P(S)中任意两个集合的并集仍然属于P(S)(但不一定是P(S)中的新元素,因为可能存在交集)。
在编程中的应用
在大多数编程语言中,集合(或类似集合的数据结构,如列表、数组、集合类型等)都支持并集操作。例如,在Python中,可以使用集合(set)类型来实现并集操作:
python
复制代码
S1 = {1, 2, 3}
S2 = {3, 4, 5}
S1_union_S2 = S1.union(S2)
# 或者简单地使用 | 运算符:S1 | S2
print(S1_union_S2) # 输出: {1, 2, 3, 4, 5}
或者使用 | 运算符来更简洁地表示并集操作:
python
复制代码
S1_union_S2 = S1 | S2
print(S1_union_S2) # 输出: {1, 2, 3, 4, 5}
并集的定义
设S1和S2是两个集合,则S1与S2的并集S1 ∪ S2是由所有属于S1或属于S2(或两者都属于)的元素所组成的集合。换句话说,如果x是S1或S2(或两者都是)的元素,那么x就是S1 ∪ S2的元素。
示例
假设S1 = {1, 2, 3}且S2 = {3, 4, 5},则S1 ∪ S2 = {1, 2, 3, 4, 5}。注意,即使元素3同时出现在S1和S2中,它在并集中也只被列出一次。
性质
交换律:S1 ∪ S2 = S2 ∪ S1。即并集运算满足交换性。
结合律:对于任意集合S1、S2和S3,(S1 ∪ S2) ∪ S3 = S1 ∪ (S2 ∪ S3)。即并集运算满足结合性。
空集:对于任意集合S,S ∪ ∅ = S,其中∅表示空集。即任何集合与空集的并集都是该集合本身。
幂集与并集:对于任意集合S,其幂集P(S)中任意两个集合的并集仍然属于P(S)(但不一定是P(S)中的新元素,因为可能存在交集)。
在编程中的应用
在大多数编程语言中,集合(或类似集合的数据结构,如列表、数组、集合类型等)都支持并集操作。例如,在Python中,可以使用集合(set)类型来实现并集操作:
python
复制代码
S1 = {1, 2, 3}
S2 = {3, 4, 5}
S1_union_S2 = S1.union(S2)
# 或者简单地使用 | 运算符:S1 | S2
print(S1_union_S2) # 输出: {1, 2, 3, 4, 5}
或者使用 | 运算符来更简洁地表示并集操作:
python
复制代码
S1_union_S2 = S1 | S2
print(S1_union_S2) # 输出: {1, 2, 3, 4, 5}
差 difference
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.difference(b))
print(b.difference(a))
b = set(["John", "Jill"])
print(a.difference(b))
print(b.difference(a))
对称差 symmetric difference
a = set(["Jake", "John", "Eric"])
b = set(["John", "Jill"])
print(a.symmetric_difference(b))
print(b.symmetric_difference(a))
b = set(["John", "Jill"])
print(a.symmetric_difference(b))
print(b.symmetric_difference(a))
子集、超集
详解
python 中集合的操作方法有哪些
在Python中,集合(Set)是一个无序的、不包含重复元素的数据结构。集合提供了丰富的操作方法,以下是一些主要的集合操作方法:
1. 创建集合
使用大括号{}(注意:空集合必须使用set()而不是{},因为{}用于创建空字典)。
使用set()函数。
2. 添加元素
add(element): 向集合中添加一个元素。
update(iterable): 向集合中添加来自另一个可迭代对象(如列表、元组、集合等)的元素。
3. 删除元素
remove(element): 从集合中移除一个元素。如果元素不存在,则抛出KeyError异常。
discard(element): 从集合中移除一个元素。如果元素不存在,则不抛出异常。
pop(): 随机移除集合中的一个元素并返回它。如果集合为空,则抛出KeyError异常(在某些Python版本中,对于空集合调用pop()将抛出KeyError,但在其他版本中可能会返回特定的错误消息或行为)。
clear(): 移除集合中的所有元素。
4. 集合运算
并集:
union(other): 返回两个集合的并集。
| 运算符:也可以使用|运算符来获取两个集合的并集。
交集:
intersection(other): 返回两个集合的交集。
& 运算符:也可以使用&运算符来获取两个集合的交集。
差集:
difference(other): 返回集合的差集,即存在于当前集合但不在另一个集合中的元素。
- 运算符:也可以使用-运算符来获取差集。
对称差集:
symmetric_difference(other): 返回两个集合的对称差集,即存在于一个集合中但不在另一个集合中的元素。
^ 运算符:也可以使用^运算符来获取对称差集。
5. 判断关系
issubset(other): 判断当前集合是否是另一个集合的子集。
issuperset(other): 判断当前集合是否是另一个集合的超集。
isdisjoint(other): 判断两个集合是否没有交集。
6. 其他操作
copy(): 返回集合的一个浅拷贝。
len(set): 返回集合中元素的数量。
in 关键字:用于判断某个元素是否存在于集合中。
示例代码
python
复制代码
# 创建集合
s1 = {1, 2, 3}
s2 = {3, 4, 5}
# 添加元素
s1.add(6)
s1.update([7, 8])
# 删除元素
s1.remove(2) # 如果2不存在,则抛出KeyError
s1.discard(9) # 如果9不存在,则不抛出异常
# 集合运算
print(s1.union(s2)) # {1, 2, 3, 4, 5, 6, 7, 8}
print(s1 & s2) # {3}
print(s1 - s2) # {1, 6, 7, 8}
print(s1 ^ s2) # {1, 4, 5, 6, 7, 8}
# 判断关系
print(s1.issubset(s1.union(s2))) # True
print(s1.isdisjoint({9, 10})) # True
# 其他操作
print(len(s1)) # 集合中元素的数量
print(3 in s1) # True
以上是在Python中集合的一些基本操作方法的概述和示例代码。集合是Python中非常有用的数据结构,特别适用于需要快速成员资格测试和消除重复项的场景。
1. 创建集合
使用大括号{}(注意:空集合必须使用set()而不是{},因为{}用于创建空字典)。
使用set()函数。
2. 添加元素
add(element): 向集合中添加一个元素。
update(iterable): 向集合中添加来自另一个可迭代对象(如列表、元组、集合等)的元素。
3. 删除元素
remove(element): 从集合中移除一个元素。如果元素不存在,则抛出KeyError异常。
discard(element): 从集合中移除一个元素。如果元素不存在,则不抛出异常。
pop(): 随机移除集合中的一个元素并返回它。如果集合为空,则抛出KeyError异常(在某些Python版本中,对于空集合调用pop()将抛出KeyError,但在其他版本中可能会返回特定的错误消息或行为)。
clear(): 移除集合中的所有元素。
4. 集合运算
并集:
union(other): 返回两个集合的并集。
| 运算符:也可以使用|运算符来获取两个集合的并集。
交集:
intersection(other): 返回两个集合的交集。
& 运算符:也可以使用&运算符来获取两个集合的交集。
差集:
difference(other): 返回集合的差集,即存在于当前集合但不在另一个集合中的元素。
- 运算符:也可以使用-运算符来获取差集。
对称差集:
symmetric_difference(other): 返回两个集合的对称差集,即存在于一个集合中但不在另一个集合中的元素。
^ 运算符:也可以使用^运算符来获取对称差集。
5. 判断关系
issubset(other): 判断当前集合是否是另一个集合的子集。
issuperset(other): 判断当前集合是否是另一个集合的超集。
isdisjoint(other): 判断两个集合是否没有交集。
6. 其他操作
copy(): 返回集合的一个浅拷贝。
len(set): 返回集合中元素的数量。
in 关键字:用于判断某个元素是否存在于集合中。
示例代码
python
复制代码
# 创建集合
s1 = {1, 2, 3}
s2 = {3, 4, 5}
# 添加元素
s1.add(6)
s1.update([7, 8])
# 删除元素
s1.remove(2) # 如果2不存在,则抛出KeyError
s1.discard(9) # 如果9不存在,则不抛出异常
# 集合运算
print(s1.union(s2)) # {1, 2, 3, 4, 5, 6, 7, 8}
print(s1 & s2) # {3}
print(s1 - s2) # {1, 6, 7, 8}
print(s1 ^ s2) # {1, 4, 5, 6, 7, 8}
# 判断关系
print(s1.issubset(s1.union(s2))) # True
print(s1.isdisjoint({9, 10})) # True
# 其他操作
print(len(s1)) # 集合中元素的数量
print(3 in s1) # True
以上是在Python中集合的一些基本操作方法的概述和示例代码。集合是Python中非常有用的数据结构,特别适用于需要快速成员资格测试和消除重复项的场景。
集合有哪些操作,比如S1 和 S2 两个集合
对于S1和S2两个集合,除了交集和并集之外,还有多种集合操作。以下是一些主要的集合操作:
1. 差集(Difference)
差集是指从集合S1中去除所有属于集合S2的元素后剩余的集合。记作S1 - S2。例如,如果S1 = {1, 2, 3, 4}且S2 = {3, 4, 5},则S1 - S2 = {1, 2}。
2. 对称差集(Symmetric Difference)
对称差集是S1和S2的差集的并集,但不包含它们的交集。即S1与S2的对称差集是所有在S1中但不在S2中,或在S2中但不在S1中的元素组成的集合。记作S1 Δ S2或S1 ^ S2(在某些编程语言中)。继续上面的例子,S1 Δ S2 = {1, 2} ∪ {5} = {1, 2, 5}。
3. 子集与超集
子集(Subset):如果S1的每一个元素都是S2的元素,则称S1是S2的子集。记作S1 ⊆ S2。
超集(Superset):如果S2包含S1的所有元素,则称S2是S1的超集。记作S2 ⊇ S1。注意,任何集合都是它自身的子集和超集。
4. 补集(Complement)
补集的概念依赖于一个特定的全集U。S1在全集U中的补集是U中所有不属于S1的元素组成的集合。记作C_U(S1)或~S1(在某些上下文中)。注意,补集的定义依赖于全集U的选取。
5. 幂集(Power Set)
幂集是指一个集合的所有子集(包括空集和自身)组成的集合。例如,如果S1 = {1, 2},则S1的幂集为{{}, {1}, {2}, {1, 2}}。
6. 笛卡尔积(Cartesian Product)
虽然笛卡尔积不是直接作用于两个集合的元素之间,但它是一种集合运算,其结果是一个新的集合。给定两个集合S1和S2,它们的笛卡尔积S1 × S2是所有可能的有序对(a, b)的集合,其中a属于S1且b属于S2。例如,如果S1 = {1, 2}且S2 = {a, b},则S1 × S2 = {(1, a), (1, b), (2, a), (2, b)}。
7. 集合的运算更新
交集更新(Intersection Update):更新集合S1,使其只包含S1和S2的交集元素。
差集更新(Difference Update):从集合S1中移除所有在S2中的元素。
对称差更新(Symmetric Difference Update):更新集合S1,使其包含S1和S2的对称差集元素。
这些集合操作在数学、计算机科学、统计学、经济学等多个学科领域都有广泛的应用。
8、并集
包含了S1和S2所有元素的集合 S1US2
1. 差集(Difference)
差集是指从集合S1中去除所有属于集合S2的元素后剩余的集合。记作S1 - S2。例如,如果S1 = {1, 2, 3, 4}且S2 = {3, 4, 5},则S1 - S2 = {1, 2}。
2. 对称差集(Symmetric Difference)
对称差集是S1和S2的差集的并集,但不包含它们的交集。即S1与S2的对称差集是所有在S1中但不在S2中,或在S2中但不在S1中的元素组成的集合。记作S1 Δ S2或S1 ^ S2(在某些编程语言中)。继续上面的例子,S1 Δ S2 = {1, 2} ∪ {5} = {1, 2, 5}。
3. 子集与超集
子集(Subset):如果S1的每一个元素都是S2的元素,则称S1是S2的子集。记作S1 ⊆ S2。
超集(Superset):如果S2包含S1的所有元素,则称S2是S1的超集。记作S2 ⊇ S1。注意,任何集合都是它自身的子集和超集。
4. 补集(Complement)
补集的概念依赖于一个特定的全集U。S1在全集U中的补集是U中所有不属于S1的元素组成的集合。记作C_U(S1)或~S1(在某些上下文中)。注意,补集的定义依赖于全集U的选取。
5. 幂集(Power Set)
幂集是指一个集合的所有子集(包括空集和自身)组成的集合。例如,如果S1 = {1, 2},则S1的幂集为{{}, {1}, {2}, {1, 2}}。
6. 笛卡尔积(Cartesian Product)
虽然笛卡尔积不是直接作用于两个集合的元素之间,但它是一种集合运算,其结果是一个新的集合。给定两个集合S1和S2,它们的笛卡尔积S1 × S2是所有可能的有序对(a, b)的集合,其中a属于S1且b属于S2。例如,如果S1 = {1, 2}且S2 = {a, b},则S1 × S2 = {(1, a), (1, b), (2, a), (2, b)}。
7. 集合的运算更新
交集更新(Intersection Update):更新集合S1,使其只包含S1和S2的交集元素。
差集更新(Difference Update):从集合S1中移除所有在S2中的元素。
对称差更新(Symmetric Difference Update):更新集合S1,使其包含S1和S2的对称差集元素。
这些集合操作在数学、计算机科学、统计学、经济学等多个学科领域都有广泛的应用。
8、并集
包含了S1和S2所有元素的集合 S1US2
数字
支持整数(整数)和浮点数(小数)两种
整数 int
定义一个整数
myint = 7
print(myint)
print(myint)
浮点 float
定义浮点数
myfloat = 7.0
print(myfloat)
myfloat = float(7)
print(myfloat)
print(myfloat)
myfloat = float(7)
print(myfloat)
特性
可以在数字上执行简单的操作符
字符串
字符串可以用单引号或双引号定义。
优缺点
字符串可以用单引号或双引号定义。
使用双引号可以很容易地包含撇号 (而如果使用单引号,这些将终止字符串)。
扩展
包含回车
包含反斜杠
包含Unicode字符
特性
可以在字符串上执行简单的操作符
one = 1
two = 2
three = one + two
print(three)
hello = "hello"
world = "world"
helloworld = hello + " " + world
print(helloworld) //hello world
two = 2
three = one + two
print(three)
hello = "hello"
world = "world"
helloworld = hello + " " + world
print(helloworld) //hello world
操作
字符串格式化
一个变量:%单个变量
# This prints out "Hello, John!"
name = "John"
print("Hello, %s!" % name)
name = "John"
print("Hello, %s!" % name)
多个变量:使用元组 %(变量1,变量2)
# This prints out "John is 23 years old."
name = "John"
age = 23
print("%s is %d years old." % (name, age))
name = "John"
age = 23
print("%s is %d years old." % (name, age))
“%”操作符用于格式化包含在“元组”(固定大小的列表)中的一组变量,以及一个格式字符串,该字符串包含普通文本以及“参数说明符”,特殊符号如“%s”和“%d”。
各类型占位符
数字
整数
%d
浮点数
%f、%.2f、%.3f、等等
%.<number of digits>f -圆点右边有固定位数的浮点数。
字符串
%s
字符串(或任何字符串表示的对象,如数字)
对象
%s
任何非字符串的对象也可以使用%s操作符进行格式化。从该对象的“repr”方法返回的字符串被格式化为字符串。例如:
十六进制表示的整数(小写/大写)
%x/% x
声明
astring = "Hello world!"
astring2 = 'Hello world!'
astring2 = 'Hello world!'
打印
astring = "Hello world!"
print("single quotes are ' '")//single quotes are ' '
print("single quotes are ' '")//single quotes are ' '
取长度
astring = "Hello world!"
print(len(astring))//12
print(len(astring))//12
输出结果为12,因为“Hello world!”有12个字符长,包括标点和空格。
取字符下标
astring = "Hello world!"
print(astring.index("o"))//4
print(astring.index("o"))//4
识别到第一个就返回。这将输出4,因为字母“o”第一次出现的位置距离第一个字符有4个字符。注意这个短语中实际上有两个o——这个方法只识别第一个o。
获得字符出现的次数
astring = "Hello world!"
print(astring.count("l"))//3
print(astring.count("l"))//3
截取子字符串[[start:stop):step]
astring = "Hello world!"
print(astring[3:7])//"lo w" [3,7)
print(astring[3:7])//"lo w" [3,7)
步长截取
astring = "Hello world!"
print(astring[3:7:2])//"l "
print(astring[3:7:2])//"l "
astring = "Hello world!"
print(astring[3:7])//"lo w"
等价于
print(astring[3:7:1])//"lo w"
print(astring[3:7])//"lo w"
等价于
print(astring[3:7:1])//"lo w"
反转字符串
astring = "Hello world!"
print(astring[::-1])// !dlrow olleH
print(astring[::-1])// !dlrow olleH
大小写
astring = "Hello world!"
print(astring.upper())//HELLO WORLD!
print(astring.lower())//hello world!
print(astring.upper())//HELLO WORLD!
print(astring.lower())//hello world!
确定字符串是否以某一字符串开始或以某一字符串结束
astring = "Hello world!"
print(astring.startswith("Hello"))//True
print(astring.endswith("asdfasdfasdf"))// False
print(astring.startswith("Hello"))//True
print(astring.endswith("asdfasdfasdf"))// False
字符串分割成列表
astring = "Hello world!"
afewwords = astring.split(" ")//[Hello, world!]
afewwords = astring.split(" ")//[Hello, world!]
不支持
不支持数字和字符串之间的混合操作符
字典
是什么
字典是一种类似于数组的数据类型,但使用的是键和值,而不是索引。存储在字典中的每个值都可以使用键来访问,键是任何类型的对象(字符串、数字、列表等),而不是使用索引来寻址。
声明
phonebook = {
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
print(phonebook)
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
print(phonebook)
phonebook = {}
phonebook["John"] = 938477566
phonebook["Jack"] = 938377264
phonebook["Jill"] = 947662781
print(phonebook)
phonebook["John"] = 938477566
phonebook["Jack"] = 938377264
phonebook["Jill"] = 947662781
print(phonebook)
遍历字典
phonebook = {"John" : 938477566,"Jack" : 938377264,"Jill" : 947662781}
for name, number in phonebook.items():
print("Phone number of %s is %d" % (name, number))
for name, number in phonebook.items():
print("Phone number of %s is %d" % (name, number))
删除元素
phonebook = {
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
phonebook.pop("John")
print(phonebook)
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
phonebook.pop("John")
print(phonebook)
phonebook = {
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
del phonebook["John"]
print(phonebook)
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
del phonebook["John"]
print(phonebook)
列表 List
长度:list.count()
特性
它们可以包含任何类型的变量,并且可以包含任意多的变量。
定义
mylist = []
mylist.append(1)
mylist.append(2)
mylist.append(3)
print(mylist[0]) # prints 1
print(mylist[1]) # prints 2
print(mylist[2]) # prints 3
# prints out 1,2,3
for x in mylist:
print(x)
mylist.append(1)
mylist.append(2)
mylist.append(3)
print(mylist[0]) # prints 1
print(mylist[1]) # prints 2
print(mylist[2]) # prints 3
# prints out 1,2,3
for x in mylist:
print(x)
操作
添加元素
删除元素
遍历元素
读取元素
异常
访问不存在的索引会产生异常(错误)。:IndexError: list index out of range
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
print(mylist[10])
IndexError: list index out of range
File "<stdin>", line 2, in <module>
print(mylist[10])
IndexError: list index out of range
数组
是什么
Numpy数组是Python列表的绝佳替代品。Numpy数组的一些关键优点是它们快速、易于使用,并且使用户有机会跨整个数组执行计算。
操作
导入numpy包并从新创建的列表中创建numpy数组。
# Create 2 new lists height and weight
height = [1.87, 1.87, 1.82, 1.91, 1.90, 1.85]
weight = [81.65, 97.52, 95.25, 92.98, 86.18, 88.45]
# Import the numpy package as np
import numpy as np
# Create 2 numpy arrays from height and weight
np_height = np.array(height)
np_weight = np.array(weight)
height = [1.87, 1.87, 1.82, 1.91, 1.90, 1.85]
weight = [81.65, 97.52, 95.25, 92.98, 86.18, 88.45]
# Import the numpy package as np
import numpy as np
# Create 2 numpy arrays from height and weight
np_height = np.array(height)
np_weight = np.array(weight)
# Create 2 new lists height and weight
height = [1.87, 1.87, 1.82, 1.91, 1.90, 1.85]
weight = [81.65, 97.52, 95.25, 92.98, 86.18, 88.45]
# Import the numpy package as np
import numpy as np
# Create 2 numpy arrays from height and weight
np_height = np.array(height)
np_weight = np.array(weight)
print(type(np_height))#<class 'numpy.ndarray'>
# Calculate bmi
bmi = np_weight / np_height ** 2
#Subsetting
# For a boolean response
print(bmi > 28)# [False False True False False False]
# Print only those observations above 26
print(bmi[bmi > 26]) #[ 27.88755755 28.75558507]
# Print the result
print(bmi) # [ 23.34925219 27.88755755 28.75558507 25.48723993 23.87257618 25.84368152]
height = [1.87, 1.87, 1.82, 1.91, 1.90, 1.85]
weight = [81.65, 97.52, 95.25, 92.98, 86.18, 88.45]
# Import the numpy package as np
import numpy as np
# Create 2 numpy arrays from height and weight
np_height = np.array(height)
np_weight = np.array(weight)
print(type(np_height))#<class 'numpy.ndarray'>
# Calculate bmi
bmi = np_weight / np_height ** 2
#Subsetting
# For a boolean response
print(bmi > 28)# [False False True False False False]
# Print only those observations above 26
print(bmi[bmi > 26]) #[ 27.88755755 28.75558507]
# Print the result
print(bmi) # [ 23.34925219 27.88755755 28.75558507 25.48723993 23.87257618 25.84368152]
数组与列表的区别,以及各自的优缺点
在Python中,"数组"一词通常不会直接指向Python内建的一个特定类型,因为Python标准库中并没有直接称为“数组”的类型,而是有列表(List)和NumPy库中的数组(Array)等数据结构。因此,当我们讨论Python中的“数组”时,我们往往是在指NumPy库中的ndarray对象,这是为了与Python的内置列表(List)进行对比。
Python 列表(List)
定义:
Python的列表是一个内置的数据结构,用于存储元素的有序集合。列表是可变的,即你可以添加、删除或修改列表中的元素。
优点:
灵活性:列表可以存储不同类型的元素(异质性)。
内置支持:Python标准库直接支持列表,无需额外安装。
动态大小:列表的大小可以根据需要自动调整。
缺点:
性能:对于大规模数值计算,列表的操作(如迭代、索引等)可能不如NumPy数组高效。
内存使用:由于列表的灵活性,它在存储数据时可能需要更多的内存。
NumPy 数组(Array)
定义:
NumPy是Python的一个库,它提供了高性能的多维数组对象(ndarray)以及用于操作这些数组的工具。NumPy数组是同质性的,即数组中的所有元素必须具有相同的数据类型。
优点:
性能:NumPy数组是为大规模数值计算优化的,因此它们比Python列表在执行数值计算时更快。
内存效率:NumPy数组在内存中存储数据的方式使得它们比列表更紧凑。
支持广播:NumPy数组支持广播,这是一种强大的机制,允许NumPy在执行算术运算时自动扩展较小数组的形状以匹配较大数组。
大量数学和科学函数:NumPy提供了大量的数学和科学计算函数,可以直接在数组上操作。
缺点:
依赖外部库:要使用NumPy数组,你需要先安装NumPy库。
同质性:数组中的所有元素必须具有相同的数据类型,这限制了其灵活性。
总结
选择使用列表还是NumPy数组取决于你的具体需求。如果你正在处理的是小型数据集或需要存储不同类型的元素,那么列表可能是更好的选择。然而,如果你正在进行大规模数值计算或需要高性能的数组操作,那么NumPy数组将是更好的选择。
Python 列表(List)
定义:
Python的列表是一个内置的数据结构,用于存储元素的有序集合。列表是可变的,即你可以添加、删除或修改列表中的元素。
优点:
灵活性:列表可以存储不同类型的元素(异质性)。
内置支持:Python标准库直接支持列表,无需额外安装。
动态大小:列表的大小可以根据需要自动调整。
缺点:
性能:对于大规模数值计算,列表的操作(如迭代、索引等)可能不如NumPy数组高效。
内存使用:由于列表的灵活性,它在存储数据时可能需要更多的内存。
NumPy 数组(Array)
定义:
NumPy是Python的一个库,它提供了高性能的多维数组对象(ndarray)以及用于操作这些数组的工具。NumPy数组是同质性的,即数组中的所有元素必须具有相同的数据类型。
优点:
性能:NumPy数组是为大规模数值计算优化的,因此它们比Python列表在执行数值计算时更快。
内存效率:NumPy数组在内存中存储数据的方式使得它们比列表更紧凑。
支持广播:NumPy数组支持广播,这是一种强大的机制,允许NumPy在执行算术运算时自动扩展较小数组的形状以匹配较大数组。
大量数学和科学函数:NumPy提供了大量的数学和科学计算函数,可以直接在数组上操作。
缺点:
依赖外部库:要使用NumPy数组,你需要先安装NumPy库。
同质性:数组中的所有元素必须具有相同的数据类型,这限制了其灵活性。
总结
选择使用列表还是NumPy数组取决于你的具体需求。如果你正在处理的是小型数据集或需要存储不同类型的元素,那么列表可能是更好的选择。然而,如果你正在进行大规模数值计算或需要高性能的数组操作,那么NumPy数组将是更好的选择。
变量
Python是完全面向对象的,而不是“静态类型”的。在使用变量之前不需要声明它们,也不需要声明它们的类型。Python中的每个变量都是一个对象。
特性
同一行“同时”对多个变量进行赋值
a, b = 3, 4
print(a, b)//3 4
print(a, b)//3 4
操作符
对数字使用,算术运算符
加减乘除 +-*/
number = 2+1-2 * 3 / 4.0
print(number)
print(number)
取模 %
remainder = 11 % 3
print(remainder)
print(remainder)
次方 **
squared = 7 ** 2
cubed = 2 ** 3
print(squared)
print(cubed)
cubed = 2 ** 3
print(squared)
print(cubed)
对字符串使用
Python支持使用加法运算符连接字符串:
helloworld = "hello" + " " + "world"
print(helloworld)//hello world
print(helloworld)//hello world
Python还支持将字符串相乘以形成具有重复序列的字符串:
lotsofhellos = "hello" * 10
print(lotsofhellos)//hellohellohellohellohellohellohellohellohellohello
print(lotsofhellos)//hellohellohellohellohellohellohellohellohellohello
对列表使用
列表可以用加法操作符连接:
even_numbers = [2,4,6,8]
odd_numbers = [1,3,5,7]
all_numbers = odd_numbers + even_numbers
print(all_numbers)//[1, 3, 5, 7, 2, 4, 6, 8]
odd_numbers = [1,3,5,7]
all_numbers = odd_numbers + even_numbers
print(all_numbers)//[1, 3, 5, 7, 2, 4, 6, 8]
就像在字符串中一样,Python支持使用乘法运算符用重复序列形成新的列表:
print([1,2,3] * 3)//[1, 2, 3, 1, 2, 3, 1, 2, 3]
条件
条件运算符
布尔条件
x = 2
print(x == 2) # prints out True
print(x == 3) # prints out False
print(x < 3) # prints out True
print(x == 2) # prints out True
print(x == 3) # prints out False
print(x < 3) # prints out True
布尔操作符
"and"和"or"布尔运算符允许构建复杂的布尔表达式,
name = "John"
age = 23
if name == "John" and age == 23:
print("Your name is John, and you are also 23 years old.")
if name == "John" or name == "Rick":
print("Your name is either John or Rick.")
// Your name is John, and you are also 23 years old.
//Your name is either John or Rick.
age = 23
if name == "John" and age == 23:
print("Your name is John, and you are also 23 years old.")
if name == "John" or name == "Rick":
print("Your name is either John or Rick.")
// Your name is John, and you are also 23 years old.
//Your name is either John or Rick.
包含条件:In
"in"操作符可用于检查指定对象是否存在于可迭代对象容器中,例如列表:
name = "John"
if name in ["John", "Rick"]:
print("Your name is either John or Rick.")
if name in ["John", "Rick"]:
print("Your name is either John or Rick.")
不包含:not in
phonebook = {
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
# your code goes here
# testing code
if "Jake" in phonebook:
print("Jake is listed in the phonebook.")
if "Jill" not in phonebook:
print("Jill is not listed in the phonebook.")
"John" : 938477566,
"Jack" : 938377264,
"Jill" : 947662781
}
# your code goes here
# testing code
if "Jake" in phonebook:
print("Jake is listed in the phonebook.")
if "Jill" not in phonebook:
print("Jill is not listed in the phonebook.")
值是否相等:==
地址相等即是否是同一对象:is
与双等于操作符“==”不同,“is”操作符不匹配变量的值,而是匹配实例本身。例如:
x = [1,2,3]
y = [1,2,3]
print(x == y) # Prints out True
print(x is y) # Prints out False
y = [1,2,3]
print(x == y) # Prints out True
print(x is y) # Prints out False
地址是否不相等即是否不是同一对象:not
print(not False) # Prints out True
print((not False) == (False)) # Prints out False
print((not False) == (False)) # Prints out False
语句
控制流程语句
if语句
if条件语句
if A is True/False:
elif B is True/False:
else:
elif B is True/False:
else:
statement = False
another_statement = True
if statement is False:
# do something
print('statement')
pass
elif another_statement is True:
# else if do something else
print('another_statement')
pass
else:
# do another thing
print('else do')
pass
another_statement = True
if statement is False:
# do something
print('statement')
pass
elif another_statement is True:
# else if do something else
print('another_statement')
pass
else:
# do another thing
print('else do')
pass
if true :
else:
else:
x = 2
if x == 2:
print("x equals two!")
else:
print("x does not equal to two.")
if x == 2:
print("x equals two!")
else:
print("x does not equal to two.")
循环语句
Python中有两种类型的循环,for和while。
for循环
primes = [2, 3, 5, 7]
for prime in primes:
print(prime)
/*
2
3
5
7
*/
for prime in primes:
print(prime)
/*
2
3
5
7
*/
# Prints out the numbers 0,1,2,3,4
for x in range(5):
print(x)
# Prints out 3,4,5
for x in range(3, 6):
print(x)
# Prints out 3,5,7
for x in range(3, 8, 2):
print(x)
/*
0
1
2
3
4
3
4
5
3
5
7
*/
for x in range(5):
print(x)
# Prints out 3,4,5
for x in range(3, 6):
print(x)
# Prints out 3,5,7
for x in range(3, 8, 2):
print(x)
/*
0
1
2
3
4
3
4
5
3
5
7
*/
while循环
# Prints out 0,1,2,3,4
count = 0
while count < 5:
print(count)
count += 1 # This is the same as count = count + 1
count = 0
while count < 5:
print(count)
count += 1 # This is the same as count = count + 1
辅助语句
break和continue语句
Break用于退出for循环或while循环,而continue用于跳过当前块,并返回“for”或“while”语句。举几个例子:
# Prints out 0,1,2,3,4
count = 0
while True:
print(count)
count += 1
if count >= 5:
break
# Prints out only odd numbers - 1,3,5,7,9
for x in range(10):
# Check if x is even
if x % 2 == 0:
continue
print(x)
/*
0
1
2
3
4
1
3
5
7
9
*/
count = 0
while True:
print(count)
count += 1
if count >= 5:
break
# Prints out only odd numbers - 1,3,5,7,9
for x in range(10):
# Check if x is even
if x % 2 == 0:
continue
print(x)
/*
0
1
2
3
4
1
3
5
7
9
*/
else语句
我们可以使用else for循环。当“for”或“while”语句的循环条件失败时,执行“else”中的代码部分。如果break语句在for循环中执行,那么“else”部分将被跳过。注意,即使有continue语句,“else”部分也会执行。
# Prints out 0,1,2,3,4 and then it prints "count value reached 5"
count=0
while(count<5):
print(count)
count +=1
else:
print("count value reached %d" %(count))
# Prints out 1,2,3,4
for i in range(1, 10):
if(i%5==0):
break
print(i)
else:
print("this is not printed because for loop is terminated because of break but not due to fail in condition")
/*0
1
2
3
4
count value reached 5
1
2
3
4*/
count=0
while(count<5):
print(count)
count +=1
else:
print("count value reached %d" %(count))
# Prints out 1,2,3,4
for i in range(1, 10):
if(i%5==0):
break
print(i)
else:
print("this is not printed because for loop is terminated because of break but not due to fail in condition")
/*0
1
2
3
4
count value reached 5
1
2
3
4*/
导入语句
异常处理语句
正则表达式
举例
邮箱正则
# Exercise: make a regular expression that will match an email
import re
def test_email(your_pattern):
pattern = re.compile(your_pattern)
emails = ["john@example.com", "python-list@python.org", "wha.t.`1an?ug{}ly@email.com"]
for email in emails:
if not re.match(pattern, email):
print("You failed to match %s" % (email))
elif not your_pattern:
print("Forgot to enter a pattern!")
else:
print("Pass")
# Your pattern here!
pattern = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?"
test_email(pattern)
import re
def test_email(your_pattern):
pattern = re.compile(your_pattern)
emails = ["john@example.com", "python-list@python.org", "wha.t.`1an?ug{}ly@email.com"]
for email in emails:
if not re.match(pattern, email):
print("You failed to match %s" % (email))
elif not your_pattern:
print("Forgot to enter a pattern!")
else:
print("Pass")
# Your pattern here!
pattern = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?"
test_email(pattern)
异常表达式
举例
def do_stuff_with_number(n):
print(n)
def catch_this():
the_list = (1, 2, 3, 4, 5)
for i in range(20):
try:
do_stuff_with_number(the_list[i])
except IndexError: # Raised when accessing a non-existing index of a list
do_stuff_with_number(0)
catch_this()
print(n)
def catch_this():
the_list = (1, 2, 3, 4, 5)
for i in range(20):
try:
do_stuff_with_number(the_list[i])
except IndexError: # Raised when accessing a non-existing index of a list
do_stuff_with_number(0)
catch_this()
获取后名
actor = {"name": "John Cleese", "rank": "awesome"}
def get_last_name():
try:
return actor["name"].split(' ')[11]
except IndexError:
print("catch an indexError !")
return "default lastname"
print("All exceptions caught! Good job!")
print("The actor's last name is %s" % get_last_name())
def get_last_name():
try:
return actor["name"].split(' ')[11]
except IndexError:
print("catch an indexError !")
return "default lastname"
print("All exceptions caught! Good job!")
print("The actor's last name is %s" % get_last_name())
函数
块
块是用下列格式书写的代码区域:
block_head:
1st block line
2nd block line
...
block_head:
1st block line
2nd block line
...
经典函数:无参、固定参、可变参
定义
def my_function():
print("Hello From My Function!")
print("Hello From My Function!")
调用
my_function()
详解
在Python中,函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码块。使用函数可以提高代码的模块化,使得代码更加清晰、易于管理和维护。Python定义函数使用def关键字,后跟函数名和圆括号(),圆括号中可以包含传递给函数的参数。函数的主体则紧跟在冒号:之后,并且必须缩进。
定义函数
下面是一个简单的函数定义示例,该函数计算两个数的和:
python
复制代码
def add(x, y):
"""返回两个数的和"""
return x + y
调用函数
定义了函数之后,你可以通过函数名加上圆括号来调用它。如果函数需要参数,你需要在圆括号中提供这些参数。
python
复制代码
result = add(5, 3)
print(result) # 输出: 8
函数参数
函数参数可以是位置参数、关键字参数、默认参数、可变参数(*args)和关键字可变参数(**kwargs)。
位置参数:按照函数定义时参数的顺序传递。
关键字参数:通过参数名来指定参数值,这允许你以任意顺序传递参数。
默认参数:在函数定义时,为参数指定默认值。调用函数时,如果没有为这些参数提供值,则使用默认值。
可变参数(*args):允许你传递一个参数列表给函数,这些参数在函数内部被处理为一个元组。
关键字可变参数(**kwargs):允许你传递一个字典作为参数,这些参数在函数内部被处理为一个字典。
返回值
函数使用return语句返回值。如果函数没有return语句,则默认返回None。
示例
下面是一个包含多种参数的函数示例:
python
复制代码
def greet(name, greeting='Hello', punctuation='!'):
"""向某人打招呼,可以自定义问候语和标点符号"""
message = f"{greeting}, {name}{punctuation}"
return message
# 使用位置参数
print(greet('Alice')) # 输出: Hello, Alice!
# 使用关键字参数
print(greet(name='Bob', greeting='Hi', punctuation='.')) # 输出: Hi, Bob.
# 使用默认参数
print(greet('Charlie', punctuation='??')) # 输出: Hello, Charlie??
文档字符串
在函数定义的第一行字符串是函数的文档字符串(docstring),它是对函数功能的简短描述。使用help()函数可以查看函数的文档字符串。
python
复制代码
help(greet)
通过熟练使用函数,你可以编写出更加模块化和易于维护的Python代码。
定义函数
下面是一个简单的函数定义示例,该函数计算两个数的和:
python
复制代码
def add(x, y):
"""返回两个数的和"""
return x + y
调用函数
定义了函数之后,你可以通过函数名加上圆括号来调用它。如果函数需要参数,你需要在圆括号中提供这些参数。
python
复制代码
result = add(5, 3)
print(result) # 输出: 8
函数参数
函数参数可以是位置参数、关键字参数、默认参数、可变参数(*args)和关键字可变参数(**kwargs)。
位置参数:按照函数定义时参数的顺序传递。
关键字参数:通过参数名来指定参数值,这允许你以任意顺序传递参数。
默认参数:在函数定义时,为参数指定默认值。调用函数时,如果没有为这些参数提供值,则使用默认值。
可变参数(*args):允许你传递一个参数列表给函数,这些参数在函数内部被处理为一个元组。
关键字可变参数(**kwargs):允许你传递一个字典作为参数,这些参数在函数内部被处理为一个字典。
返回值
函数使用return语句返回值。如果函数没有return语句,则默认返回None。
示例
下面是一个包含多种参数的函数示例:
python
复制代码
def greet(name, greeting='Hello', punctuation='!'):
"""向某人打招呼,可以自定义问候语和标点符号"""
message = f"{greeting}, {name}{punctuation}"
return message
# 使用位置参数
print(greet('Alice')) # 输出: Hello, Alice!
# 使用关键字参数
print(greet(name='Bob', greeting='Hi', punctuation='.')) # 输出: Hi, Bob.
# 使用默认参数
print(greet('Charlie', punctuation='??')) # 输出: Hello, Charlie??
文档字符串
在函数定义的第一行字符串是函数的文档字符串(docstring),它是对函数功能的简短描述。使用help()函数可以查看函数的文档字符串。
python
复制代码
help(greet)
通过熟练使用函数,你可以编写出更加模块化和易于维护的Python代码。
分类
根据参数个数分类
无参函数
上述例子中my_function函数是一个无参函数
固定参数函数
def myfunction(first, second, third):
# do something with the 3 variables
...
# do something with the 3 variables
...
可变参数函数
定义、调用
def foo(first, second, third, *therest):
print("First: %s" %(first))
print("Second: %s" %(second))
print("Third: %s" %(third))
print("And all the rest... %s" %(list(therest)))
foo(1, 2, 3, 4, 5)
#First: 1
#Second: 2
#Third: 3
#And all the rest... [4, 5]
print("First: %s" %(first))
print("Second: %s" %(second))
print("Third: %s" %(third))
print("And all the rest... %s" %(list(therest)))
foo(1, 2, 3, 4, 5)
#First: 1
#Second: 2
#Third: 3
#And all the rest... [4, 5]
分类
按照参数的获取方式不同
列表可变*therest
def foo(first, second, third, *therest):
print("First: %s" %(first))
print("Second: %s" %(second))
print("Third: %s" %(third))
print("And all the rest... %s" %(list(therest)))
foo(1, 2, 3, 4, 5)
print("First: %s" %(first))
print("Second: %s" %(second))
print("Third: %s" %(third))
print("And all the rest... %s" %(list(therest)))
foo(1, 2, 3, 4, 5)
字典可变**therest
def bar(first, second, third, **options):
if options.get("action") == "sum":
print("The sum is: %d" %(first + second + third))
if options.get("number") == "first":
return first
result = bar(1, 2, 3, action = "sum", number = "first")
print("Result: %d" %(result))
if options.get("action") == "sum":
print("The sum is: %d" %(first + second + third))
if options.get("number") == "first":
return first
result = bar(1, 2, 3, action = "sum", number = "first")
print("Result: %d" %(result))
举例
填入foo和bar函数,这样它们就可以接收可变数量的参数(3个或更多)。foo函数必须返回接收到的额外参数的数量。如果带有关键字magicnumber的参数值为7,则该工具条必须返回True,否则返回False。
# edit the functions prototype and implementation
def foo(a, b, c, *args):
return len(args)
def bar(a, b, c, **kwargs):
return kwargs["magicnumber"] == 7
# test code
if foo(1, 2, 3, 4) == 1:
print("Good.")
if foo(1, 2, 3, 4, 5) == 2:
print("Better.")
if bar(1, 2, 3, magicnumber=6) == False:
print("Great.")
if bar(1, 2, 3, magicnumber=7) == True:
print("Awesome!")
#Good.
#Better.
#Great.
#Awesome!
def foo(a, b, c, *args):
return len(args)
def bar(a, b, c, **kwargs):
return kwargs["magicnumber"] == 7
# test code
if foo(1, 2, 3, 4) == 1:
print("Good.")
if foo(1, 2, 3, 4, 5) == 2:
print("Better.")
if bar(1, 2, 3, magicnumber=6) == False:
print("Great.")
if bar(1, 2, 3, magicnumber=7) == True:
print("Awesome!")
#Good.
#Better.
#Great.
#Awesome!
使用
举例
不仅可以根据顺序,获取可变参数,而且还可以使用关键字获取可变参数
def bar(first, second, third, **options):
if options.get("action") == "sum":
print("The sum is: %d" %(first + second + third))
if options.get("number") == "first":
return first
result = bar(1, 2, 3, action = "sum", number = "first")
print("Result: %d" %(result))
if options.get("action") == "sum":
print("The sum is: %d" %(first + second + third))
if options.get("number") == "first":
return first
result = bar(1, 2, 3, action = "sum", number = "first")
print("Result: %d" %(result))
特点
不仅可以根据顺序,获取可变参数,而且还可以使用关键字获取可变参数。不过两种参数获取方式的定义方式不一样
空函数:定义
def bar(a, b, c, **options):
pass
pass
lambda函数
定义:your_function_name = lambda inputs : output
举例
求和函数
经典函数:
def sum(a,b):
return a + b
a = 1
b = 2
c = sum(a,b)
print(c)
lambda函数:
a = 1
b = 2
sum = lambda x,y : x + y
c = sum(a,b)
print(c)
def sum(a,b):
return a + b
a = 1
b = 2
c = sum(a,b)
print(c)
lambda函数:
a = 1
b = 2
sum = lambda x,y : x + y
c = sum(a,b)
print(c)
编写一个程序,使用lambda函数检查给定列表中的数字是否为奇数。对于每个元素,如果数字是奇数,则打印“True”;如果不是奇数,则打印“False”。
l = [2,4,7,3,14,19]
isOdd = lambda i : print(i % 2 == 1)
for i in l:
# your code here
isOdd(i)
isOdd = lambda i : print(i % 2 == 1)
for i in l:
# your code here
isOdd(i)
偏函数
例子
from functools import partial
def func(u, v, w, x):
return u*4 + v*3 + w*2 + x
p = partial(func,5,6,7)
print(p(8))
print(func(5,6,7,8))
def func(u, v, w, x):
return u*4 + v*3 + w*2 + x
p = partial(func,5,6,7)
print(p(8))
print(func(5,6,7,8))
是什么
Partial functions(偏函数)是一个来自函数式编程的强大工具,主要用于减少函数调用的复杂性。偏函数的概念是固定一个函数的一些参数,然后生成一个新的函数的行为。这种方式可以让我们复用已有的函数但不需要改变它们的实现,从而简化代码并提高复用性。
在Python中,Partial functions(偏函数)是一个来自函数式编程的强大工具,主要用于减少函数调用的复杂性。偏函数的概念是固定一个函数的一些参数,然后生成一个新的函数的行为。这种方式可以让我们复用已有的函数但不需要改变它们的实现,从而简化代码并提高复用性。
一、偏函数的定义
偏函数在Python中通常是通过functools模块中的partial函数来实现的。partial函数接受一个函数作为第一个参数,然后可以接受任意数量的位置参数或关键字参数。这些参数会被“冻结”在原始函数上,从而生成一个新的函数,这个新函数在调用时会自动携带这些被“冻结”的参数。
二、偏函数的使用方法
1. 固定参数值
假设我们有一个函数power(base, exponent),用于计算幂。如果我们经常需要计算平方数,就可以使用partial来创建一个新的函数square,其中exponent参数被固定为2。
python
复制代码
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
print(square(3)) # 输出: 9
2. 预设关键字参数
对于接受关键字参数的函数,partial也可以预设这些参数的值。例如,int()函数可以接受一个base参数来指定转换的进制。如果我们经常需要进行二进制到十进制的转换,可以创建一个新的函数来固定base参数为2。
python
复制代码
import functools
int2 = functools.partial(int, base=2)
print(int2('1000000')) # 输出: 64
3. 预设位置参数
除了关键字参数,partial也可以预设位置参数的值。这在需要固定某些参数位置,但不想使用关键字参数时非常有用。
python
复制代码
max_with_10 = functools.partial(max, 10)
print(max_with_10(5, 6, 7)) # 输出: 10
在这个例子中,10被预设为max函数的第一个参数,这意味着无论调用时传入什么值,10都会被当作第一个参数来处理。
三、偏函数的注意事项
参数顺序:partial函数将预设参数应用到原始函数的参数上,按照它们在原始函数中定义的顺序。
关键字参数的覆盖:如果偏函数和原始函数都使用了同一个关键字参数,那么偏函数的值将会覆盖原始函数的值。
偏函数仍然是函数:偏函数本身仍然是函数,可以像其他任何函数一样使用,包括作为其他函数的参数,或者在类中作为方法使用。
四、总结
Python中的Partial functions(偏函数)通过functools.partial实现,允许我们固定函数的部分参数,从而生成一个新的函数。这种方式可以简化函数调用的复杂性,提高代码的复用性和可读性。
一、偏函数的定义
偏函数在Python中通常是通过functools模块中的partial函数来实现的。partial函数接受一个函数作为第一个参数,然后可以接受任意数量的位置参数或关键字参数。这些参数会被“冻结”在原始函数上,从而生成一个新的函数,这个新函数在调用时会自动携带这些被“冻结”的参数。
二、偏函数的使用方法
1. 固定参数值
假设我们有一个函数power(base, exponent),用于计算幂。如果我们经常需要计算平方数,就可以使用partial来创建一个新的函数square,其中exponent参数被固定为2。
python
复制代码
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
print(square(3)) # 输出: 9
2. 预设关键字参数
对于接受关键字参数的函数,partial也可以预设这些参数的值。例如,int()函数可以接受一个base参数来指定转换的进制。如果我们经常需要进行二进制到十进制的转换,可以创建一个新的函数来固定base参数为2。
python
复制代码
import functools
int2 = functools.partial(int, base=2)
print(int2('1000000')) # 输出: 64
3. 预设位置参数
除了关键字参数,partial也可以预设位置参数的值。这在需要固定某些参数位置,但不想使用关键字参数时非常有用。
python
复制代码
max_with_10 = functools.partial(max, 10)
print(max_with_10(5, 6, 7)) # 输出: 10
在这个例子中,10被预设为max函数的第一个参数,这意味着无论调用时传入什么值,10都会被当作第一个参数来处理。
三、偏函数的注意事项
参数顺序:partial函数将预设参数应用到原始函数的参数上,按照它们在原始函数中定义的顺序。
关键字参数的覆盖:如果偏函数和原始函数都使用了同一个关键字参数,那么偏函数的值将会覆盖原始函数的值。
偏函数仍然是函数:偏函数本身仍然是函数,可以像其他任何函数一样使用,包括作为其他函数的参数,或者在类中作为方法使用。
四、总结
Python中的Partial functions(偏函数)通过functools.partial实现,允许我们固定函数的部分参数,从而生成一个新的函数。这种方式可以简化函数调用的复杂性,提高代码的复用性和可读性。
声明
from functools import partial
def multiply(x, y):
return x * y
# create a new function that multiplies by 2
dbl = partial(multiply, 2)
print(dbl(4))
def multiply(x, y):
return x * y
# create a new function that multiplies by 2
dbl = partial(multiply, 2)
print(dbl(4))
嵌套函数
嵌套函数是定义在另一个函数内部的函数。需要注意的是,嵌套函数可以访问封闭作用域的变量。然而,至少在python中,它们只是只读的。但是,可以对这些变量显式地使用“nonlocal”关键字来修改它们。
例子
定义
def transmit_to_space(message):
"This is the enclosing function"
def data_transmitter():
"The nested function"
print(message)
data_transmitter()
print(transmit_to_space("Test message"))
"This is the enclosing function"
def data_transmitter():
"The nested function"
print(message)
data_transmitter()
print(transmit_to_space("Test message"))
使用nonlocal修饰参数来修改外部参数的值
未使用nonlocal修饰
def print_msg(number):
def printer():
"Here we are using the nonlocal keyword"
#nonlocal number
number=3
print(number)
printer()
print(number)
print_msg(9)
#3
#9
def printer():
"Here we are using the nonlocal keyword"
#nonlocal number
number=3
print(number)
printer()
print(number)
print_msg(9)
#3
#9
使用nonlocal修饰
def print_msg(number):
def printer():
"Here we are using the nonlocal keyword"
nonlocal number
number=3
print(number)
printer()
print(number)
print_msg(9)
#3
#3
def printer():
"Here we are using the nonlocal keyword"
nonlocal number
number=3
print(number)
printer()
print(number)
print_msg(9)
#3
#3
结论
如果没有nonlocal关键字,输出将是“3 9”,然而,使用它,我们得到“3 3”,这是“number”变量的值被修改。
闭包:保留了函数及其执行上下文的对象。返回值返回函数对象的函数
例子
def transmit_to_space(message):
"This is the enclosing function"
def data_transmitter():
"The nested function"
print(message)
return data_transmitter
fun2 = transmit_to_space("Burn the Sun!")
fun2()
"This is the enclosing function"
def data_transmitter():
"The nested function"
print(message)
return data_transmitter
fun2 = transmit_to_space("Burn the Sun!")
fun2()
闭包
什么闭包:即使完成了“transmit_to_space()”的执行,消息也被保留了下来。这种将数据附加到某些代码的技术,甚至在其他原始函数结束之后,在python中称为闭包
例子
定义一个乘以factor的乘法函数
def multiplier_of(factor):
def multiplier(number):
return number * factor
return multiplier
multiplywith5 = multiplier_of(5)
print(multiplywith5(9))
def multiplier(number):
return number * factor
return multiplier
multiplywith5 = multiplier_of(5)
print(multiplywith5(9))
优点:闭包可以避免使用全局变量,并提供某种形式的数据隐藏。当类中的方法很少时,请使用闭包)。
特性
函数也是对象
类、对象
是什么
对象是将变量和函数封装成一个实体。对象从类中获取变量和函数。类本质上是创建对象的模板。
声明类
// 声明一个类
class MyClass:
variable = "blah"
def function(self):
print("This is a message inside the class.")
class MyClass:
variable = "blah"
def function(self):
print("This is a message inside the class.")
创建对象
class MyClass:
variable = "blah"
def function(self):
print("This is a message inside the class.")
// 创建一个对象
myobjectx = MyClass()
variable = "blah"
def function(self):
print("This is a message inside the class.")
// 创建一个对象
myobjectx = MyClass()
访问对象变量
class MyClass:
variable = "blah"
def function(self):
print("This is a message inside the class.")
myobjectx = MyClass()
// 访问对象变量
myobjectx.variable
// 打印访问的变量的值
print(myobjectx.variable)
variable = "blah"
def function(self):
print("This is a message inside the class.")
myobjectx = MyClass()
// 访问对象变量
myobjectx.variable
// 打印访问的变量的值
print(myobjectx.variable)
访问对象函数
class MyClass:
variable = "blah"
def function(self):
print("This is a message inside the class.")
myobjectx = MyClass()
myobjectx.function()
variable = "blah"
def function(self):
print("This is a message inside the class.")
myobjectx = MyClass()
myobjectx.function()
初始化 init()
__init__()函数是在初始化类时调用的特殊函数。它用于在类中赋值。
class NumberHolder:
def __init__(self, number):
self.number = number
def returnNumber(self):
return self.number
var = NumberHolder(7)
print(var.returnNumber()) #Prints '7'
def __init__(self, number):
self.number = number
def returnNumber(self):
return self.number
var = NumberHolder(7)
print(var.returnNumber()) #Prints '7'
模块、包
模块
是什么
Python中的模块只是扩展名为.py的Python文件。模块名与文件名一致。Python模块可以定义和实现一组函数、类或变量。上面的例子包括两个文件:
mygame/
mygame/game.py
mygame/draw.py
mygame/
mygame/game.py
mygame/draw.py
引入模块
使用import命令从其他模块导入模块。
# game.py
# import the draw module
import draw
def play_game():
...
def main():
result = play_game()
draw.draw_game(result)
# this means that if this script is executed, then
# main() will be executed
if __name__ == '__main__':
main()
# import the draw module
import draw
def play_game():
...
def main():
result = play_game()
draw.draw_game(result)
# this means that if this script is executed, then
# main() will be executed
if __name__ == '__main__':
main()
将模块对象导入到当前命名空间
# game.py
# import the draw module
from draw import draw_game
def main():
result = play_game()
draw_game(result)
# import the draw module
from draw import draw_game
def main():
result = play_game()
draw_game(result)
从模块中导入所有对象
# game.py
# import the draw module
from draw import *
def main():
result = play_game()
draw_game(result)
# import the draw module
from draw import *
def main():
result = play_game()
draw_game(result)
自定义导入名称
# game.py
# import the draw module
if visual_mode:
# in visual mode, we draw using graphics
import draw_visual as draw
else:
# in textual mode, we print out text
import draw_textual as draw
def main():
result = play_game()
# this can either be visual or textual depending on visual_mode
draw.draw_game(result)
# import the draw module
if visual_mode:
# in visual mode, we draw using graphics
import draw_visual as draw
else:
# in textual mode, we print out text
import draw_textual as draw
def main():
result = play_game()
# this can either be visual or textual depending on visual_mode
draw.draw_game(result)
单例
# draw.py
def draw_game():
# when clearing the screen we can use the main screen object initialized in this module
clear_screen(main_screen)
...
def clear_screen(screen):
...
class Screen():
...
# initialize main_screen as a singleton
main_screen = Screen()
def draw_game():
# when clearing the screen we can use the main screen object initialized in this module
clear_screen(main_screen)
...
def clear_screen(screen):
...
class Screen():
...
# initialize main_screen as a singleton
main_screen = Screen()
扩展模块加载路径
除了默认的本地目录和内置模块外,还有几种方法可以告诉Python解释器在哪里查找模块。你可以使用环境变量PYTHONPATH来指定其他目录来查找像这样的模块:
PYTHONPATH=/foo python game.py
您也可以使用sys.path.append函数。执行import命令前请先执行:
sys.path.append("/foo")
引入内置模块
# import the library
import urllib
# use it
urllib.urlopen(...)
import urllib
# use it
urllib.urlopen(...)
我们可以通过使用dir函数来查找每个模块中实现的函数:
>>> import urllib
>>> dir(urllib)
['ContentTooShortError', 'FancyURLopener', 'MAXFTPCACHE', 'URLopener', '__all__', '__builtins__',
'__doc__', '__file__', '__name__', '__package__', '__version__', '_ftperrors', '_get_proxies',
'_get_proxy_settings', '_have_ssl', '_hexdig', '_hextochr', '_hostprog', '_is_unicode', '_localhost',
'_noheaders', '_nportprog', '_passwdprog', '_portprog', '_queryprog', '_safe_map', '_safe_quoters',
'_tagprog', '_thishost', '_typeprog', '_urlopener', '_userprog', '_valueprog', 'addbase', 'addclosehook',
'addinfo', 'addinfourl', 'always_safe', 'basejoin', 'c', 'ftpcache', 'ftperrors', 'ftpwrapper', 'getproxies',
'getproxies_environment', 'getproxies_macosx_sysconf', 'i', 'localhost', 'main', 'noheaders', 'os',
'pathname2url', 'proxy_bypass', 'proxy_bypass_environment', 'proxy_bypass_macosx_sysconf', 'quote',
'quote_plus', 'reporthook', 'socket', 'splitattr', 'splithost', 'splitnport', 'splitpasswd', 'splitport',
'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'ssl', 'string', 'sys', 'test', 'test1',
'thishost', 'time', 'toBytes', 'unquote', 'unquote_plus', 'unwrap', 'url2pathname', 'urlcleanup', 'urlencode',
'urlopen', 'urlretrieve']
>>> dir(urllib)
['ContentTooShortError', 'FancyURLopener', 'MAXFTPCACHE', 'URLopener', '__all__', '__builtins__',
'__doc__', '__file__', '__name__', '__package__', '__version__', '_ftperrors', '_get_proxies',
'_get_proxy_settings', '_have_ssl', '_hexdig', '_hextochr', '_hostprog', '_is_unicode', '_localhost',
'_noheaders', '_nportprog', '_passwdprog', '_portprog', '_queryprog', '_safe_map', '_safe_quoters',
'_tagprog', '_thishost', '_typeprog', '_urlopener', '_userprog', '_valueprog', 'addbase', 'addclosehook',
'addinfo', 'addinfourl', 'always_safe', 'basejoin', 'c', 'ftpcache', 'ftperrors', 'ftpwrapper', 'getproxies',
'getproxies_environment', 'getproxies_macosx_sysconf', 'i', 'localhost', 'main', 'noheaders', 'os',
'pathname2url', 'proxy_bypass', 'proxy_bypass_environment', 'proxy_bypass_macosx_sysconf', 'quote',
'quote_plus', 'reporthook', 'socket', 'splitattr', 'splithost', 'splitnport', 'splitpasswd', 'splitport',
'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'ssl', 'string', 'sys', 'test', 'test1',
'thishost', 'time', 'toBytes', 'unquote', 'unquote_plus', 'unwrap', 'url2pathname', 'urlcleanup', 'urlencode',
'urlopen', 'urlretrieve']
Python解释器的help函数来阅读函数的更多信息
help(urllib.urlopen)
模块的两种导入方式
import foo.bar
from foo import bar
__init__.py 文件
是什么
如果我们创建一个名为foo的目录,它标记了包的名称,那么我们就可以在该包中创建一个名为bar的模块。然后我们在foo目录中添加__init__.py文件。
操作
__init__.py文件还可以通过覆盖__all__变量来决定包导出哪些模块作为API,同时保留其他模块为内部模块,如下所示:
__init__.py:
__all__ = ["bar"]
__all__ = ["bar"]
包
生成器(Generator)
是什么
通常指的是生成器方法
类型
生成器类型(types.GeneratorType)
if type(fib()) == types.GeneratorType:
print("The fib function is a generator.")
print("The fib function is a generator.")
用来做什么的
节省内存:生成器按需产生值,而不是一次性将所有值存储在内存中。这对于处理大量数据或无限序列特别有用。
简化代码:生成器提供了一种简洁的方式来表示复杂的迭代逻辑。
简化代码:生成器提供了一种简洁的方式来表示复杂的迭代逻辑。
如何使用
yield生成值
yield
在Python中,yield 关键字在函数中的使用赋予了该函数一种特殊的能力,使其成为一个生成器函数。yield 的含义和作用主要体现在以下几个方面:
暂停与恢复执行:当函数执行到 yield 语句时,它会暂停当前的执行,并将紧随 yield 之后的值返回给函数的调用者。此时,函数的状态(包括局部变量和当前执行位置)会被保存起来。当再次对生成器进行迭代(例如,通过 next() 函数或在 for 循环中)时,函数会从上次暂停的位置继续执行,直到遇到下一个 yield 语句或函数结束。
返回生成的值:yield 语句不仅暂停函数的执行,还将其后的值返回给生成器的调用者。这使得生成器能够按需产生一系列的值,而不是一次性返回所有值。
节省内存:由于生成器是按需产生值的,因此它们对于处理大量数据或无限序列特别有用。与一次性将所有数据加载到内存中的列表相比,生成器可以显著节省内存。
简化代码:使用生成器可以简化某些复杂的迭代逻辑,特别是当需要处理的数据集合是通过一系列计算或复杂操作生成时。
在你给出的 lottery 函数中,yield 的使用使得该函数能够生成一个包含7个随机数的序列,其中前6个随机数是在1到40之间,最后一个随机数是在1到15之间。当对 lottery() 函数返回的生成器进行迭代时,每次迭代都会生成并返回序列中的下一个随机数,直到所有随机数都被生成并返回。
例如:
python
复制代码
import random
def lottery():
for i in range(6):
yield random.randint(1, 40)
yield random.randint(1, 15)
# 使用生成器
lotto_gen = lottery()
print(next(lotto_gen)) # 输出第一个随机数
print(list(lotto_gen)) # 输出剩余的随机数作为列表
在这个例子中,next(lotto_gen) 调用了生成器的下一个值,而 list(lotto_gen) 则将剩余的随机数作为一个列表返回。注意,由于 list(lotto_gen) 会耗尽生成器中的所有值,所以在再次迭代之前,你需要重新调用 lottery() 来获取一个新的生成器。
暂停与恢复执行:当函数执行到 yield 语句时,它会暂停当前的执行,并将紧随 yield 之后的值返回给函数的调用者。此时,函数的状态(包括局部变量和当前执行位置)会被保存起来。当再次对生成器进行迭代(例如,通过 next() 函数或在 for 循环中)时,函数会从上次暂停的位置继续执行,直到遇到下一个 yield 语句或函数结束。
返回生成的值:yield 语句不仅暂停函数的执行,还将其后的值返回给生成器的调用者。这使得生成器能够按需产生一系列的值,而不是一次性返回所有值。
节省内存:由于生成器是按需产生值的,因此它们对于处理大量数据或无限序列特别有用。与一次性将所有数据加载到内存中的列表相比,生成器可以显著节省内存。
简化代码:使用生成器可以简化某些复杂的迭代逻辑,特别是当需要处理的数据集合是通过一系列计算或复杂操作生成时。
在你给出的 lottery 函数中,yield 的使用使得该函数能够生成一个包含7个随机数的序列,其中前6个随机数是在1到40之间,最后一个随机数是在1到15之间。当对 lottery() 函数返回的生成器进行迭代时,每次迭代都会生成并返回序列中的下一个随机数,直到所有随机数都被生成并返回。
例如:
python
复制代码
import random
def lottery():
for i in range(6):
yield random.randint(1, 40)
yield random.randint(1, 15)
# 使用生成器
lotto_gen = lottery()
print(next(lotto_gen)) # 输出第一个随机数
print(list(lotto_gen)) # 输出剩余的随机数作为列表
在这个例子中,next(lotto_gen) 调用了生成器的下一个值,而 list(lotto_gen) 则将剩余的随机数作为一个列表返回。注意,由于 list(lotto_gen) 会耗尽生成器中的所有值,所以在再次迭代之前,你需要重新调用 lottery() 来获取一个新的生成器。
特点
可以代替return
在Python中,一个函数中使用yield语句时,该函数自动变成一个生成器函数(generator function)。生成器函数是一种特殊的迭代器,它返回一个迭代器对象,这个对象在每次迭代时都会执行函数中的代码,直到遇到下一个yield语句或者函数结束。
在你给出的lottery函数中,尽管函数本身没有显式的return语句,但使用了yield语句,这使得它成为一个生成器。当这个函数被调用时,它并不立即执行其体内的代码,而是返回一个生成器对象。随后,每当对返回的生成器对象使用迭代(例如通过next()函数或者在for循环中)时,函数中的代码会从上次停止的yield语句之后继续执行,直到遇到下一个yield语句或者函数执行完毕。
具体到lottery函数:
当第一次迭代(或调用next())时,函数执行到第一个yield语句,生成一个1到40之间的随机数,然后暂停。
再次迭代时,它从上一个yield语句之后继续执行,再次生成一个随机数,直到循环结束,总共生成6个1到40之间的随机数。
循环结束后,执行到第二个yield语句,生成一个1到15之间的随机数,然后函数执行完毕。
因此,尽管lottery函数没有显式的return语句,但它通过yield语句返回了一个生成器对象,这个对象能够按需生成一系列的值。
这种机制使得生成器在处理大量数据或需要逐步生成数据时非常有用,因为它允许按需生成数据,而不是一次性将所有数据加载到内存中。这对于处理大型数据集或无限序列(如自然数序列)特别有用。
在你给出的lottery函数中,尽管函数本身没有显式的return语句,但使用了yield语句,这使得它成为一个生成器。当这个函数被调用时,它并不立即执行其体内的代码,而是返回一个生成器对象。随后,每当对返回的生成器对象使用迭代(例如通过next()函数或者在for循环中)时,函数中的代码会从上次停止的yield语句之后继续执行,直到遇到下一个yield语句或者函数执行完毕。
具体到lottery函数:
当第一次迭代(或调用next())时,函数执行到第一个yield语句,生成一个1到40之间的随机数,然后暂停。
再次迭代时,它从上一个yield语句之后继续执行,再次生成一个随机数,直到循环结束,总共生成6个1到40之间的随机数。
循环结束后,执行到第二个yield语句,生成一个1到15之间的随机数,然后函数执行完毕。
因此,尽管lottery函数没有显式的return语句,但它通过yield语句返回了一个生成器对象,这个对象能够按需生成一系列的值。
这种机制使得生成器在处理大量数据或需要逐步生成数据时非常有用,因为它允许按需生成数据,而不是一次性将所有数据加载到内存中。这对于处理大型数据集或无限序列(如自然数序列)特别有用。
可以使用for in 遍历
生成器方法,返回生成器对象,定义生成器对象变量接收返回值,操作生成器对像
完整例子
# fill in this function
def fib():
a, b = 1, 1
while 1:
yield a
a, b = b, a + b
# 判断是否是生成器类型
import types
if type(fib()) == types.GeneratorType:
print("Good1, The fib function is a generator.")
#生成器forin遍历
counter = 0
for n in fib():
print(n)
counter += 1
if counter == 10:
break
#声明一个生成器对象,生成器对象是由生成器方法生成
gen = fib();
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
def fib():
a, b = 1, 1
while 1:
yield a
a, b = b, a + b
# 判断是否是生成器类型
import types
if type(fib()) == types.GeneratorType:
print("Good1, The fib function is a generator.")
#生成器forin遍历
counter = 0
for n in fib():
print(n)
counter += 1
if counter == 10:
break
#声明一个生成器对象,生成器对象是由生成器方法生成
gen = fib();
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
定义一个生成器方法
# fill in this function
def fib():
a, b = 1, 1
while 1:
yield a
a, b = b, a + b
def fib():
a, b = 1, 1
while 1:
yield a
a, b = b, a + b
判断是否是生成器类型
# 判断是否是生成器类型
import types
if type(fib()) == types.GeneratorType:
print("Good1, The fib function is a generator.")
import types
if type(fib()) == types.GeneratorType:
print("Good1, The fib function is a generator.")
声明一个生成器对象
#声明一个生成器对象,生成器对象是由生成器方法生成
gen = fib();
gen = fib();
使用 for in 进行迭代
#生成器forin遍历
counter = 0
for n in fib():
print(n)
counter += 1
if counter == 10:
break
counter = 0
for n in fib():
print(n)
counter += 1
if counter == 10:
break
next(gen)方法生成并获取下一个值
#声明一个生成器对象,生成器对象是由生成器方法生成
gen = fib();
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
gen = fib();
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
详细
生成器如何使用
Python 中的生成器是一种迭代器,用于简化创建迭代器的过程。它们是通过编写包含 yield 语句的函数来定义的。每次 yield 语句被调用时,生成器会暂停执行,并返回 yield 后面的值给调用者。当生成器的 __next__() 方法被调用时(或在循环中自动调用),生成器会从上次暂停的地方继续执行,直到遇到下一个 yield 语句或执行结束。
定义生成器
生成器可以通过两种方式定义:
使用 yield 语句的函数:
python
复制代码
def my_generator():
yield 1
yield 2
yield 3
这个函数是一个生成器函数,因为它包含了一个或多个 yield 语句。调用这个函数时,它不会立即执行函数体中的代码,而是返回一个生成器对象。
使用圆括号而不是方括号来创建生成器表达式:
python
复制代码
my_gen_expr = (x*2 for x in range(3))
这是一个生成器表达式,它生成一个生成器对象,该对象将产生 0*2, 1*2, 2*2 的值。
使用生成器
生成器对象支持迭代器协议,即它们有 __iter__() 和 __next__() 方法。你可以使用 next() 函数或在一个循环中迭代它们来消费它们产生的值。
使用 next() 函数
python
复制代码
gen = my_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
# 如果再次调用 next(gen),会抛出 StopIteration 异常,因为生成器已经执行完毕
在循环中使用
python
复制代码
for value in my_generator():
print(value)
# 输出:
# 1
# 2
# 3
for value in (x*2 for x in range(3)):
print(value)
# 输出:
# 0
# 2
# 4
生成器的优点
节省内存:生成器按需产生值,而不是一次性将所有值存储在内存中。这对于处理大量数据或无限序列特别有用。
简化代码:生成器提供了一种简洁的方式来表示复杂的迭代逻辑。
示例:使用生成器生成斐波那契数列
python
复制代码
def fibonacci(n):
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
for fib_num in fibonacci(10):
print(fib_num)
# 输出斐波那契数列的前10个数
这个示例展示了如何使用生成器来生成斐波那契数列的前 n 个数。每次调用 yield 时,都会暂停函数,并返回当前的斐波那契数,直到达到所需的数量。
定义生成器
生成器可以通过两种方式定义:
使用 yield 语句的函数:
python
复制代码
def my_generator():
yield 1
yield 2
yield 3
这个函数是一个生成器函数,因为它包含了一个或多个 yield 语句。调用这个函数时,它不会立即执行函数体中的代码,而是返回一个生成器对象。
使用圆括号而不是方括号来创建生成器表达式:
python
复制代码
my_gen_expr = (x*2 for x in range(3))
这是一个生成器表达式,它生成一个生成器对象,该对象将产生 0*2, 1*2, 2*2 的值。
使用生成器
生成器对象支持迭代器协议,即它们有 __iter__() 和 __next__() 方法。你可以使用 next() 函数或在一个循环中迭代它们来消费它们产生的值。
使用 next() 函数
python
复制代码
gen = my_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
# 如果再次调用 next(gen),会抛出 StopIteration 异常,因为生成器已经执行完毕
在循环中使用
python
复制代码
for value in my_generator():
print(value)
# 输出:
# 1
# 2
# 3
for value in (x*2 for x in range(3)):
print(value)
# 输出:
# 0
# 2
# 4
生成器的优点
节省内存:生成器按需产生值,而不是一次性将所有值存储在内存中。这对于处理大量数据或无限序列特别有用。
简化代码:生成器提供了一种简洁的方式来表示复杂的迭代逻辑。
示例:使用生成器生成斐波那契数列
python
复制代码
def fibonacci(n):
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
for fib_num in fibonacci(10):
print(fib_num)
# 输出斐波那契数列的前10个数
这个示例展示了如何使用生成器来生成斐波那契数列的前 n 个数。每次调用 yield 时,都会暂停函数,并返回当前的斐波那契数,直到达到所需的数量。
迭代器
思考
遍历和迭代的区别是什么
迭代一种使用生成器的遍历方法
在Python中,遍历(Traversal)和迭代(Iteration)这两个概念经常一起出现,并且它们之间有着紧密的联系,但在具体使用时有一些微妙的区别。
遍历(Traversal)
遍历通常指的是按照一定的顺序访问数据结构(如列表、元组、字典、集合、树、图等)中的每个元素,但不一定需要遵循迭代器的协议。遍历的目的是为了查看或处理数据结构中的每个元素,但它不一定需要使用iter()函数或for循环中的迭代器。
例如,你可以直接通过索引来遍历列表中的每个元素,尽管这不是最Pythonic的方式,但它仍然是一种遍历。
python
复制代码
my_list = [1, 2, 3, 4, 5]
for i in range(len(my_list)):
print(my_list[i]) # 通过索引遍历列表
迭代(Iteration)
迭代是Python中更核心、更广泛使用的概念。它指的是通过迭代器(Iterator)逐一访问数据结构中的元素。迭代器是遵循迭代器协议的对象,即实现了__iter__()和__next__()方法的对象。当你对可迭代对象(如列表、元组、字典等)使用iter()函数时,你会得到一个迭代器。然后,你可以使用next()函数或for循环来遍历迭代器中的元素。
python
复制代码
my_list = [1, 2, 3, 4, 5]
iterator = iter(my_list) # 获取迭代器
while True:
try:
print(next(iterator)) # 使用next()函数迭代
except StopIteration:
break # 当迭代器耗尽时退出循环
# 或者使用for循环进行迭代
for item in my_list:
print(item) # for循环自动处理迭代过程
区别与联系
区别:遍历更侧重于按照某种顺序访问数据结构中的元素,而迭代则更侧重于通过迭代器来逐一访问元素。遍历可以通过多种方式实现(如直接通过索引访问),而迭代则严格遵循迭代器协议。
联系:在Python中,当你使用for循环遍历一个可迭代对象时,实际上是在背后使用了迭代机制。for循环会自动调用可迭代对象的__iter__()方法获取迭代器,并通过不断调用迭代器的__next__()方法来遍历元素,直到捕获到StopIteration异常为止。
因此,可以说迭代是Python中实现遍历的一种更底层、更通用的方式。在大多数情况下,你不需要显式地处理迭代器,因为for循环已经为你封装好了这些细节。但在某些需要更精细控制迭代过程的情况下(如需要同时遍历多个可迭代对象或需要提前退出迭代),直接操作迭代器会更有用。
在Python中,遍历(Traversal)和迭代(Iteration)这两个概念经常一起出现,并且它们之间有着紧密的联系,但在具体使用时有一些微妙的区别。
遍历(Traversal)
遍历通常指的是按照一定的顺序访问数据结构(如列表、元组、字典、集合、树、图等)中的每个元素,但不一定需要遵循迭代器的协议。遍历的目的是为了查看或处理数据结构中的每个元素,但它不一定需要使用iter()函数或for循环中的迭代器。
例如,你可以直接通过索引来遍历列表中的每个元素,尽管这不是最Pythonic的方式,但它仍然是一种遍历。
python
复制代码
my_list = [1, 2, 3, 4, 5]
for i in range(len(my_list)):
print(my_list[i]) # 通过索引遍历列表
迭代(Iteration)
迭代是Python中更核心、更广泛使用的概念。它指的是通过迭代器(Iterator)逐一访问数据结构中的元素。迭代器是遵循迭代器协议的对象,即实现了__iter__()和__next__()方法的对象。当你对可迭代对象(如列表、元组、字典等)使用iter()函数时,你会得到一个迭代器。然后,你可以使用next()函数或for循环来遍历迭代器中的元素。
python
复制代码
my_list = [1, 2, 3, 4, 5]
iterator = iter(my_list) # 获取迭代器
while True:
try:
print(next(iterator)) # 使用next()函数迭代
except StopIteration:
break # 当迭代器耗尽时退出循环
# 或者使用for循环进行迭代
for item in my_list:
print(item) # for循环自动处理迭代过程
区别与联系
区别:遍历更侧重于按照某种顺序访问数据结构中的元素,而迭代则更侧重于通过迭代器来逐一访问元素。遍历可以通过多种方式实现(如直接通过索引访问),而迭代则严格遵循迭代器协议。
联系:在Python中,当你使用for循环遍历一个可迭代对象时,实际上是在背后使用了迭代机制。for循环会自动调用可迭代对象的__iter__()方法获取迭代器,并通过不断调用迭代器的__next__()方法来遍历元素,直到捕获到StopIteration异常为止。
因此,可以说迭代是Python中实现遍历的一种更底层、更通用的方式。在大多数情况下,你不需要显式地处理迭代器,因为for循环已经为你封装好了这些细节。但在某些需要更精细控制迭代过程的情况下(如需要同时遍历多个可迭代对象或需要提前退出迭代),直接操作迭代器会更有用。
列表推导(List Comprehensions)
举例
已知一个由单词组成的列表,生成一个新的列表其中每个元素是对应元素单词的长度
遍历循环处理:
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split()
word_lengths = []
for word in words:
if word != "the":
word_lengths.append(len(word))
print(words)
print(word_lengths)
使用列表推导处理:
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split()
word_lengths = [len(word) for word in words if word != "the"]
print(words)
print(word_lengths)
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split()
word_lengths = []
for word in words:
if word != "the":
word_lengths.append(len(word))
print(words)
print(word_lengths)
使用列表推导处理:
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split()
word_lengths = [len(word) for word in words if word != "the"]
print(words)
print(word_lengths)
使用列表推导式,从列表“numbers”中创建一个名为“newlist”的新列表,该列表仅包含列表中的正数作为整数。
numbers = [34.6, -203.4, 44.9, 68.3, -12.2, 44.6, 12.7]
newlist = [int(number) for number in numbers if number > 0]
print(newlist)
newlist = [int(number) for number in numbers if number > 0]
print(newlist)
序列化
json
encode to json string
要将数据结构编码为JSON,请使用“dumps”方法。这个方法接受一个对象并返回一个String对象:
import json
json_string = json.dumps([1, 2, 3, "a", "b", "c"])
print(json_string)
json_string = json.dumps([1, 2, 3, "a", "b", "c"])
print(json_string)
decode to struct
要将JSON加载回数据结构,请使用“loads”方法。这个方法接受一个字符串并将其转换回json对象数据结构:
import json
print(json.loads(json_string))
print(json.loads(json_string))
例子
打印出添加了键值对“Me”:800的JSON字符串。
import json
# fix this function, so it adds the given name
# and salary pair to salaries_json, and return it
def add_employee(salaries_json, name, salary):
# Add your code here
salaries_struct = json.loads(salaries_json)
salaries_struct[name] = salary
salaries_json = json.dumps(salaries_struct)
return salaries_json
# test code
salaries = '{"Alfred" : 300, "Jane" : 400 }'
new_salaries = add_employee(salaries, "Me", 800)
decoded_salaries = json.loads(new_salaries)
print(decoded_salaries["Alfred"])
print(decoded_salaries["Jane"])
print(decoded_salaries["Me"])
/*
300
400
800
*/
# fix this function, so it adds the given name
# and salary pair to salaries_json, and return it
def add_employee(salaries_json, name, salary):
# Add your code here
salaries_struct = json.loads(salaries_json)
salaries_struct[name] = salary
salaries_json = json.dumps(salaries_struct)
return salaries_json
# test code
salaries = '{"Alfred" : 300, "Jane" : 400 }'
new_salaries = add_employee(salaries, "Me", 800)
decoded_salaries = json.loads(new_salaries)
print(decoded_salaries["Alfred"])
print(decoded_salaries["Jane"])
print(decoded_salaries["Me"])
/*
300
400
800
*/
pickle
Python支持Python专有的数据序列化方法pickle(以及更快的替代方法cPickle)。
你可以用同样的方法来使用它。
你可以用同样的方法来使用它。
import pickle
pickled_string = pickle.dumps([1, 2, 3, "a", "b", "c"])
print(pickle.loads(pickled_string))
pickled_string = pickle.dumps([1, 2, 3, "a", "b", "c"])
print(pickle.loads(pickled_string))
是什么
pickle 是 Python 中的一个标准模块,它实现了对象序列化和反序列化的功能。序列化是指将对象(如列表、字典、自定义类的实例等)转换成一个字节流(bytes-like object),以便可以将它们保存到文件中或通过网络传输;反序列化则是将这样的字节流重新转换回 Python 对象。
pickle 模块非常适合用于保存 Python 对象的本地存储,因为它可以处理 Python 中的几乎所有对象类型,包括那些通过用户定义的类创建的实例。然而,由于 pickle 生成的字节流是 Python 特有的,并且可能包含对特定 Python 版本和环境的依赖,因此不建议用于不同 Python 版本或不同环境之间的对象交换,也不建议用于需要高安全性的场合(因为 pickle 加载不受信任的数据时可能会执行恶意代码)。
使用 pickle 模块的基本步骤
序列化(对象 -> 字节流)
python
复制代码
import pickle
# 假设我们有一个对象
data = {'a': [1, 2.0, 3, 4+6j],
'b': ("character string", b"byte string"),
'c': {None, True, False}}
# 序列化对象
with open('data.pickle', 'wb') as f:
pickle.dump(data, f)
反序列化(字节流 -> 对象)
python
复制代码
# 从文件中加载并反序列化对象
with open('data.pickle', 'rb') as f:
data_loaded = pickle.load(f)
print(data_loaded)
注意事项
安全性:如前所述,pickle 加载不受信任的数据源可能会执行恶意代码。因此,在加载来自不可信来源的 pickle 数据时,应格外小心。
版本兼容性:使用 pickle 序列化的数据可能在不同版本的 Python 之间不兼容。
替代方案:对于需要跨平台或跨语言交换数据的场景,考虑使用 JSON、XML 或其他数据交换格式。Python 的 json 模块提供了对 JSON 数据的序列化和反序列化支持,适用于大多数简单的数据交换需求。
pickle 模块非常适合用于保存 Python 对象的本地存储,因为它可以处理 Python 中的几乎所有对象类型,包括那些通过用户定义的类创建的实例。然而,由于 pickle 生成的字节流是 Python 特有的,并且可能包含对特定 Python 版本和环境的依赖,因此不建议用于不同 Python 版本或不同环境之间的对象交换,也不建议用于需要高安全性的场合(因为 pickle 加载不受信任的数据时可能会执行恶意代码)。
使用 pickle 模块的基本步骤
序列化(对象 -> 字节流)
python
复制代码
import pickle
# 假设我们有一个对象
data = {'a': [1, 2.0, 3, 4+6j],
'b': ("character string", b"byte string"),
'c': {None, True, False}}
# 序列化对象
with open('data.pickle', 'wb') as f:
pickle.dump(data, f)
反序列化(字节流 -> 对象)
python
复制代码
# 从文件中加载并反序列化对象
with open('data.pickle', 'rb') as f:
data_loaded = pickle.load(f)
print(data_loaded)
注意事项
安全性:如前所述,pickle 加载不受信任的数据源可能会执行恶意代码。因此,在加载来自不可信来源的 pickle 数据时,应格外小心。
版本兼容性:使用 pickle 序列化的数据可能在不同版本的 Python 之间不兼容。
替代方案:对于需要跨平台或跨语言交换数据的场景,考虑使用 JSON、XML 或其他数据交换格式。Python 的 json 模块提供了对 JSON 数据的序列化和反序列化支持,适用于大多数简单的数据交换需求。
与json相比有哪些优势
在Python中,pickle是一个标准模块,用于对象的序列化和反序列化。序列化是指将Python对象转换为字节流,以便可以将其存储在文件中或通过网络传输;反序列化则是将这些字节流转换回Python对象。
pickle与JSON的区别
特性pickleJSON
数据类型支持支持Python中的几乎所有对象类型,包括自定义对象主要支持字符串、数字、布尔值、数组(列表)、字典(对象)等基本数据类型,对Python自定义对象支持有限
数据格式二进制序列化格式文本序列化格式(通常为UTF-8编码)
可读性不可读(二进制数据)可读(人类可读的文本格式)
语言依赖性Python特有,非Python程序可能无法重建pickle对象跨语言,广泛用于多种编程语言中
安全性加载不受信任的数据时可能执行恶意代码相对安全,因为数据是文本格式,难以隐藏恶意代码
版本兼容性可能在不同Python版本间不兼容跨版本兼容性较好
pickle的优势
广泛的类型支持:
pickle可以处理Python中的几乎所有对象类型,包括自定义类的实例,这为Python对象的持久化和传输提供了极大的便利。
高效的序列化与反序列化:
相较于手动将对象编码为字符串或数组再存储/传输,pickle的dump和load函数提供了更为高效和简便的序列化与反序列化方法。
快速的读取与写入:
在经常存取的场景下,pickle的读取和写入效率较高,特别是对于复杂的数据结构或大型对象。
易于使用:
pickle的API简单直观,使用dump和load函数即可轻松实现对象的序列化和反序列化。
注意事项
尽管pickle具有诸多优势,但由于其生成的字节流是Python特有的,并且可能包含对特定Python版本和环境的依赖,因此不建议用于不同Python版本或不同环境之间的对象交换。
在加载来自不可信来源的pickle数据时,应格外小心,因为可能存在执行恶意代码的风险。
综上所述,pickle是Python中一个强大的对象序列化模块,适用于Python对象的本地存储和传输。然而,在跨语言或跨版本的数据交换中,可能需要考虑使用其他更为通用的数据交换格式,如JSON。
pickle与JSON的区别
特性pickleJSON
数据类型支持支持Python中的几乎所有对象类型,包括自定义对象主要支持字符串、数字、布尔值、数组(列表)、字典(对象)等基本数据类型,对Python自定义对象支持有限
数据格式二进制序列化格式文本序列化格式(通常为UTF-8编码)
可读性不可读(二进制数据)可读(人类可读的文本格式)
语言依赖性Python特有,非Python程序可能无法重建pickle对象跨语言,广泛用于多种编程语言中
安全性加载不受信任的数据时可能执行恶意代码相对安全,因为数据是文本格式,难以隐藏恶意代码
版本兼容性可能在不同Python版本间不兼容跨版本兼容性较好
pickle的优势
广泛的类型支持:
pickle可以处理Python中的几乎所有对象类型,包括自定义类的实例,这为Python对象的持久化和传输提供了极大的便利。
高效的序列化与反序列化:
相较于手动将对象编码为字符串或数组再存储/传输,pickle的dump和load函数提供了更为高效和简便的序列化与反序列化方法。
快速的读取与写入:
在经常存取的场景下,pickle的读取和写入效率较高,特别是对于复杂的数据结构或大型对象。
易于使用:
pickle的API简单直观,使用dump和load函数即可轻松实现对象的序列化和反序列化。
注意事项
尽管pickle具有诸多优势,但由于其生成的字节流是Python特有的,并且可能包含对特定Python版本和环境的依赖,因此不建议用于不同Python版本或不同环境之间的对象交换。
在加载来自不可信来源的pickle数据时,应格外小心,因为可能存在执行恶意代码的风险。
综上所述,pickle是Python中一个强大的对象序列化模块,适用于Python对象的本地存储和传输。然而,在跨语言或跨版本的数据交换中,可能需要考虑使用其他更为通用的数据交换格式,如JSON。
代码自省
是什么
代码自省是检查类、函数和关键字以了解它们是什么、它们做什么以及它们知道什么的能力。
例子
打印给定Vehicle对象的所有属性列表。
# Define the Vehicle class
class Vehicle:
name = ""
kind = "car"
color = ""
value = 100.00
def description(self):
desc_str = "%s is a %s %s worth $%.2f." % (self.name, self.color, self.kind, self.value)
return desc_str
# Print a list of all attributes of the Vehicle class.
print(dir(Vehicle))
/*
<script.py> output:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'description', 'kind', 'name', 'value']
*/
class Vehicle:
name = ""
kind = "car"
color = ""
value = 100.00
def description(self):
desc_str = "%s is a %s %s worth $%.2f." % (self.name, self.color, self.kind, self.value)
return desc_str
# Print a list of all attributes of the Vehicle class.
print(dir(Vehicle))
/*
<script.py> output:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'description', 'kind', 'name', 'value']
*/
闭包 Closures
举例
rase关键字
在Python中,raise 关键字用于引发一个异常。当你想要在你的代码中明确地指示错误发生时,你可以使用 raise 关键字后跟一个异常类(或其实例)来抛出一个异常。这可以让调用者知道在代码的某个地方出现了问题,并可以根据异常的类型和内容来做出相应的处理。
基本用法
引发一个异常类:
你可以直接引发一个异常类,Python会自动为这个异常类创建一个实例。这通常用于标准异常类型,如ValueError、TypeError等。
python
复制代码
raise ValueError("这是一个值错误")
引发一个异常实例:
你也可以先创建异常类的实例,然后使用raise来抛出它。这种方式允许你传递更多的信息给异常对象。
python
复制代码
error = ValueError("这是一个值错误")
raise error
自定义异常
Python允许你定义自己的异常类,这些类应该直接或间接地继承自Exception类(或其子类)。然后,你可以像使用标准异常一样使用这些自定义异常。
python
复制代码
class MyCustomError(Exception):
"""一个简单的自定义异常"""
pass
# 引发自定义异常
raise MyCustomError("这是一个自定义错误")
捕获异常
通常,你会在使用try块中编写可能引发异常的代码,并使用except块来捕获并处理这些异常。
python
复制代码
try:
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理除以零的异常
print("不能除以零")
注意事项
当一个异常被抛出时,Python会中断当前代码块的执行,并查找最近的except块来捕获这个异常。
如果找不到相应的except块,异常将被传递到上一级调用者,直到被捕获或程序终止。
谨慎使用异常来处理程序的控制流,因为它们会使代码更难理解和维护。异常应该用于处理异常情况,而不是正常的控制流逻辑。
基本用法
引发一个异常类:
你可以直接引发一个异常类,Python会自动为这个异常类创建一个实例。这通常用于标准异常类型,如ValueError、TypeError等。
python
复制代码
raise ValueError("这是一个值错误")
引发一个异常实例:
你也可以先创建异常类的实例,然后使用raise来抛出它。这种方式允许你传递更多的信息给异常对象。
python
复制代码
error = ValueError("这是一个值错误")
raise error
自定义异常
Python允许你定义自己的异常类,这些类应该直接或间接地继承自Exception类(或其子类)。然后,你可以像使用标准异常一样使用这些自定义异常。
python
复制代码
class MyCustomError(Exception):
"""一个简单的自定义异常"""
pass
# 引发自定义异常
raise MyCustomError("这是一个自定义错误")
捕获异常
通常,你会在使用try块中编写可能引发异常的代码,并使用except块来捕获并处理这些异常。
python
复制代码
try:
# 尝试执行的代码
result = 10 / 0
except ZeroDivisionError:
# 处理除以零的异常
print("不能除以零")
注意事项
当一个异常被抛出时,Python会中断当前代码块的执行,并查找最近的except块来捕获这个异常。
如果找不到相应的except块,异常将被传递到上一级调用者,直到被捕获或程序终止。
谨慎使用异常来处理程序的控制流,因为它们会使代码更难理解和维护。异常应该用于处理异常情况,而不是正常的控制流逻辑。
装饰器
是什么
装饰器只是另一个函数,它接受一个函数并返回一个函数。类似注解。本质是一个函数。
Python的装饰器是什么?
Python的装饰器(Decorator)是一种特殊的函数,它允许你在不修改原有函数代码的情况下,给函数增加新的功能。装饰器本质上是一个函数,它接收一个函数作为参数并返回一个新的函数。这个新函数是对原函数的一个增强或修改版本。
如何使用装饰器?
使用装饰器通常遵循以下步骤:
定义装饰器函数:这个函数接收一个函数作为参数,并返回一个新的函数。在这个装饰器函数内部,你可以定义任何想要执行的代码,比如日志记录、性能测试、事务处理等。然后,在返回的新函数中调用原函数,并可以添加额外的功能。
使用@符号应用装饰器:在Python中,你可以通过在函数定义之前添加@符号和装饰器名来应用装饰器。这样做会将原函数作为参数传递给装饰器函数,并将装饰器函数返回的新函数赋值给原函数名。
示例
python
复制代码
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello() # 输出将被装饰器修改
装饰器接收参数
如果原函数需要接收参数,你可以在装饰器内部的wrapper函数中定义*args和**kwargs来接收任意数量和类型的参数,并将它们传递给原函数。
python
复制代码
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def add(x, y):
return x + y
print(add(5, 3)) # 输出:8,并且前后有额外的输出
常用于什么场景?
装饰器在Python中非常有用,常用于以下场景:
日志记录:在不修改函数代码的情况下,为函数添加日志记录功能。
性能测试:测量函数的执行时间,以评估其性能。
事务处理:确保一系列数据库操作要么全部成功,要么在发生错误时全部回滚。
缓存:将函数的返回值存储起来,下次以相同参数调用时直接返回缓存结果,以提高效率。
权限校验:在函数执行前校验用户的权限。
功能扩展:在不修改原函数的基础上,给函数添加新的功能。
装饰器是Python中一个非常强大且灵活的特性,它使得代码更加模块化和可重用。
Python的装饰器(Decorator)是一种特殊的函数,它允许你在不修改原有函数代码的情况下,给函数增加新的功能。装饰器本质上是一个函数,它接收一个函数作为参数并返回一个新的函数。这个新函数是对原函数的一个增强或修改版本。
如何使用装饰器?
使用装饰器通常遵循以下步骤:
定义装饰器函数:这个函数接收一个函数作为参数,并返回一个新的函数。在这个装饰器函数内部,你可以定义任何想要执行的代码,比如日志记录、性能测试、事务处理等。然后,在返回的新函数中调用原函数,并可以添加额外的功能。
使用@符号应用装饰器:在Python中,你可以通过在函数定义之前添加@符号和装饰器名来应用装饰器。这样做会将原函数作为参数传递给装饰器函数,并将装饰器函数返回的新函数赋值给原函数名。
示例
python
复制代码
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello() # 输出将被装饰器修改
装饰器接收参数
如果原函数需要接收参数,你可以在装饰器内部的wrapper函数中定义*args和**kwargs来接收任意数量和类型的参数,并将它们传递给原函数。
python
复制代码
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def add(x, y):
return x + y
print(add(5, 3)) # 输出:8,并且前后有额外的输出
常用于什么场景?
装饰器在Python中非常有用,常用于以下场景:
日志记录:在不修改函数代码的情况下,为函数添加日志记录功能。
性能测试:测量函数的执行时间,以评估其性能。
事务处理:确保一系列数据库操作要么全部成功,要么在发生错误时全部回滚。
缓存:将函数的返回值存储起来,下次以相同参数调用时直接返回缓存结果,以提高效率。
权限校验:在函数执行前校验用户的权限。
功能扩展:在不修改原函数的基础上,给函数添加新的功能。
装饰器是Python中一个非常强大且灵活的特性,它使得代码更加模块化和可重用。
如何使用
例子
假设你想把输出乘以一个变量。你可以定义这个装饰器,并像下面这样使用它:
def multiply(multiplier):
def multiply_generator(old_function):
def new_function(*args, **kwds):
return multiplier * old_function(*args, **kwds)
return new_function
return multiply_generator # it returns the new generator
# Usage
@multiply(3) # multiply is not a generator, but multiply(3) is
def return_num(num):
return num
# Now return_num is decorated and reassigned into itself
return_num(5) # should return 15
def multiply_generator(old_function):
def new_function(*args, **kwds):
return multiplier * old_function(*args, **kwds)
return new_function
return multiply_generator # it returns the new generator
# Usage
@multiply(3) # multiply is not a generator, but multiply(3) is
def return_num(num):
return num
# Now return_num is decorated and reassigned into itself
return_num(5) # should return 15
入参类型检查
def type_check(correct_type):
def decorator(old_function):
def new_function(arg):
if(isinstance(arg,correct_type)):
return old_function(arg)
else:
print('Bad Type')
return new_function
return decorator
@type_check(int)
def times2(num):
return num*2
print(times2(2))
times2('Not A Number')
@type_check(str)
def first_letter(word):
return word[0]
print(first_letter('Hello World'))
first_letter(['Not', 'A', 'String'])
def decorator(old_function):
def new_function(arg):
if(isinstance(arg,correct_type)):
return old_function(arg)
else:
print('Bad Type')
return new_function
return decorator
@type_check(int)
def times2(num):
return num*2
print(times2(2))
times2('Not A Number')
@type_check(str)
def first_letter(word):
return word[0]
print(first_letter('Hello World'))
first_letter(['Not', 'A', 'String'])
Map, Filter, and Reduce
映射器 Map map(func, *iterables)
是什么
函数变成的范例
如何使用
例子
已知宠物名字的的列表,使所有名字变成大写
传统方法
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = []
for pet in my_pets:
pet_ = pet.upper()
uppered_pets.append(pet_)
print(uppered_pets)
uppered_pets = []
for pet in my_pets:
pet_ = pet.upper()
uppered_pets.append(pet_)
print(uppered_pets)
函数式编程
使用map()函数不仅更简单,而且更加灵活。我只是这样做:
# Python 3
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = list(map(str.upper, my_pets))
print(uppered_pets)
my_pets = ['alfred', 'tabitha', 'william', 'arla']
uppered_pets = list(map(str.upper, my_pets))
print(uppered_pets)
把列表中的第一个元素四舍五入到小数点后一位,第二个元素四舍五入到小数点后两位,第三个元素四舍五入到小数点后三位,以此类推。使用map(),这是小菜一碟。让我们看看怎么做。
# Python 3
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 7)))
print(result) // [3.6, 5.58, 4.009, 56.2424, 9.01344, 32.00013]
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 7)))
print(result) // [3.6, 5.58, 4.009, 56.2424, 9.01344, 32.00013]
如果两个列表长度不一样怎么办?按照短的来,不会报错
# Python 3
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 3)))
print(result) // [3.6, 5.58]
circle_areas = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1, 3)))
print(result) // [3.6, 5.58]
两个列表变成元组
my_strings = ['a', 'b', 'c', 'd', 'e']
my_numbers = [1, 2, 3, 4, 5]
results = list(map(lambda x, y: (x, y), my_strings, my_numbers))
print(results)
my_numbers = [1, 2, 3, 4, 5]
results = list(map(lambda x, y: (x, y), my_strings, my_numbers))
print(results)
过滤器 Filter filter(func, iterable)
例子
下面是10个学生在化学考试中的分数列表(可迭代)。让我们过滤出(找出)那些分数超过75分的人……使用过滤器。
# Python 3
scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65]
def is_A_student(score):
return score > 75
over_75 = list(filter(is_A_student, scores))
print(over_75) // [90, 76, 88, 81]
scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65]
def is_A_student(score):
return score > 75
over_75 = list(filter(is_A_student, scores))
print(over_75) // [90, 76, 88, 81]
下一个示例是一个回文检测器。“回文”是一个单词、短语或序列,向后读和向前读是一样的。让我们从可疑的回文元组(iterable)中过滤出属于回文的单词。
# Python 3
dromes = ("demigod", "rewire", "madam", "freer", "anutforajaroftuna", "kiosk")
palindromes = list(filter(lambda word: word == word[::-1], dromes))
print(palindromes) // ['madam', 'anutforajaroftuna']
print(dromes[0][::-1])//反转字符串 牛逼
dromes = ("demigod", "rewire", "madam", "freer", "anutforajaroftuna", "kiosk")
palindromes = list(filter(lambda word: word == word[::-1], dromes))
print(palindromes) // ['madam', 'anutforajaroftuna']
print(dromes[0][::-1])//反转字符串 牛逼
归约操作 Reduce
声明
reduce(func, iterable[, initial])
func 两个入参的衰减函数
func 两个入参的衰减函数
例子
创建自己版本的Python内置sum()函数。sum()函数返回传递给它的可迭代对象中所有项的和
# Python 3
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers)
print(result) //68
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers)
print(result) //68
通常,这都是关于迭代的:reduce接受数字中的第一个和第二个元素,并将它们分别传递给custom_sum。Custom_sum计算它们的和并返回给reduce。然后Reduce获取该结果并将其作为custom_sum的第一个元素,并将数字中的下一个元素(第三个)作为custom_sum的第二个元素。它连续地(累积地)这样做,直到耗尽数字。
上边的例子设置初始值10
# Python 3
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers, 10)
print(result) // 78
from functools import reduce
numbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, numbers, 10)
print(result) // 78
zip(list1,list2)
是什么:将对应的列表元素打包成元组
Python 中的 zip() 方法是一个内置函数,用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象(在 Python 3 中,返回的是一个迭代器,而在 Python 2 中,返回的是一个列表)。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 操作符,可以将元组解压为列表。
基本使用
假设我们有两个列表,我们想要将它们对应位置的元素组合在一起:
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
# 使用zip()函数
zipped = zip(list1, list2)
# 将zip对象转换为列表
zip_list = list(zipped)
print(zip_list)
# 输出: [(1, 'a'), (2, 'b'), (3, 'c')]
解压zip对象
如果你想将zip对象中的元素解压到多个变量或列表中,你可以使用 * 操作符(在Python 3中)。
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
zipped = zip(list1, list2)
a, b = zip(*zipped) # 注意,这里a和b是元组的元组,需要进一步转换
# 因为zip(*zipped)返回的是元组的元组,我们需要转换为列表
a, b = list(a), list(b)
print(a)
# 输出: [1, 2, 3]
print(b)
# 输出: ['a', 'b', 'c']
# 或者直接解压到变量中(如果知道确切的个数)
x, y, z = zip(*zip(list1, list2))[0]
print(x, y, z)
# 输出: 1 a 3 注意:这里z是list2的第二个元素'b'之前的元素,因为zip*的行为是转置
# 正确的解压到三个变量
x, y, z = zip(*zip(list1, list2))[0][:3] # 但这实际上是多余的,因为我们已经知道长度
x, y, z = list(zip(*zip(list1, list2)))[0] # 更正确的做法,直接获取第一个元组
print(x, y, z)
# 输出: 1 a c
注意:zip(*zipped) 的行为实际上是将原始的zip对象“转置”了。如果原始的zip对象包含多个元组,且每个元组的元素数量相同,zip(*zipped) 将返回一个新的zip对象,其中元组的顺序与原始zip对象中的元素顺序相反(但在这个例子中,由于我们只有一个zip对象,所以结果看起来像是“解包”了原始列表)。
与循环结合使用
zip() 也可以与循环结合使用,来同时遍历多个序列。
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
for item1, item2 in zip(list1, list2):
print(item1, item2)
# 输出:
# 1 a
# 2 b
# 3 c
这种用法在处理具有相关数据的多个列表时特别有用。
基本使用
假设我们有两个列表,我们想要将它们对应位置的元素组合在一起:
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
# 使用zip()函数
zipped = zip(list1, list2)
# 将zip对象转换为列表
zip_list = list(zipped)
print(zip_list)
# 输出: [(1, 'a'), (2, 'b'), (3, 'c')]
解压zip对象
如果你想将zip对象中的元素解压到多个变量或列表中,你可以使用 * 操作符(在Python 3中)。
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
zipped = zip(list1, list2)
a, b = zip(*zipped) # 注意,这里a和b是元组的元组,需要进一步转换
# 因为zip(*zipped)返回的是元组的元组,我们需要转换为列表
a, b = list(a), list(b)
print(a)
# 输出: [1, 2, 3]
print(b)
# 输出: ['a', 'b', 'c']
# 或者直接解压到变量中(如果知道确切的个数)
x, y, z = zip(*zip(list1, list2))[0]
print(x, y, z)
# 输出: 1 a 3 注意:这里z是list2的第二个元素'b'之前的元素,因为zip*的行为是转置
# 正确的解压到三个变量
x, y, z = zip(*zip(list1, list2))[0][:3] # 但这实际上是多余的,因为我们已经知道长度
x, y, z = list(zip(*zip(list1, list2)))[0] # 更正确的做法,直接获取第一个元组
print(x, y, z)
# 输出: 1 a c
注意:zip(*zipped) 的行为实际上是将原始的zip对象“转置”了。如果原始的zip对象包含多个元组,且每个元组的元素数量相同,zip(*zipped) 将返回一个新的zip对象,其中元组的顺序与原始zip对象中的元素顺序相反(但在这个例子中,由于我们只有一个zip对象,所以结果看起来像是“解包”了原始列表)。
与循环结合使用
zip() 也可以与循环结合使用,来同时遍历多个序列。
python
复制代码
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
for item1, item2 in zip(list1, list2):
print(item1, item2)
# 输出:
# 1 a
# 2 b
# 3 c
这种用法在处理具有相关数据的多个列表时特别有用。
如何使用
举例
参考:https://www.learnpython.org
其他
认证考试
https://www.learnx.org
0 条评论
下一页