Python基础
基本用法
最简单的 print 用法是输出一个字符串:
print("Hello, World!")
输出:
Hello, World!
打印多个值
print 可以打印多个值,默认情况下它们之间用空格分隔:
print("Hello", "World", 123)
输出:
Hello World 123
输出不同类型的数据
print 可以输出各种类型的数据,包括字符串、整数、浮点数、布尔值等:
print("String:", "example", "Integer:", 10, "Float:", 10.5, "Boolean:", True)
输出:
String: example Integer: 10 Float: 10.5 Boolean: True
参数详解
print 函数有几个可选参数:
sep: 指定分隔符,默认是空格。end: 指定结束字符,默认是换行符。file: 指定输出的文件对象,默认是sys.stdout(标准输出)。flush: 指定是否立即刷新输出缓冲区,默认是False。
sep 参数
sep 参数用于指定打印多个值时的分隔符:
print("Hello", "World", sep="-")
输出:
Hello-World
end 参数
end 参数用于指定打印结束后的字符,默认是换行符 \n:
print("Hello", end="")
print("World")
输出:
HelloWorld
print("Hello", "World", sep="-", end="!")
输出:
Hello-World!
file 参数
file 参数用于指定输出的目标,可以是一个文件对象:
open("output.txt", "w"):以写模式 ("w") 打开文件。如果文件不存在,会创建一个新文件;如果文件已经存在,会清空文件内容并重新写入。as f:将打开的文件对象赋值给变量f。在with代码块内,可以通过f访问文件对象。file=f表示print的输出将直接写入到f所指向的文件output.txt中,而不是默认的标准输出(通常是终端或控制台)。
with open("output.txt", "w") as f:
print("Hello, World!", file=f)
这会将 “Hello, World!” 写入 output.txt 文件中。
flush 参数
flush 参数用于指定是否立即刷新输出缓冲区:
import time
print("Loading", end="", flush=True)
time.sleep(1)
print(".", end="", flush=True)
time.sleep(1)
print(".", end="", flush=True)
time.sleep(1)
print(".")
输出:
Loading...
格式化输出
print 函数支持多种字符串格式化方法,包括 % 操作符、str.format 方法和 f-strings(格式化字符串字面量)。
使用 % 操作符
name = "Alice"
age = 30
print("Name: %s, Age: %d" % (name, age))
输出:
Name: Alice, Age: 30
使用 str.format 方法
name = "Bob"
age = 25
print("Name: {}, Age: {}".format(name, age))
输出:
Name: Bob, Age: 25
使用 f 字符串(Python 3.6+)
name = "Charlie"
age = 35
print(f"Name: {name}, Age: {age}")
输出:
Name: Charlie, Age: 35
常见示例
打印列表
my_list = [1, 2, 3, 4, 5]
print("My list:", my_list)
输出:
My list: [1, 2, 3, 4, 5]
打印字典
my_dict = {"name": "Alice", "age": 30}
print("My dictionary:", my_dict)
输出:
My dictionary: {'name': 'Alice', 'age': 30}
_
占位符(Placeholder)
当你在循环、解包或其他操作中不需要使用某个变量时,可以使用 _ 作为占位符。这是一种告诉读者和解释器该变量不重要的惯例。
示例:
for _ in range(5):
print("Hello")
range(5)生成了一个包含 5 个整数的可迭代对象。for _ in range(5):这个循环会执行 5 次,但循环变量_在循环体内没有被使用。- 这种写法表明循环变量的值对代码逻辑并不重要,循环体只需要执行一定次数的操作。
解包时的占位符
在解包操作中,_ 可以用来忽略某些值。例如,当你只对部分数据感兴趣时,可以使用 _ 忽略其余的值。
示例:
a, _, c = (1, 2, 3)
print(a) # 输出: 1
print(c) # 输出: 3
a, _ = (1, 2)将元组(1, 2)中的第一个值分配给a,第二个值被分配给_。- 这里
_被用作一个占位符,因为第二个值不需要使用。
交互式解释器中的临时变量
在 Python 的交互式解释器(REPL)中,_ 用来保存上一个计算的结果。每次执行计算,_ 都会被更新为最近一次计算的结果。
示例:
>>> 2 + 3
5
>>> _ * 2
10
2 + 3计算结果是5。_现在存储了上一个计算的结果(即5)。_ * 2计算5 * 2,得到10。
作为国际化(i18n)函数的别名
在国际化(i18n)库中,_ 经常用作翻译函数的别名。这种用法在翻译函数中非常常见,目的是简化函数调用。
示例:
from gettext import gettext as _
print(_("Hello, World!"))
gettext是一个函数,用于翻译字符串。gettext as _将gettext函数重命名为_,使得代码中更简洁地使用翻译功能。_('Hello, world!')将字符串'Hello, world!'翻译成用户的本地语言。
作为不变的变量名
在某些情况下,_ 被用作不变的变量名,表示这个变量的值不应被修改。这种用法虽然不常见,但在一些代码规范中有可能出现。
在函数参数中
在定义函数时,_ 可以作为函数参数的占位符,表示该参数不被使用。
示例:
def func(a, _):
print(a)
func(1, 2) # 输出: 1
这里的 _ 作为第二个参数的占位符,表示函数不使用它的值。
变化的量
- 单引号
'和 双引号":在定义单行字符串时可以互换使用。选择哪种引号取决于字符串内容以及个人习惯。 - 三引号
'''或""":用于定义多行字符串或文档字符串(docstring),能够保留多行文本的格式。
单引号和双引号
单引号和双引号都可以用来定义字符串,且功能完全一样。选择哪种引号通常取决于个人喜好或字符串中包含的引号类型。
示例
# 使用单引号
single_quoted_string = 'Hello, World!'
# 使用双引号
double_quoted_string = "Hello, World!"
使用引号的注意事项
-
包含引号的字符串:
-
如果字符串中包含单引号,建议使用双引号来定义字符串,以避免转义字符。
string_with_single_quote = "It's a sunny day." -
如果字符串中包含双引号,建议使用单引号来定义字符串。
string_with_double_quote = 'He said, "Hello!"'
-
-
转义字符:如果必须在字符串中包含与定义字符串的引号相同的类型,可以使用转义字符
\。使用转义字符
\可以避免语法错误\":在双引号字符串中插入双引号。\n:插入换行符。\t:插入制表符。\\:插入反斜杠本身。
# 字符串中包含单引号 string_with_escaped_single_quote = 'It\'s a sunny day.' # 输出: It's a sunny day. # 字符串中包含双引号 string_with_escaped_double_quote = "He said, \"Hello!\"" # 输出: He said, "Hello!" # 字符串中包含换行符和制表符 string_with_escape_sequences = "Line 1\nLine 2\n\tIndented Line 3" 输出: Line 1 Line 2 Indented Line 3 # 字符串中包含反斜杠 string_with_backslash = "Path to file: C:\\Users\\Name" # 输出: Path to file: C:\Users\Name
三引号(单引号三引号和双引号三引号)
三引号(无论是单引号还是双引号)用于定义多行字符串或文档字符串(docstring)。
单引号三引号
single_quoted_multiline_string = '''This is a string
that spans multiple lines. You can use single quotes
and preserve the formatting.'''
输出:
This is a string
that spans multiple lines. You can use single quotes
and preserve the formatting.
双引号三引号
double_quoted_multiline_string = """This is another string
that spans multiple lines. You can use double quotes
and preserve the formatting."""
输出:
This is another string
that spans multiple lines. You can use double quotes
and preserve the formatting.
使用场景
-
多行字符串:三引号特别适合用于多行字符串,能够保留字符串中的换行符和空格。
multiline_string = """This is a string that spans multiple lines. It preserves line breaks and spaces.""" 输出: This is a string that spans multiple lines. It preserves line breaks and spaces. -
文档字符串(Docstring) :三引号常用于函数、类和模块的文档字符串,用于提供函数或类的说明文档。
def my_function(): """ This is a docstring that describes the function's purpose and behavior. """ pass
数学运算
| 运算符 | 描述 | 例子 |
|---|---|---|
| + | 加 | 3+4=7 |
| - | 减 | 3-4=-1 |
| * | 乘 | 3*4=12 |
| / | 除 | 3/2=1.5 |
| % | 取模 | 103%100=3 |
| ** | 幂 | 3**2=9 |
| // | 取整除 | 10//3=3 |
条件判断
if 如果
in_trash = True
if in_trash:
print("可以被彻底删除")
输出:可以被彻底删除
in_trash = True
if not in_trash:
print("不可以被彻底删除")
输出:无结果
if-else 如果否则
in_trash = True
if in_trash:
print("可以被彻底删除")
else:
print("不可以被彻底删除")
输出:可以被彻底删除
判断条件
| 判断 | 含义 |
|---|---|
| a == b | a 是否等于 b |
| a > b | a 是否大于 b |
| a >= b | a 是否大于等于 b |
| a < b | a 是否小于 b |
| a <= b | a 是否小于等于 b |
| a != b | a 是否不等于 b |
a, b = "文件1", "文件2"
a == b
输出:false
print("2 < 3", 2 < 3)
print("3 < 2", 3 < 2)
print("2 != 2", 2 != 2)
输出:
2 < 3 True
3 < 2 False
2 != 2 False
| 判断 | 含义 |
|---|---|
| True and True | 需要两边同时满足才能返回 True |
| True or False | 只要一边是 True 则返回 True |
| not True | 给出相反结果 |
a, b = 1, 2
if a > b:
print("a 大于 b")
else:
print("a 不大于 b")
输出:a 不大于 b
if-elif-else
today = 4
if today == 1:
print("周一")
elif today == 2:
print("周二")
elif today == 3:
print("周三")
else:
print("周一周二周三之外的一天")
输出:周一周二周三之外的一天
for 循环
使用 range 函数
range 函数常用于生成一系列的数字,这些数字可以用来控制循环的次数:
range(5)生成一个从 0 到 4 的整数序列
range 函数常用于生成一系列的数字,这些数字可以用来控制循环的次数:
for i in range(5):
print(i)
输出:
0
1
2
3
4
range(2, 6)生成一个从 2 到 5 的整数序列
for i in range(2, 6):
print(i)
输出:
2
3
4
5
range(0, 10, 2)生成一个从 0 到 9 的偶数序列
for i in range(0, 10, 2):
print(i)
输出:
0
2
4
6
8
遍历字典
字典的遍历可以通过遍历其键、值或键值对:
-
遍历键:
person = {"name": "Alice", "age": 30} for key in person: print(key)输出:
name age -
遍历值:
person = {"name": "Alice", "age": 30} for value in person.values(): print(value)输出:
Alice 30 -
遍历键值对:
person.items()返回一个包含字典所有键值对的视图对象,每个键值对都是一个二元组(key, value)。for key, value in person.items()语句使用了两个变量key和value来分别接收这些键值对中的键和值。print(f"{key}: {value}")使用了 f-string 来格式化字符串。f"{key}: {value}"表达式将当前的key和value插入到字符串中。
person = {"name": "Alice", "age": 30} for key, value in person.items(): print(f"{key}: {value}")输出:
name: Alice age: 30
列表推导式
列表推导式是一种使用 for 循环的简洁方式,用于生成新列表:
squares = [x**2 for x in range(10)]
print(squares)
输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
在这个示例中,[x**2 for x in range(10)] 使用 for 循环生成了一个包含 0 到 9 的平方的新列表。
嵌套 for 循环
for 循环可以嵌套以处理更复杂的情况:
for i in range(3):
for j in range(3):
print(f"i={i}, j={j}")
输出:
i=0, j=0
i=0, j=1
i=0, j=2
i=1, j=0
i=1, j=1
i=1, j=2
i=2, j=0
i=2, j=1
i=2, j=2
在这个示例中,内层 for 循环在每次外层 for 循环的迭代中都会执行。
for 循环的控制语句
-
break:跳出当前循环,结束整个循环体的执行。for i in range(5): if i == 3: break print(i)输出:
0 1 2 -
continue:跳过当前迭代,继续执行下一次循环。for i in range(5): if i == 3: continue print(i)输出:
0 1 2 4 -
else:for循环后可以跟else语句,它会在循环正常结束时执行(没有遇到break)。for i in range(5): print(i) else: print("Loop finished.")输出:
0 1 2 3 4 Loop finished.
While 循环
基本示例
count = 0
while count < 5:
print(count)
count += 1
输出:
0
1
2
3
4
在这个示例中,count 从 0 开始,直到它等于 5。每次循环中,count 的值都会增加 1,直到条件 count < 5 为 False。
无限循环
如果 while 循环的条件始终为 True,则会导致无限循环。要退出无限循环,你可以使用 break 语句:
while True:
response = input("Type 'exit' to quit: ")
if response == 'exit':
print("Exiting the program.")
break
print("You typed:", response)
input() 函数显示提示信息并等待用户输入。
input("Type 'exit' to quit: ") 显示提示信息 "Type 'exit' to quit: ",并等待用户输入。用户输入的内容会被存储在变量 response 中。
这个循环会持续运行,直到用户输入 'exit'。
控制语句
-
break:立即退出循环,不再执行循环体中的其他代码。count = 0 while True: if count == 3: break print(count) count += 1输出:
0 1 2 -
continue:跳过当前循环的剩余部分,直接开始下一次循环。count = 0 while count < 5: count += 1 if count == 3: continue print(count)输出:
1 2 4 5在这个示例中,当
count等于 3 时,continue语句会跳过print(count),所以3不会被打印。 -
else:while循环可以跟一个else语句块,它会在循环正常结束时(没有遇到break)执行。count = 0 while count < 5: print(count) count += 1 else: print("Loop finished.")输出:
0 1 2 3 4 Loop finished.在这个示例中,当
count达到 5 时,循环结束,else部分的代码执行。
使用 while 循环处理用户输入
while 循环常用于处理需要不断获取用户输入的情况,直到满足特定条件:
while True:
number = input("Enter a number (or 'q' to quit): ")
if number == 'q':
print("Exiting the program.")
break
try:
number = int(number)
print(f"You entered: {number}")
except ValueError:
print("Invalid input. Please enter a number or 'q' to quit.")
这个示例会持续获取用户输入,直到用户输入 'q'。如果输入的是有效数字,则打印该数字;如果输入无效,则提示错误信息。
数据种类
List 列表
list(列表)是一种内置的数据结构,用于存储多个项目。列表是可变的,可以包含不同类型的元素,并且支持多种操作,如添加、删除、排序等。
创建列表
你可以使用方括号 [] 来创建一个列表。列表中的元素可以是任意类型,包括数字、字符串、其他列表等。
# 创建一个空列表
empty_list = []
# 创建一个包含不同数据类型的列表
mixed_list = [1, 2.5, "Hello", True]
# 创建一个嵌套列表
nested_list = [1, [2, 3], [4, [5, 6]]]
提取列表的子列表
-
切片基本格式:
list[start:stop]提取从索引start到stop之前的元素。start是起始索引,stop是结束索引(不包括stop)。- 切片操作:
[:3]是一个切片操作,表示从列表的开始位置(索引0)到索引3之前的位置(即索引3的前一个位置)的所有元素。切片的结束索引是不包含的。
- 切片操作:
-
省略
start或stop:[:stop]从开头到stop之前的位置。[start:]从start到列表末尾。- 切片操作:
[2:4]表示从索引2开始,到索引4之前的位置的所有元素。切片的结束索引是不包含的。
-
负索引:使用负索引可以从列表末尾向前访问元素。例如,
[-1]代表最后一个元素,[-2]代表倒数第二个元素。- 切片操作:
[-3:]表示从倒数第 3 个位置开始,一直到列表的结束。负索引从列表的末尾向前计数,-1是最后一个元素,-2是倒数第二个元素,以此类推。
- 切片操作:
files = ["file1", "file2", "file3", "file4", "file5"]
print("files[:3] ", files[:3])
print("files[2:4] ", files[2:4])
print("files[-3:] ", files[-3:])
输出:
files[:3] ['f1.txt', 'f2.txt', 'f3.txt']
files[2:4] ['f3.txt', 'f4.txt']
files[-3:] ['f3.txt', 'f4.txt', 'f5.txt']
访问和修改列表
访问元素
使用索引来访问列表中的元素。索引从 0 开始。
my_list = ["apple", "banana", "cherry"]
# 访问第一个元素
print(my_list[0]) # 输出: apple
# 访问最后一个元素
print(my_list[-1]) # 输出: cherry
修改元素
你可以通过索引来修改列表中的元素。
my_list = ["apple", "banana", "cherry"]
# 修改第一个元素
my_list[0] = "orange"
print(my_list) # 输出: ['orange', 'banana', 'cherry']
嵌套列表中修改元素
l = [1, "file", ["2", 3.2]]
print(l)
l[2][0] = "new string"
print(l)
输出:
[1, 'file', ['2', 3.2]]
[1, 'file', ['new string', 3.2]]
l[2]:这部分访问列表l中的第三个元素(索引2),它是嵌套的列表["2", 3.2]。l[2][0]:进一步访问嵌套列表中的第一个元素(索引0),即"2"。- 赋值操作:将
"2"修改为"new string",所以现在嵌套列表变为["new string", 3.2]。
常用列表操作
添加元素
-
append():在列表末尾添加一个元素。my_list = [1, 2, 3] my_list.append(4) print(my_list) # 输出: [1, 2, 3, 4] -
extend():将一个可迭代对象(如另一个列表)中的所有元素添加到列表末尾。my_list = [1, 2, 3] my_list.extend([4, 5]) print(my_list) # 输出: [1, 2, 3, 4, 5] -
insert():在指定位置插入一个元素。my_list = [1, 2, 3] my_list.insert(1, "a") print(my_list) # 输出: [1, 'a', 2, 3]
删除元素
-
remove():删除第一个匹配的元素。my_list = [1, 2, 3, 2] my_list.remove(2) print(my_list) # 输出: [1, 3, 2] -
pop():删除并返回指定位置的元素。如果不指定位置,则删除并返回最后一个元素。my_list = [1, 2, 3] item = my_list.pop() print(item) # 输出: 3 print(my_list) # 输出: [1, 2] # 删除指定位置的元素 item = my_list.pop(0) print(item) # 输出: 1 print(my_list) # 输出: [2] -
clear():删除列表中的所有元素。my_list = [1, 2, 3] my_list.clear() print(my_list) # 输出: []
查找元素
-
index():返回第一个匹配元素的索引。my_list = [1, 2, 3] index = my_list.index(2) print(index) # 输出: 1 -
count():返回指定元素在列表中出现的次数。my_list = [1, 2, 2, 3] count = my_list.count(2) print(count) # 输出: 2
排序
-
sort():原地排序列表。my_list = [3, 1, 2] my_list.sort() print(my_list) # 输出: [1, 2, 3] -
sorted():返回一个新的排序后的列表,不修改原列表。my_list = [3, 1, 2] sorted_list = sorted(my_list) print(sorted_list) # 输出: [1, 2, 3] print(my_list) # 输出: [3, 1, 2] (原列表不变) -
reverse():原地反转列表的顺序。my_list = [1, 2, 3] my_list.reverse() print(my_list) # 输出: [3, 2, 1]
列表推导式
列表推导式是生成列表的一种简洁方法:
# 创建一个包含 0 到 9 的平方数的列表
squares = [x**2 for x in range(10)]
print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
列表的嵌套
列表可以嵌套:
nested_list = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 访问嵌套列表的元素
print(nested_list[0][1]) # 输出: 2
Dict 字典
dict(字典)是一种内置的数据结构,用于存储键值对(key-value pairs) 。字典是一种无序的数据集合,其中每个键(key)都是唯一的,且可以通过键来快速访问对应的值(value)。
创建字典
字典的基本语法是使用花括号 {} 包含键值对,键和值之间用冒号 : 分隔,键值对之间用逗号 , 分隔。
# 创建一个空字典
empty_dict = {}
# 创建一个包含数据的字典
person = {
"name": "Alice",
"age": 30,
"city": "New York"
}
访问字典中的值
使用键来访问字典中的值:
person = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 访问字典中的值
print(person["name"]) # 输出: Alice
print(person["age"]) # 输出: 30
修改字典中的值
通过键来修改字典中的值:
person = {
"name": "Alice",
"age": 30,
"city": "New York"
}
# 修改字典中的值
person["age"] = 31
print(person["age"]) # 输出: 31
添加键值对
向字典中添加新的键值对:
person = {
"name": "Alice",
"age": 30
}
# 添加新的键值对
person["city"] = "New York"
print(person) # 输出: {'name': 'Alice', 'age': 30, 'city': 'New York'}
删除键值对
-
使用
del语句:删除指定键的键值对。person = { "name": "Alice", "age": 30, "city": "New York" } del person["city"] print(person) # 输出: {'name': 'Alice', 'age': 30} -
使用
pop()方法:删除指定键的键值对,并返回对应的值。如果键不存在,pop()方法可以指定默认值。person = { "name": "Alice", "age": 30, "city": "New York" } city = person.pop("city", "Unknown") print(city) # 输出: New York print(person) # 输出: {'name': 'Alice', 'age': 30}
遍历字典
-
遍历键:
person = { "name": "Alice", "age": 30, "city": "New York" } for key in person: print(key, ":", person[key]) 输出: name : Alice age : 30 city : New York -
遍历值:
person = { "name": "Alice", "age": 30, "city": "New York" } for value in person.values(): print(value) -
遍历键值对:
person = { "name": "Alice", "age": 30, "city": "New York" } for key, value in person.items(): print(key, ":", value)
字典方法
-
get(key, default):返回指定键的值,如果键不存在,则返回default(如果未提供default,则返回None)。person = { "name": "Alice", "age": 30 } print(person.get("city", "Unknown")) # 输出: Unknown -
keys():返回字典中所有键的视图。person = { "name": "Alice", "age": 30 } print(person.keys()) # 输出: dict_keys(['name', 'age']) -
values():返回字典中所有值的视图。person = { "name": "Alice", "age": 30 } print(person.values()) # 输出: dict_values(['Alice', 30]) -
items():返回字典中所有键值对的视图。person = { "name": "Alice", "age": 30 } print(person.items()) # 输出: dict_items([('name', 'Alice'), ('age', 30)]) -
update(other_dict):将other_dict中的键值对更新到当前字典中。如果有相同的键,则会覆盖原来的值。person = { "name": "Alice", "age": 30 } additional_info = { "city": "New York", "age": 31 } person.update(additional_info) print(person) # 输出: {'name': 'Alice', 'age': 31, 'city': 'New York'} -
clear():清空字典中的所有键值对。person = { "name": "Alice", "age": 30 } person.clear() print(person) # 输出: {}
Tuple 元组
tuple(元组)是一种内置的数据结构,用于存储多个项目。与列表类似,元组可以包含多个元素,但有几个关键的不同点:
- 不可变性:元组一旦创建,就不能修改(即不可变)。这意味着不能添加、删除或修改元组中的元素。
- 定义:元组使用圆括号
()来创建,而列表使用方括号[]。
创建元组
元组的基本语法是使用圆括号 () 包含元素,元素之间用逗号 , 分隔。也可以省略圆括号,仅使用逗号来定义单元素元组。
# 创建一个空元组
empty_tuple = ()
# 创建一个包含多个元素的元组
my_tuple = (1, "hello", 3.14, [1, 2, 3])
# 创建一个单元素元组(注意逗号)
single_element_tuple = (1,)
# 创建一个没有圆括号的元组(Python 会自动识别)
auto_tuple = 1, "hello", 3.14
# 创建一个嵌套元组
nested_tuple = (1, (2, 3), (4, (5, 6)))
访问元组中的元素
使用索引访问元组中的元素,索引从 0 开始。
my_tuple = (1, "hello", 3.14, [1, 2, 3])
# 访问第一个元素
print(my_tuple[0]) # 输出: 1
# 访问最后一个元素
print(my_tuple[-1]) # 输出: [1, 2, 3]
# 访问嵌套元组中的元素
print(my_tuple[3][1]) # 输出: 2 (访问的是内嵌列表中的第二个元素)
元组的操作
尽管元组是不可变的,但你仍然可以执行以下操作:
-
连接元组:使用
+运算符将两个元组连接在一起。tuple1 = (1, 2, 3) tuple2 = (4, 5, 6) combined = tuple1 + tuple2 print(combined) # 输出: (1, 2, 3, 4, 5, 6) -
重复元组:使用
*运算符重复元组。my_tuple = (1, 2, 3) repeated = my_tuple * 3 print(repeated) # 输出: (1, 2, 3, 1, 2, 3, 1, 2, 3) -
切片:和列表一样,元组也支持切片操作。
my_tuple = (1, 2, 3, 4, 5) sliced = my_tuple[1:4] print(sliced) # 输出: (2, 3, 4)
元组的应用
元组在实际编程中有广泛的应用:
- 不可变数据:用来存储不需要修改的数据,例如函数的返回值。
- 作为字典的键:由于元组是不可变的,可以用作字典的键,而列表则不能。
- 数据分组:用来将多个相关的数据项打包在一起,例如函数的多个返回值。
元组的内置方法
元组提供了以下几种方法:
-
count(value):返回元组中value出现的次数。my_tuple = (1, 2, 3, 1, 1) count_ones = my_tuple.count(1) print(count_ones) # 输出: 3 -
index(value, [start, end]):返回value在元组中第一次出现的索引。如果指定了start和end,则在这个范围内查找。my_tuple = (1, 2, 3, 1, 1) index_of_two = my_tuple.index(2) print(index_of_two) # 输出: 1
Set 合集
set(集合)是一种内置的数据结构,用于存储不重复的元素。集合是无序的,不允许重复的元素,并且支持多种数学集合运算,如并集、交集、差集等
创建集合
集合的基本语法是使用花括号 {} 或 set() 函数。请注意,空集合必须使用 set() 函数创建,因为 {} 被解释为一个空字典。
# 创建一个空集合
empty_set = set()
# 创建一个包含多个元素的集合
my_set = {1, 2, 3, 4, 5}
# 使用 set() 函数创建集合
another_set = set([1, 2, 3, 4, 5])
集合的特性
- 无序:集合中的元素是无序的,不能通过索引来访问集合中的元素。
- 唯一性:集合中的元素是唯一的,重复的元素会被自动移除。
访问集合
由于集合是无序的,不能通过索引访问集合中的元素。但可以使用循环来遍历集合中的元素。
my_set = {1, 2, 3, 4, 5}
# 遍历集合
for item in my_set:
print(item)
添加和删除元素
-
添加元素:使用
add()方法添加单个元素。my_set = {1, 2, 3} my_set.add(4) print(my_set) # 输出: {1, 2, 3, 4} -
添加多个元素:使用
update()方法添加多个元素。update()方法接受一个可迭代对象(如列表、元组等)。my_set = {1, 2, 3} my_set.update([4, 5, 6]) print(my_set) # 输出: {1, 2, 3, 4, 5, 6} -
删除元素:使用
remove()或discard()方法删除元素。-
remove():删除指定的元素,如果元素不存在会引发KeyError异常。my_set = {1, 2, 3} my_set.remove(2) print(my_set) # 输出: {1, 3} -
discard():删除指定的元素,如果元素不存在不会引发异常。my_set = {1, 2, 3} my_set.discard(4) # 不会引发异常,即使元素 4 不存在 print(my_set) # 输出: {1, 2, 3}
-
-
弹出元素:使用
pop()方法随机删除并返回一个元素。如果集合为空,会引发KeyError异常。my_set = {1, 2, 3} # 随机删除集合中的一个元素,并将其赋值给变量 item item = my_set.pop() # 打印被删除的元素 print(item) # 输出: 1(或者 2 或 3,取决于内部实现) # 打印集合的当前状态 print(my_set) # 输出: {2, 3}(或者 {1, 3} 或 {1, 2}) -
清空集合:使用
clear()方法清空集合中的所有元素。my_set = {1, 2, 3} my_set.clear() print(my_set) # 输出: set()
集合运算
集合支持多种数学集合运算,如并集、交集、差集等:
-
并集:使用
|运算符或union()方法。set1 = {1, 2, 3} set2 = {3, 4, 5} union_set = set1 | set2 print(union_set) # 输出: {1, 2, 3, 4, 5} # 或使用 union() 方法 union_set = set1.union(set2) print(union_set) # 输出: {1, 2, 3, 4, 5} -
交集:使用
&运算符或intersection()方法。set1 = {1, 2, 3} set2 = {3, 4, 5} intersection_set = set1 & set2 print(intersection_set) # 输出: {3} # 或使用 intersection() 方法 intersection_set = set1.intersection(set2) print(intersection_set) # 输出: {3} -
差集:使用
-运算符或difference()方法。set1 = {1, 2, 3} set2 = {3, 4, 5} difference_set = set1 - set2 print(difference_set) # 输出: {1, 2} # 或使用 difference() 方法 difference_set = set1.difference(set2) print(difference_set) # 输出: {1, 2} -
对称差集:使用
^运算符或symmetric_difference()方法。set1 = {1, 2, 3} set2 = {3, 4, 5} symmetric_difference_set = set1 ^ set2 print(symmetric_difference_set) # 输出: {1, 2, 4, 5} # 或使用 symmetric_difference() 方法 symmetric_difference_set = set1.symmetric_difference(set2) print(symmetric_difference_set) # 输出: {1, 2, 4, 5}
集合方法
-
copy():返回集合的浅拷贝。my_set = {1, 2, 3} copied_set = my_set.copy() print(copied_set) # 输出: {1, 2, 3} -
issubset(other_set):判断当前集合是否是other_set的子集。set1 = {1, 2} set2 = {1, 2, 3} print(set1.issubset(set2)) # 输出: True -
issuperset(other_set):判断当前集合是否是other_set的超集。set1 = {1, 2, 3} set2 = {1, 2} print(set1.issuperset(set2)) # 输出: True -
isdisjoint(other_set):判断当前集合与other_set是否没有交集。set1 = {1, 2} set2 = {3, 4} print(set1.isdisjoint(set2)) # 输出: True
map
map 函数是 Python 内置的一个高阶函数,它用于将指定函数应用到给定可迭代对象的每个元素上,并返回一个迭代器,该迭代器生成应用函数后的结果。
语法
map(function, iterable, ...)
-
function:应用于iterable中每个元素的函数。可以是一个函数、lambda 表达式或其他可调用对象。-
lambda 基本语法
lambda arguments: expressionlambda:关键字,用于定义 lambda 函数。arguments:函数的参数列表(可以是多个参数,逗号分隔)。expression:一个返回值的表达式,不允许有多个语句。
-
-
iterable:一个或多个可迭代对象,它们的元素将被传递给function。 -
map可以接受多个可迭代对象作为参数,并且function必须能处理这些可迭代对象中的所有元素。
返回值
map函数返回一个迭代器,可以用list()或tuple()转换为列表或元组。
示例:
- 基本用法:
numbers = [1, 2, 3, 4, 5]
# 使用 map 和 lambda 函数来计算每个元素的平方
squares = map(lambda x: x ** 2, numbers)
# 转换为列表并输出
print(list(squares)) # 输出: [1, 4, 9, 16, 25]
- 多个可迭代对象:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# 将两个列表的元素逐对相加
sums = map(lambda x, y: x + y, list1, list2)
# 转换为列表并输出
print(list(sums)) # 输出: [5, 7, 9]
Function 函数
定义函数
定义函数使用 def 关键字。函数是一组可重用的代码块,用于执行单一、相关的任务。定义函数的基本语法如下:
def function_name(parameters):
"""Docstring"""
# Function body
return value
函数的各个部分
def关键字:用于声明函数。function_name:函数名,应简洁明了地描述函数的功能。parameters:函数参数,是函数接收的输入。可以没有参数,也可以有一个或多个参数,多个参数之间用逗号分隔。Docstring:可选,用于描述函数的用途和行为。通常用三引号括起来。- 函数体:包含函数的实际代码块。
return语句:可选,用于返回函数的结果。如果省略,函数返回None。
基本示例
定义一个简单的函数,用于计算两个数的和:
def add(a, b):
"""Returns the sum of a and b"""
return a + b
# 调用函数
result = add(3, 5)
print(result) # 输出: 8
带有默认参数的函数
函数参数可以有默认值。如果调用函数时未提供这些参数的值,将使用默认值。
def greet(name, message="Hello"):
"""Prints a greeting message"""
print(f"{message}, {name}!")
# 调用函数
greet("Alice") # 输出: Hello, Alice!
greet("Bob", "Hi") # 输出: Hi, Bob!
带有可变参数的函数
使用 *args 和 **kwargs 来处理不定数量的参数。
*args:用于接收任意数量的位置参数,返回一个元组。**kwargs:用于接收任意数量的关键字参数,返回一个字典。
def print_args(*args):
"""Prints all positional arguments"""
for arg in args:
print(arg)
def print_kwargs(**kwargs):
"""Prints all keyword arguments"""
for key, value in kwargs.items():
print(f"{key}: {value}")
# 调用函数
print_args(1, 2, 3) # 输出: 1 2 3
print_kwargs(a=1, b=2, c=3) # 输出: a: 1 b: 2 c: 3
带有返回值的函数
函数可以返回多个值,这些值会以元组的形式返回。
def divide(a, b):
"""Returns the quotient and remainder of a divided by b"""
quotient = a // b
remainder = a % b
return quotient, remainder
# 调用函数
q, r = divide(10, 3)
print(f"Quotient: {q}, Remainder: {r}") # 输出: Quotient: 3, Remainder: 1
函数的作用域(全局和局部变量)
| 变量 | 特点 |
|---|---|
| 全局 global | 函数里外都能用 (公用) |
| 局部 local | 仅在函数内有用 (私有) |
局部变量
- 局部变量:在函数内部定义的变量,只能在函数内部访问。函数执行完毕后,局部变量会被销毁。
示例
def my_function():
local_var = 10 # 局部变量
print(f"Inside function: local_var = {local_var}")
my_function()
# print(local_var) # 这行代码会报错,因为 local_var 是局部变量,在函数外部不可访问
在上面的例子中,local_var 是一个局部变量,只能在 my_function 内部访问。如果尝试在函数外部访问 local_var,会引发 NameError 异常。
全局变量
- 全局变量:在函数外部定义的变量,可以在整个模块内访问。要在函数内部修改全局变量,需要使用
global关键字。全局变量在模块加载时创建,并在程序运行期间存在。
示例
global_var = 20 # 全局变量
def my_function():
print(f"Inside function: global_var = {global_var}")
my_function() # 输出: Inside function: global_var = 20
print(f"Outside function: global_var = {global_var}") # 输出: Outside function: global_var = 20
在上面的例子中,global_var 是一个全局变量,可以在 my_function 内部和函数外部访问。
修改全局变量
x = 10 # 全局变量
def modify():
global x # 声明使用全局变量 x
x = 20 # 修改全局变量 x
print(f"Before modifying: x = {x}") # Before modifying: x = 10
modify()
print(f"After modifying: x = {x}") # After modifying: x = 20
在上面的例子中,通过使用 global 关键字,可以在 modify_global 函数内部修改全局变量 x。
闭包和非局部变量
在嵌套函数中,使用 nonlocal 关键字可以声明一个变量不是局部变量,而是嵌套函数的外层函数的局部变量。
nonlocal关键字:用于在嵌套函数中声明外层函数的局部变量。只能在嵌套函数中使用,声明的是外层(但不是全局)变量- 作用:允许嵌套函数修改外层函数的局部变量。
- 示例:通过
nonlocal修改并访问外层函数的局部变量,保证在嵌套函数内外一致。
示例
def outer_function():
outer_var = 10 # 外层函数的局部变量
def inner_function():
nonlocal outer_var # 声明使用外层函数的局部变量 表示 inner_function 中对 outer_var 的任何修改都作用于 outer_function 的局部变量 outer_var。
outer_var += 5
print(f"Inside inner_function: outer_var = {outer_var}")
inner_function() # inner_function 被调用,修改并打印 outer_var 的值
print(f"Inside outer_function: outer_var = {outer_var}")
outer_function()
运行结果
Inside inner_function: outer_var = 15
Inside outer_function: outer_var = 15
在上面的例子中,inner_function 使用 nonlocal 关键字声明 outer_var,这样可以在 inner_function 内部修改 outer_var 的值。
没有 nonlocal 的情况
def outer_function():
outer_var = 10 # 外层函数的局部变量
def inner_function():
outer_var = 5 # 创建一个新的局部变量,不会影响外层函数的 outer_var
print(f"Inside inner_function: outer_var = {outer_var}")
inner_function()
print(f"Inside outer_function: outer_var = {outer_var}")
outer_function()
运行结果
Inside inner_function: outer_var = 5
Inside outer_function: outer_var = 10
在这个例子中,inner_function 创建了一个新的局部变量 outer_var,不会影响外层函数的 outer_var。
局部变量和全局变量的查找顺序(LEGB规则)
Python 使用 LEGB(Local, Enclosing, Global, Built-in)规则来查找变量:
- Local(局部作用域) :首先在当前函数的局部作用域查找变量。
- Enclosing(嵌套作用域) :如果在局部作用域找不到,则查找外层函数的作用域(对于嵌套函数)。
- Global(全局作用域) :如果在嵌套作用域找不到,则查找全局作用域。
- Built-in(内置作用域) :如果在全局作用域找不到,则查找 Python 内置作用域。
示例
x = "global" # 全局变量
def outer():
x = "enclosing" # 局部变量
def inner(): # 嵌套函数
x = "local" # 局部变量
print(x) # x 是 inner 函数的局部变量 输出: local
inner() # 打印 inner 函数内部的 x
print(x) # x 是 outer 函数的局部变量 输出: enclosing
outer()
print(x) # 输出: global
在上面的例子中,inner 函数会优先使用它的局部变量 x。如果没有局部变量 x,则会使用外层函数 outer 的变量 x,如果再没有,则使用全局变量 x。
匿名函数(Lambda 函数)
匿名函数使用 lambda 关键字创建,通常用于简单的、一次性的操作。
基本语法
lambda arguments: expression
arguments:参数列表,多个参数用逗号分隔。expression:一个单一的表达式,表示函数的返回值。
示例
-
基本示例:
# 普通函数 def add(x, y): return x + y # 使用 lambda 表达式 add_lambda = lambda x, y: x + y # 测试 print(add(2, 3)) # 输出: 5 print(add_lambda(2, 3)) # 输出: 5 -
用于内置函数:
lambda表达式经常与内置函数如map(),filter(), 和sorted()一起使用。# 使用 lambda 和 map 函数 numbers = [1, 2, 3, 4, 5] squared_numbers = map(lambda x: x ** 2, numbers) print(list(squared_numbers)) # 输出: [1, 4, 9, 16, 25] # 使用 lambda 和 filter 函数 even_numbers = filter(lambda x: x % 2 == 0, numbers) print(list(even_numbers)) # 输出: [2, 4] # 使用 lambda 和 sorted 函数进行自定义排序 pairs = [(1, 'one'), (3, 'three'), (2, 'two')] sorted_pairs = sorted(pairs, key=lambda pair: pair[1]) print(sorted_pairs) # 输出: [(1, 'one'), (2, 'two'), (3, 'three')] -
用作函数参数:
# 传递 lambda 作为参数 def apply_function(func, value): return func(value) result = apply_function(lambda x: x * 2, 5) print(result) # 输出: 10 -
作为数据结构中的元素:
# 使用 lambda 作为列表中的元素 functions = [lambda x: x + 1, lambda x: x * 2, lambda x: x - 1] for func in functions: print(func(3)) # 输出: 4, 6, 2
特点
- 匿名:
lambda函数没有名称。它们主要用于定义简单的函数体而无需显式命名。 - 限制:
lambda表达式只能包含一个表达式,不能包含语句或多个表达式。 - 短小:适合用在简短、一次性的函数需求场景。
使用场景
- 简短的函数定义:当函数体非常简单,且只使用一次时,使用
lambda更加简洁。 - 函数式编程:
lambda常用于函数式编程风格的场景,如与map(),filter(),sorted()等函数一起使用。 - 局部使用:当需要将函数作为参数传递给其他函数时,使用
lambda可以避免定义额外的函数。
特殊方法
特殊方法(也称为魔法方法或双下划线方法)用于定义类的行为
__init__()
作用:初始化实例。当创建类的实例时,__init__ 方法被自动调用,用于初始化实例的属性。
示例:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# 创建实例
person = Person("Alice", 30)
print(person.name) # 输出: Alice
print(person.age) # 输出: 30
__repr__()
作用:定义对象的“官方”字符串表现形式。__repr__ 方法应该返回一个字符串,这个字符串表示的对象在使用 eval() 时能恢复到原来的对象。如果没有提供 __str__ 方法,__repr__ 会被用作对象的默认字符串表现形式。
示例:
!r 用于调用 repr() 函数,以确保 name 和 age 的值被表示为 Python 字符串字面量(对于字符串,!r 将会包括引号)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name!r}, age={self.age!r})"
# 创建实例
person = Person("Alice", 30)
print(repr(person)) # 输出: Person(name='Alice', age=30)
__str__()
作用:定义对象的“非正式”字符串表现形式。__str__ 方法应该返回一个对用户友好的字符串表示,用于 print() 或 str()。
示例:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name}, {self.age} years old"
# 创建实例
person = Person("Alice", 30)
print(person) # 输出: Alice, 30 years old
__iter__()
作用:使对象成为可迭代的对象。__iter__ 方法返回一个迭代器对象,该对象实现了 __next__ 方法。通常,__iter__ 方法会返回 self 或者一个新的迭代器对象。
示例:
class Fibonacci:
def __init__(self, max):
"""
初始化 Fibonacci 迭代器对象
:param max: 生成的 Fibonacci 数字的最大值
"""
self.max = max # 设置 Fibonacci 数列的最大值
self.a, self.b = 0, 1 # 初始化 Fibonacci 数列的前两个数字
def __iter__(self):
"""
返回迭代器对象本身
:return: 迭代器对象
"""
return self # 迭代器本身是可迭代的
def __next__(self):
"""
生成 Fibonacci 数列的下一个数字
:return: 当前 Fibonacci 数字
"""
if self.a > self.max:
# 如果当前数字大于最大值,抛出 StopIteration 异常以结束迭代
raise StopIteration
# 更新 Fibonacci 数字
self.a, self.b = self.b, self.a + self.b
return self.a # 返回更新后的数字
# 创建 Fibonacci 迭代器实例,最大值为 10
fib = Fibonacci(10)
# 使用 for 循环遍历 Fibonacci 迭代器
for num in fib:
print(num) # 输出: 1 1 2 3 5 8
fib = Fibonacci(10):创建一个Fibonacci迭代器实例,设置最大值为 10。for num in fib::使用for循环遍历迭代器,__next__()方法在每次迭代中被调用,直到StopIteration异常被抛出。
输出解释
对于 fib = Fibonacci(10),Fibonacci 迭代器会生成小于或等于 10 的 Fibonacci 数字:
- 迭代开始时,
a = 0和b = 1。 - 在第一次调用
__next__()时,a更新为 1。 - 第二次调用
__next__()时,a更新为 1。 - 第三次调用
__next__()时,a更新为 2。 - 依此类推,直到生成 8。
- 当
a达到 13 超过最大值 10 时,抛出StopIteration异常,结束迭代。
最终,for 循环输出的结果是:1 1 2 3 5 8。
__next__()
作用:从迭代器中获取下一个值。__next__ 方法通常由迭代器实现,返回序列的下一个值。当没有更多值可返回时,应该抛出 StopIteration 异常。
示例:
class Countdown:
def __init__(self, start):
"""
初始化 Countdown 实例。
:param start: 倒计时的开始值
"""
self.start = start
def __iter__(self):
"""
将 Countdown 实例标记为可迭代对象。
:return: 返回迭代器对象本身
"""
self.current = self.start # 设置当前计数值为开始值
return self # 返回迭代器对象本身
def __next__(self):
"""
返回序列的下一个值。如果序列结束,则抛出 StopIteration 异常。
:return: 当前计数值
:raises StopIteration: 当当前计数值小于等于 0 时
"""
if self.current <= 0:
raise StopIteration # 序列结束,抛出 StopIteration 异常
self.current -= 1 # 减少当前计数值
return self.current + 1 # 返回当前计数值(加 1 是因为计数是从 start 开始的)
def main():
"""
主函数,创建 Countdown 实例并演示其使用。
"""
countdown = Countdown(5) # 创建 Countdown 实例,开始值为 5
print("Countdown from 5:")
for number in countdown:
print(number) # 输出倒计时的数字
if __name__ == "__main__":
main() # 运行主函数
Class 类
类(class)是一种用于创建自定义对象的机制
定义类
使用 class 关键字定义类。类定义通常包括属性(变量)和方法(函数)。
基本结构
class File:
def __init__(self):
self.name = "f1"
self.create_time = "today"
my_file = File()
print(my_file.name) # 输出: f1
print(my_file.create_time) # 输出: today
示例解释
-
定义类
File:class关键字:用于定义一个类- 类名
File:类的名称,按照惯例,类名首字母大写
-
定义构造方法
__init__:__init__是构造方法(初始化方法),在创建类实例时自动调用。self参数指向类的实例,用于访问实例的属性和方法。
-
初始化属性:
self.name被设置为"f1",这是实例的一个属性,表示文件名。self.create_time被设置为"today",这是实例的另一个属性,表示文件的创建时间。
-
创建类的实例
my_file:my_file是File类的一个实例,调用File()时,__init__方法被执行,初始化实例的属性。
Class的功能
为类添加更多属性和方法,以增加功能。
class File:
def __init__(self, name, create_time):
self.name = name
self.create_time = create_time
def rename(self, new_name):
self.name = new_name
def get_info(self):
return f"File name: {self.name}, Created on: {self.create_time}"
# 创建类的实例
my_file = File("f1", "today")
# 访问和打印属性
print(my_file.name) # 输出: f1
print(my_file.create_time) # 输出: today
# 调用方法
my_file.rename("new_name")
print(my_file.name) # 输出: new_name
info = my_file.get_info()
print(info) # 输出: File name: new_name, Created on: today
使用默认参数
你也可以在构造方法中使用默认参数。
class File:
def __init__(self, name="f1", create_time="today"):
self.name = name
self.create_time = create_time
# 创建类的实例
my_file = File() # 使用默认参数
print(my_file.name) # 输出: f1
print(my_file.create_time) # 输出: today
my_file_with_custom_name = File(name="custom_name")
print(my_file_with_custom_name.name) # 输出: custom_name
print(my_file_with_custom_name.create_time) # 输出: today
类的返回值
class File:
def __init__(self, name, create_time="today"):
self.name = name
self.create_time = create_time
def get_info(self):
return self.name + " is created at " + self.create_time
my_file = File("my_file")
print(my_file.get_info()) # 输出: my_file is created at today
继承
类可以从其他类继承属性和方法。继承通过将父类作为参数传递给子类来实现。
示例
class File:
def __init__(self, name, create_time="today"):
self.name = name
self.create_time = create_time
def get_info(self):
return self.name + " is created at " + self.create_time
class Video(File): # 继承了 File 的属性和功能
def __init__(self, name, window_size=(1080, 720)):
# 将共用属性的设置导入 File 父类
super().__init__(name=name, create_time="today")
self.window_size = window_size
class Text(File): # 继承了 File 的属性和功能
def __init__(self, name, language="zh-cn"):
# 将共用属性的设置导入 File 父类
super().__init__(name=name, create_time="today")
self.language = language
# 也可以在子类里复用父类功能
def get_more_info(self):
return self.get_info() + ", using language of " + self.language
v = Video("my_video")
t = Text("my_text")
print(v.get_info()) # 调用父类的功能
print(t.create_time) # 调用父类的属性
print(t.language) # 调用自己的属性
print(t.get_more_info()) # 调用自己加工父类的功能
运行结果
my_video is created at today
today
zh-cn
my_text is created at today, using language of zh-cn
私有属性和功能 __
- 私有属性和方法是通过在属性名或方法名前加上双下划线
__来实现 - 使得这些属性和方法在类的外部不可直接访问,但仍然可以通过名称修饰来访问。
| 私有 | 特点 |
|---|---|
| _ 一个下划线开头 | 弱隐藏 不想让别人用 (别人在必要情况下还是可以用的) |
| __ 两个下划线开头 | 强隐藏 不让别人用 |
定义私有属性和方法
在类中定义私有属性和方法时,前缀使用双下划线 __。
class File:
def __init__(self, name, create_time="today"):
self.__name = name
self.__create_time = create_time
def __get_info(self):
return self.__name + " is created at " + self.__create_time
def public_get_info(self):
return self.__get_info()
# 创建类的实例
my_file = File("my_file")
# 直接访问私有属性和方法会失败
# print(my_file.__name) # AttributeError
# print(my_file.__get_info()) # AttributeError
# 可以通过类的方法间接访问私有属性和方法
print(my_file.public_get_info()) # 输出: my_file is created at today
解释
-
私有属性:
self.__name和self.__create_time是私有属性,无法在类的外部直接访问。
-
私有方法:
__get_info是私有方法,无法在类的外部直接调用。
-
公有方法:
public_get_info是公有方法,可以在类的外部调用,它间接调用私有方法__get_info。
名称修饰
虽然私有属性和方法不能在类的外部直接访问,但可以通过 Python 的名称修饰机制访问。名称修饰会将私有属性和方法的名称改为 _ClassName__AttributeName 的形式。
class File:
def __init__(self, name, create_time="today"):
self.__name = name
self.__create_time = create_time
def __get_info(self):
return self.__name + " is created at " + self.__create_time
# 创建类的实例
my_file = File("my_file")
# 通过名称修饰访问私有属性和方法
print(my_file._File__name) # 输出: my_file
print(my_file._File__get_info()) # 输出: my_file is created at today
示例:带私有属性和方法的继承
子类可以继承父类的公有和私有属性和方法,但私有属性和方法在子类中会被名称修饰。
class File:
def __init__(self, name, create_time="today"):
self.__name = name
self.__create_time = create_time
def __get_info(self):
return self.__name + " is created at " + self.__create_time
def public_get_info(self):
return self.__get_info()
class Video(File):
def __init__(self, name, window_size=(1080, 720)):
super().__init__(name)
self.window_size = window_size
# 创建类的实例
v = Video("my_video")
# 通过子类的实例访问父类的公有方法
print(v.public_get_info()) # 输出: my_video is created at today
# 通过名称修饰访问父类的私有属性和方法
print(v._File__name) # 输出: my_video
print(v._File__get_info()) # 输出: my_video is created at today
注意事项
-
名称修饰机制:
- 私有属性和方法通过名称修饰机制仍可访问,但通常不推荐这样做,因为这破坏了封装性。
-
保护级别:
- Python 中没有真正的私有属性和方法的概念,只有基于约定的保护级别。前缀
_表示“受保护的”属性和方法,开发者应该将其视为私有,但实际上仍可访问。
- Python 中没有真正的私有属性和方法的概念,只有基于约定的保护级别。前缀
进一步扩展
保护级别的属性和方法
使用单下划线 _ 表示“受保护的”属性和方法,虽然可以访问,但不建议在类的外部使用。
class File:
def __init__(self, name, create_time="today"):
self._name = name
self._create_time = create_time
def _get_info(self):
return self._name + " is created at " + self._create_time
class Video(File):
def __init__(self, name, window_size=(1080, 720)):
super().__init__(name)
self.window_size = window_size
v = Video("my_video")
print(v._get_info()) # 输出: my_video is created at today
方法重写
子类可以重写父类的方法。
示例
class ParentClass:
def method(self):
return "Parent method"
class ChildClass(ParentClass):
def method(self):
return "Child method"
child_obj = ChildClass()
print(child_obj.method()) # 输出: Child method
类和实例变量
- 实例变量:通过
self访问,每个实例都有独立的值。 - 类变量:通过类名访问,所有实例共享同一个值。
示例
class MyClass:
class_variable = "Class variable"
def __init__(self, instance_variable):
self.instance_variable = instance_variable
obj1 = MyClass("Instance variable 1")
obj2 = MyClass("Instance variable 2")
print(obj1.instance_variable) # 输出: Instance variable 1
print(obj2.instance_variable) # 输出: Instance variable 2
print(obj1.class_variable) # 输出: Class variable
print(obj2.class_variable) # 输出: Class variable
MyClass.class_variable = "New class variable"
print(obj1.class_variable) # 输出: New class variable
print(obj2.class_variable) # 输出: New class variable
私有变量和方法
通过在变量或方法名前加双下划线(__)定义私有变量和方法,避免在类外部访问。
示例
class MyClass:
def __init__(self, value):
self.__private_variable = value
def __private_method(self):
return self.__private_variable
def public_method(self):
return self.__private_method()
obj = MyClass("Private value")
# print(obj.__private_variable) # 会报错,无法访问私有变量
# print(obj.__private_method()) # 会报错,无法访问私有方法
print(obj.public_method()) # 输出: Private value
module模块
模块 是一个包含 Python 代码的文件,文件名以 .py 结尾。模块可以定义函数、类、变量,还可以包含可执行的代码。模块使得代码的组织和重用变得更简单和有效。
如何创建模块
创建模块非常简单,只需要创建一个 .py 文件即可。例如,创建一个名为 mymodule.py 的文件,并在其中定义一些函数和变量:
# 文件名: mymodule.py
def greet(name):
return f"Hello, {name}!"
def add(a, b):
return a + b
PI = 3.14159
如何导入模块
可以使用 import 语句导入模块并使用其功能。下面是如何在另一个 Python 文件中使用 mymodule 模块:
# 文件名: main.py
import mymodule
print(mymodule.greet("Alice")) # 输出: Hello, Alice!
print(mymodule.add(5, 3)) # 输出: 8
print(mymodule.PI) # 输出: 3.14159
从模块中导入特定的对象
你可以从模块中导入特定的函数、类或变量,而不是整个模块:
# 文件名: main.py
from mymodule import greet, PI
print(greet("Bob")) # 输出: Hello, Bob!
print(PI) # 输出: 3.14159
使用别名
你可以为模块或其对象指定别名,以简化代码或避免命名冲突:
# 文件名: main.py
import mymodule as mm
print(mm.greet("Charlie")) # 输出: Hello, Charlie!
print(mm.add(7, 8)) # 输出: 15
print(mm.PI) # 输出: 3.14159
from mymodule import add as addition
print(addition(10, 20)) # 输出: 30
模块的 __name__ 属性
每个模块都有一个 __name__ 属性,它的值是模块的名称。如果模块是被直接运行的,则 __name__ 的值为 '__main__'。这可以用来区分模块是被直接运行还是被导入。
# 文件名: mymodule.py
def greet(name):
return f"Hello, {name}!"
if __name__ == "__main__":
print(greet("Main"))
如果 mymodule.py 被直接运行,则输出:
Hello, Main
如果 mymodule.py 被导入到其他模块中,则不会执行 if __name__ == "__main__": 部分的代码。
包(Packages)
包 是一种特殊的模块,它允许将模块组织到目录中。一个包目录下必须包含一个 __init__.py 文件,才能被 Python 识别为包。__init__.py 可以是空的,也可以包含包的初始化代码。
示例:
假设有以下目录结构:
myproject/
├── mypackage/
│ ├── __init__.py
│ ├── module1.py
│ └── module2.py
└── main.py
在 mypackage/__init__.py 中:
# 文件名: mypackage/__init__.py
def package_function():
return "Function from mypackage"
在 mypackage/module1.py 中:
# 文件名: mypackage/module1.py
def module1_function():
return "Function from module1"
在 mypackage/module2.py 中:
# 文件名: mypackage/module2.py
def module2_function():
return "Function from module2"
在 main.py 中:
# 文件名: main.py
from mypackage import package_function
from mypackage.module1 import module1_function
from mypackage.module2 import module2_function
print(package_function()) # 输出: Function from mypackage
print(module1_function()) # 输出: Function from module1
print(module2_function()) # 输出: Function from module2
常用标准库模块
Python 标准库包含许多内置模块,提供了各种功能。例如:
os:提供与操作系统交互的功能。sys:提供与 Python 解释器相关的功能。math:提供数学函数。datetime:提供处理日期和时间的功能。
示例:
import os
import sys
import math
from datetime import datetime
print(os.getcwd()) # 输出当前工作目录
print(sys.version) # 输出 Python 版本
print(math.sqrt(16)) # 输出: 4.0
print(datetime.now()) # 输出当前日期和时间
文件管理
读写文件
| mode | 意思 |
|---|---|
| w | (创建)写文本 |
| r | 读文本,文件不存在会报错 |
| a | 在文本最后添加 |
| wb | 写二进制 binary |
| rb | 读二进制 binary |
| ab | 添加二进制 |
| w+ | 又可以读又可以(创建)写 |
| r+ | 又可以读又可以写, 文件不存在会报错 |
| a+ | 可读写,在文本最后添加 |
| x | 创建 |
打开文件
使用 open() 函数打开文件。open() 函数有两个主要参数:
- 文件路径:要打开的文件的路径。
- 模式:打开文件的模式,如读取模式(
'r')、写入模式('w')、追加模式('a')等。
常用模式:
'r':读取模式(默认)。文件必须存在。'w':写入模式。如果文件存在,会被覆盖;如果文件不存在,会创建新文件。'a':追加模式。文件存在时,数据会被添加到文件末尾;文件不存在时,会创建新文件。'b':二进制模式。可以与其他模式结合使用,如'rb'或'wb',用于读取或写入二进制文件。't':文本模式(默认)。可以与其他模式结合使用,如'rt'或'wt',用于读取或写入文本文件。
示例:
# 打开文件以读取
file = open('example.txt', 'r')
读取文件
读取文本文件的内容:
read(size=-1):读取文件的全部内容。如果指定size,则读取指定大小的内容。readline(size=-1):读取一行内容。如果指定size,则读取指定大小的内容。readlines(hint=-1):读取所有行并返回一个列表。如果指定hint,则读取指定数量的字节。
示例:
with语句:确保文件在操作完成后自动关闭,即使在处理文件过程中发生异常。这避免了手动调用file.close()的需求,减少了出错的可能性。open('example.txt', 'r'):使用open()函数打开名为example.txt的文件'r'表示以读取模式打开文件。这个模式允许你读取文件内容,但不允许修改。
# 读取整个文件内容
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# 读取一行内容
with open('example.txt', 'r') as file:
first_line = file.readline()
print(first_line)
# 读取所有行
with open('example.txt', 'r') as file:
lines = file.readlines()
for line in lines:
# end='':指定打印时行尾不添加额外的换行符
print(line, end='')
写入文件
写入文本文件:
write(string):写入字符串到文件。如果文件存在,内容会被覆盖;如果文件不存在,会创建新文件。writelines(lines):将序列中的所有字符串写入文件。
示例:
# 写入内容到文件(会覆盖文件内容)
with open('example.txt', 'w') as file:
file.write('Hello, world!\n')
file.write('This is a new line.')
# 追加内容到文件
with open('example.txt', 'a') as file:
file.write('\nAppended line.')
关闭文件
close() :关闭文件。文件关闭后,不能再读取或写入文件。
示例:
file = open('example.txt', 'r')
# 读取文件内容
content = file.read()
print(content)
file.close() # 关闭文件
推荐使用:使用 with 语句来处理文件。它会自动处理文件的打开和关闭。
二进制文件操作
打开二进制文件:
# 打开二进制文件
with open('example.bin', 'rb') as file:
content = file.read()
print(content)
写入二进制文件:
# 写入二进制文件
with open('example.bin', 'wb') as file:
file.write(b'\x00\x01\x02') # 写入二进制数据
文件操作的异常处理
在文件操作过程中,可能会遇到各种异常,例如文件不存在或权限问题。可以使用 try 和 except 来处理这些异常。
示例:
try:
with open('example.txt', 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print('File not found.')
except IOError:
print('An error occurred while handling the file.')
文件编码,中文乱码
文件编码 是一种将字符映射到字节序列的方式。常见的编码包括:
- UTF-8:一种支持所有语言字符的编码方式,广泛用于网页和现代应用程序。
- GBK:一种主要用于简体中文的编码方式。
- ISO-8859-1(Latin-1):一种用于西欧语言的编码方式。
- UTF-16:一种支持所有语言字符的编码方式,但文件大小较大。
指定编码方式
在使用 open() 函数时,可以通过 encoding 参数指定文件编码。以下是一些常见的编码方式和示例:
- UTF-8 编码:适用于大多数场景,特别是处理多语言文本时。
# 读取 UTF-8 编码的文件
with open('example.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)
# 写入 UTF-8 编码的文件
with open('example.txt', 'w', encoding='utf-8') as file:
file.write('你好,世界!') # 写入中文内容
- GBK 编码:常用于处理简体中文文本。
# 读取 GBK 编码的文件
with open('example.txt', 'r', encoding='gbk') as file:
content = file.read()
print(content)
# 写入 GBK 编码的文件
with open('example.txt', 'w', encoding='gbk') as file:
file.write('你好,世界!') # 写入中文内容
检测文件编码
安装 chardet:
pip install chardet
使用 chardet 检测编码:
chardet.detect()方法检测字节数据的编码result = chardet.detect(raw_data):返回的result是一个字典,其中包含检测到的编码 ('encoding')、编码置信度 ('confidence'),以及语言信息 ('language'),尽管语言信息可能不总是提供。
import chardet
# 检测文件编码
with open('example.txt', 'rb') as file:
raw_data = file.read()
result = chardet.detect(raw_data)
encoding = result['encoding']
print(f"Detected encoding: {encoding}")
# 以检测到的编码重新读取文件
with open('example.txt', 'r', encoding=encoding) as file:
content = file.read()
print(content)
处理编码错误
在读取或写入文件时,如果文件的编码方式不正确,可能会引发编码错误。你可以通过 errors 参数来指定如何处理这些错误。常见的错误处理策略包括:
'ignore':忽略编码错误。'replace':用替代字符(如�)替代无法解码的字符。
示例:
# 以忽略错误的方式读取文件
with open('example.txt', 'r', encoding='utf-8', errors='ignore') as file:
content = file.read()
print(content)
# 以替代字符的方式读取文件
with open('example.txt', 'r', encoding='utf-8', errors='replace') as file:
content = file.read()
print(content)
示例:处理中文乱码的完整流程
读取中文文件,自动检测编码,并处理可能的乱码:
import chardet
# 自动检测文件编码
with open('example.txt', 'rb') as file:
raw_data = file.read()
result = chardet.detect(raw_data)
encoding = result['encoding']
# 读取文件内容,处理乱码
with open('example.txt', 'r', encoding=encoding, errors='replace') as file:
content = file.read()
print(content)
r+ w+ a+
r+
"r+"模式在 Python 中用于以读写模式打开文件。它允许你读取文件内容,同时也可以修改(写入)文件- 文件必须已经存在,否则会抛出
FileNotFoundError异常
# 使用 r+ 模式打开文件
with open('example.txt', 'r+') as file:
lines = file.readlines() # 读取所有行到列表中
lines[1] = 'Python is amazing!\n' # 修改第二行的内容
file.seek(0) # 将文件指针移到文件开头
file.writelines(lines) # 写入修改后的内容
# 读取文件并输出查看结果
with open('example.txt', 'r') as file:
content = file.read()
print(content)
截断 file.truncate()
# 使用 r+ 模式打开文件
with open('example.txt', 'r+') as file:
lines = file.readlines() # 读取所有行
file.seek(0) # 将文件指针移到开头
file.writelines(lines[:2]) # 只写入前两行
file.truncate() # 截断文件,删除从当前位置到文件末尾的所有内容
# 读取文件并输出查看结果
with open('example.txt', 'r') as file:
content = file.read()
print(content)
w+
"w+"模式在 Python 中用于以读写模式打开文件。- 与
"r+"模式不同的是,"w+"模式在打开文件时会清空文件的内容(如果文件已存在),并且如果文件不存在则会创建一个新文件。
如果文件 example.txt 不存在,或者它存在但内容会被清空,我们可以使用 "w+" 模式创建新文件并写入内容。
代码示例:
# 创建一个初始文件
with open('example.txt', 'w+') as file:
file.write("Initial content.\n")
# 使用 w+ 模式重新打开文件,清空内容并写入新内容
with open('example.txt', 'w+') as file:
file.write("New content replaces old content.\n")
file.seek(0) # 将文件指针移动到文件开头,以确保读取新写入的内容
print(file.read())
a+
"a+"模式用于以读写模式打开文件,但与"w+"模式不同的是,它不会清空文件的内容,而是将新内容追加到文件的末尾。- 如果文件不存在,它会创建一个新文件。
- 这个模式适用于你想在文件末尾添加内容,同时又希望能够读取文件内容的情况。
# 使用 a+ 模式打开文件
with open('example.txt', 'a+') as file:
file.seek(0) # 将文件指针移动到开头,以便读取现有内容
content = file.read() # 读取现有内容
print("Current content:")
print(content)
file.write("Appended line 1.\n")
file.write("Appended line 2.\n")
# 读取文件并输出查看结果
with open('example.txt', 'r') as file:
content = file.read()
print("\nUpdated content:")
print(content)
文件目录管理
文件目录操作
文件和目录的操作通常使用 os 和 shutil 模块
os模块:用于基本的文件和目录操作,如创建、删除、重命名、移动和列出文件或目录。shutil模块:提供了更高级的文件和目录操作,如复制、移动和删除目录及其内容。
使用 os 模块进行文件和目录操作
获取当前工作目录
import os
current_directory = os.getcwd()
print("Current Directory:", current_directory)
切换工作目录
import os
os.chdir('/path/to/new/directory')
print("Directory changed to:", os.getcwd())
创建新目录
os.makedirs:用于递归创建目录。即使中间的目录不存在,它也会创建所有必要的父目录。exist_ok=True:如果目录已经存在,不会引发FileExistsError异常。设置为True时,这个参数会让函数忽略已经存在的目录。os.path.exists:用于检查指定路径是否存在。如果路径存在,返回True;否则返回False。
import os
# 创建单个目录
os.mkdir('new_directory')
# 创建多级目录
os.makedirs('parent_directory/child_directory')
# 创建目录 "project",如果已存在则不会引发异常
os.makedirs("project", exist_ok=True)
# 检查目录是否存在
print(os.path.exists("project"))
删除目录
os.removedirs:用于删除目录及其空父目录,但目录必须为空。如果目录中还有文件或其他子目录,它不会成功删除。shutil.rmtree:用于递归删除目录及其所有内容,适用于删除非空目录。- 异常处理:使用
try-except语句捕获可能发生的异常,以便在删除失败时进行适当处理。
import os
# 删除空目录
os.rmdir('empty_directory')
# 删除多级目录及其内容
import shutil
shutil.rmtree('parent_directory')
import os
# 检查路径是否存在
if os.path.exists("user/mofan"):
# 尝试删除目录
try:
os.removedirs("user/mofan")
print("user removed")
except OSError as e:
# 如果删除失败,捕获异常并打印错误信息
print(f"Error: {e}")
else:
print("user not exist")
import shutil
import os
# 检查路径是否存在
if os.path.exists("user/mofan"):
# 尝试递归删除目录及其所有内容
try:
shutil.rmtree("user/mofan")
print("user removed")
except OSError as e:
# 如果删除失败,捕获异常并打印错误信息
print(f"Error: {e}")
else:
print("user not exist")
重命名或移动文件/目录
import os
# 重命名文件或目录
os.rename('old_name.txt', 'new_name.txt')
# 移动文件或目录到新位置
os.rename('file.txt', 'new_directory/file.txt')
列出目录中的文件和目录
import os
# 列出当前目录的文件和子目录
entries = os.listdir('.')
for entry in entries:
print(entry)
使用 shutil 模块进行高级文件和目录操作
复制文件
import shutil
# 复制文件
shutil.copy('source_file.txt', 'destination_file.txt')
# 复制文件并重命名
shutil.copy('source_file.txt', 'new_directory/new_file.txt')
复制目录及其内容
import shutil
# 复制目录及其内容
shutil.copytree('source_directory', 'destination_directory')
移动文件或目录
import shutil
# 移动文件
shutil.move('source_file.txt', 'new_directory/destination_file.txt')
# 移动目录
shutil.move('source_directory', 'new_directory/destination_directory')
删除文件
import os
# 删除文件
os.remove('file_to_delete.txt')
文件目录多种检验
获取文件名:使用 os.path.basename
import os
path = '/home/user/docs/file.txt'
file_name = os.path.basename(path)
print(f"File name: {file_name}") # 输出: file.txt
获取目录名:使用 os.path.dirname
import os
path = '/home/user/docs/file.txt'
directory_name = os.path.dirname(path)
print(f"Directory name: {directory_name}") # 输出: /home/user/docs
检查路径是否存在:使用 os.path.exists
import os
path = '/home/user/docs/file.txt'
if os.path.exists(path):
print(f"Path {path} exists.")
else:
print(f"Path {path} does not exist.")
检查是否为文件或目录:分别使用 os.path.isfile 和 os.path.isdir
import os
path = '/home/user/docs/file.txt'
if os.path.isfile(path):
print(f"{path} is a file.")
elif os.path.isdir(path):
print(f"{path} is a directory.")
else:
print(f"{path} does not exist.")
检查文件或目录是否为空:使用 os.path.getsize 和 os.listdir
文件大小:os.path.getsize(path)
目录内容:os.listdir(path)
import os
file_path = '/home/user/docs/file.txt'
dir_path = '/home/user/docs'
# 检查文件是否为空
if os.path.isfile(file_path):
if os.path.getsize(file_path) == 0:
print(f"File {file_path} is empty.")
else:
print(f"File {file_path} is not empty.")
# 检查目录是否为空
if os.path.isdir(dir_path):
if not os.listdir(dir_path):
print(f"Directory {dir_path} is empty.")
else:
print(f"Directory {dir_path} is not empty.")
重新组合路径:使用 os.path.join(directory, file)
import os
directory = '/home/user/docs'
file_name = 'file_copy.txt'
new_path = os.path.join(directory, file_name)
print(f"New file path: {new_path}") # 输出: /home/user/docs/file_copy.txt
检查文件的读写权限:使用os.access(path, mode)
os.F_OK:检查文件是否存在。os.R_OK:检查文件是否可读。os.W_OK:检查文件是否可写。os.X_OK:检查文件是否可执行。
import os
path = '/home/user/docs/file.txt'
# 检查文件的读写权限
if os.access(path, os.R_OK):
print(f"File {path} is readable.")
else:
print(f"File {path} is not readable.")
if os.access(path, os.W_OK):
print(f"File {path} is writable.")
else:
print(f"File {path} is not writable.")
获取文件最后修改时间: os.path.getmtime(path)
import os
import time
path = '/home/user/docs/file.txt'
modification_time = os.path.getmtime(path)
print(f"Last modified time: {time.ctime(modification_time)}")
获取路径的绝对路径:os.path.abspath(path)
import os
relative_path = 'docs/file.txt'
absolute_path = os.path.abspath(relative_path)
print(f"Absolute path: {absolute_path}")
删除文件或目录:使用 os.remove 和 shutil.rmtree
删除文件:os.remove(path)
删除目录:shutil.rmtree(path)
import os
import shutil
file_path = '/home/user/docs/file.txt'
dir_path = '/home/user/docs/old_directory'
# 删除文件
if os.path.isfile(file_path):
os.remove(file_path)
print(f"File {file_path} deleted.")
# 删除目录
if os.path.isdir(dir_path):
shutil.rmtree(dir_path)
print(f"Directory {dir_path} deleted.")
正则表达式
更多推荐


所有评论(0)