这篇博客旨在帮助 C++ 选手快速入门 Python(皮炎通红)。当然 python 的使用过于灵活,而且自带的方法太多,这篇博客尽我所能列举与算法竞赛有关的内容。
循环结构、选择结构与代码规范
python 只用 range_based_for 和 while 循环。比较特殊的是,python有 for else 语法,只是用处非常少。
python 的分支结构使用 if elif else。
python 使用 : 开始一段代码块,使用缩进区分附属关系。python 是强格式语言,与 C++ 不同。
输入输出
python 使用 input() 函数进行输入。input() 是按照行读入的,这意味着它会一直读到换行结束,返回一个从行首开始去掉 '\n' 的字符串。
1 2 3 4 |
input(prompt) # input 的函数原型 # 它会先输出字符串 prompt 然后读入一个字符串 # 如果省略了 prompt 参数,用户将不会看到任何提示信息 |
当 input() 读到 EOF 时,会抛出一个 EOF ERROR。
1 2 3 4 5 |
Traceback (most recent call last): File "E:\coding\temp\test.py", line 2, in <module> s = input() EOFError: EOF when reading a line |
还有一种方式是使用 sys.stdin 来读入。但是请注意,如果代码运行在 IDLE 或者其他没有终端的地方时,stdin 默认是 None,这时就不能使用它来读入了【参见 stackoverflow】。
1 2 3 4 5 6 7 8 |
import sys # 逐行遍历标准输入 for line in sys.stdin: # 处理每一行数据 line = line.strip() # 去除行末的换行符 print("你输入的行是:", line) |
同样的,python 使用 print() 进行输出。 print() 支持不定长参数,它会用 ' ' 隔开每个参数,而且默认在结尾输出换行。 print() 的好处在于 py 中自带的类型都自带了 __str__() 或者 __repr__() 的魔术方法(Magic Methods),甚至如果这两种方法都没有定义, print() 也会直接输出对象的类型信息和内存地址。
我们来看 print() 的函数原型。其中的 * 表示了压缩,它会把输入的参数压缩成一个列表传入函数。注意:这里的 * 写在函数定义中,如果它出现在函数调用中,它就成了解压的操作(压缩的逆运算)。
1 2 |
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) |
看一些示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 输出一个字符串 print("Hello, world!") # Hello, world! # 输出多个对象,以空格分隔 x = 10 y = 20 print("The value of x is", x, "and the value of y is", y) # The value of x is 10 and the value of y is 20 # 使用 sep 参数自定义分隔符 print("apple", "banana", "cherry", sep=", ") # apple, banana, cherry # 使用 end 参数自定义结尾 print("Hello", end="") print(", world!") # Hello, world! # 输出到文件 with open("output.txt", "w") as f: print("This is written to a file.", file=f) # 立即刷新输出缓冲区 print("This message is flushed immediately.", flush=True) # This message is flushed immediately. |
我们可以使用格式化字符串或者 f 字符串进行输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name = "Alice" age = 30 # 使用 f 字符串格式化字符串 message = f"Hello, my name is {name} and I am {age} years old." print(message) name = "Alice" age = 30 message = "Hello, my name is %s and I am %d years old." % (name, age) print(message) name = "Alice" age = 30 message = "Hello, my name is {} and I am {} years old.".format(name, age) print(message) num = 3.141592653589793 formatted_num = "{:.2f}".format(num) print(formatted_num) # 输出: 3.14 num = 3.141592653589793 formatted_num = f"{num:.2f}" print(formatted_num) # 输出: 3.14 num = 3.141592653589793 formatted_num = "%.2f" % num print(formatted_num) # 输出: 3.14 |
注释
python 使用 # 注释,等价于 C++ 中的 //。当然还可以使用三引号来进行多行注释,等价于 C++ 中的 /**/
1 2 3 4 5 6 7 8 9 10 11 |
# 这是一个单行注释 ''' 这是一个多行注释 这个注释可以跨越多行 ''' """ 这也是一个多行注释 """ |
类型
- 数字类型:(注意 python 自带高精)
- 整数(int):表示整数值,如 -10、0、42 等。
- 浮点数(float):表示带有小数点的数值,如 3.14、-0.001、2.0 等。
- 复数(complex):表示具有实部和虚部的复数,如 3+4j、-2-5j 等。
- 布尔类型:
- 布尔值(bool):表示逻辑值,只有两个取值:True 和 False。(注意首字母是大写的)
- 序列类型:(注意 python 无数组)
- 字符串(str):表示文本序列,由单引号、双引号或三引号括起来的字符序列,如 'hello'、"world"、'''Python''' 等。(注意是 str 不是 string)
- 列表(list):表示有序可变序列,由方括号括起来的一组值,值之间用逗号分隔,如 [1, 2, 3]、['a', 'b', 'c'] 等。
- 元组(tuple):表示有序不可变序列,由圆括号括起来的一组值,值之间用逗号分隔,如 (1, 2, 3)、('a', 'b', 'c') 等。
- 映射类型:
- 字典(dict):表示键值对的集合,由花括号括起来,键值对之间用冒号分隔,如 {'name': 'Alice', 'age': 30}。(注意这是哈希表不是平衡树)
- 集合类型:
- 集合(set):表示无序不重复元素的集合,由花括号括起来,元素之间用逗号分隔,如 {1, 2, 3}、{'a', 'b', 'c'}。(注意这是哈希表不是平衡树,空集使用 set() 构造而非 {},后者表示空字典)
- NoneType 类型:
- NoneType:表示空值或空对象,只有一个取值:None。
变量与表达式
在 python 中变量无需声明类型,编译器会自动判断类型。而且 python 是一种动态类型语言,这意味着同一个变量的类型是可以改变的,当然,你最好不要这么做。变量名命名与 C++ 相同,不过注意 python 中类的名称必须是首字母大写。值得注意的是,python 支持中文作为变量名。
在 python 中赋值表达式的形式与 C++ 不同:
1 2 3 4 5 6 7 8 9 |
a, b, c = 1, 2, 3 # 等价于 C++ 中的 a=1,b=2,c=3 注意在 python 中这么写是错误的 # 在 python 中,会首先计算等号右边的表达式 然后再赋值给左边 # 这意味着你可以直接实现交换 a, b = b, a # 等价于 C++ 中的 std::swap(a, b); # 实际上等号在做的事情是将右边的序列依次赋值给左边 # 也就会它会先做一个压缩的操作,在做一个解压的操作 a = [1, 2, 3] a, b, c = a # 这就是一个解压操作的示例 |
我们来看 C++ 中的表达式:
- 算数表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# 加法(+) result_addition = 10 + 5 print("加法结果:", result_addition) # 减法(-) result_subtraction = 10 - 5 print("减法结果:", result_subtraction) # 乘法(*) result_multiplication = 10 * 5 print("乘法结果:", result_multiplication) # 除法(/)注意 int/int 的返回值为 float result_division = 10 / 5 print("除法结果:", result_division) # 整除(//) # 请注意 python 中的整除是向下取整,而不是 C++ 中的向0取整 result_floor_division = 10 // 3 print("整除结果:", result_floor_division) # 取模(%) result_modulo = 10 % 3 print("取模结果:", result_modulo) # 幂运算(**)O(N) result_power = 10 ** 2 print("幂运算结果:", result_power) # 使用括号改变运算顺序 result_with_parentheses = (10 + 5) * 2 print("使用括号改变运算顺序结果:", result_with_parentheses) |
- 比较表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# 简单的比较表达式 x = 10 y = 5 # 大于(>) result_greater_than = x > y print("x 是否大于 y:", result_greater_than) # 小于(<) result_less_than = x < y print("x 是否小于 y:", result_less_than) # 等于(==) result_equal_to = x == y print("x 是否等于 y:", result_equal_to) # 不等于(!=) result_not_equal_to = x != y print("x 是否不等于 y:", result_not_equal_to) # 大于等于(>=) result_greater_than_or_equal_to = x >= y print("x 是否大于等于 y:", result_greater_than_or_equal_to) # 小于等于(<=) result_less_than_or_equal_to = x <= y print("x 是否小于等于 y:", result_less_than_or_equal_to) # 连续使用 z = 11 print(x <= y <= z) # 等价于 x <= y and y <= z |
- 逻辑表达式
1 2 3 4 5 |
x = 10 y = 5 result = (x > 5) and (y < 10) # 注意优先级 not>and>or # 注意没有 && || 这种东西 |
- 成员表达式:用于检查一个值是否属于某个集合的表达式,结果是布尔值 True 或 False。成员运算符包括 in 和 not in。例如:
1 2 3 4 5 6 7 |
x = 10 numbers = [1, 2, 3, 4, 5] result = x in numbers # False result = x not in numbers # True # 注意时间复杂度 # 列表 O(N) 字典和集合 O(1) |
- 身份表达式:用于检查两个对象是否引用同一个内存地址的表达式,结果是布尔值 True 或 False。身份运算符包括 is 和 is not。例如:
1 2 3 4 |
x = [1, 2, 3] y = [1, 2, 3] result = x is y |
- 位运算表达式:用于对整数进行位运算的表达式,包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>)等运算。例如:
1 2 3 4 |
x = 5 y = 3 result = x & y |
- 列表表达式:支持多层嵌套
1 2 3 4 5 6 7 |
[expression for item in iterable if condition] # 使用列表表达式过滤偶数 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] even_numbers = [x for x in numbers if x % 2 == 0] print(even_numbers) # 输出: [2, 4, 6, 8, 10] |
- 三目运算:这与 C++ 中的三目运算类似
1 2 |
expression1 if condition else expression2 |
函数和 lambda 表达式
python 中函数的定义需要写上 def 。定义可以写在任何位置,可以是循环体或者函数体中,不过要注意变量的作用域。
1 2 3 4 5 6 7 |
def greet(name): """这是一个简单的问候函数""" print("Hello, " + name + "!") # 调用函数 greet("Alice") |
当然你可以加上类型修饰使得函数更加清晰。这样会使得代码更加安全。
1 2 3 4 5 6 7 8 9 10 |
from typing import List def square_list(nums: List[int]) -> List[int]: """将输入列表中的每个元素平方,并返回结果列表""" return [num ** 2 for num in nums] # 调用函数 result = square_list([1, 2, 3, 4, 5]) print(result) # 输出: [1, 4, 9, 16, 25] |
在函数定义中,你可以使用 * 和 ** 来压缩参数。* 表示压缩成列表,而 ** 表示压缩成字典。
1 2 3 4 5 6 7 |
def example_func(*args, **kwargs): print("Positional arguments (*args):", args) print("Keyword arguments (**kwargs):", kwargs) # 调用函数 example_func(1, 2, 3, name='Alice', age=30) |
而函数调用的过程中,* 和 ** 用来解压参数。* 用以解压列表,** 用以解压字典。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def example_func(a, b, c): print("a:", a) print("b:", b) print("c:", c) # 使用*解包列表 args_list = [1, 2, 3] example_func(*args_list) # 使用**解包字典 kwargs_dict = {'a': 1, 'b': 2, 'c': 3} example_func(**kwargs_dict) |
我们来看 lambda 表达式。lambda 表达式是一种用于创建匿名函数的特殊语法。它允许你在代码中创建简单的函数,而不需要使用 def
关键字定义一个常规函数。
lambda表达式的基本语法是:
1 2 |
f = lambda x: int(x + 0.5) # 这是一个四舍五入的lambda表达式示例 |
文件读写
python 使用 open() 函数打开一个文件。
1 2 |
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) |
我们可以把文件存入一个变量,例如 f = open(file, 'w')
。但是这样不够安全,我们可以使用 with 来打开一个文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 逐行读取文件内容 with open('example.txt', 'r') as file: for line in file: print(line) # 打开文件并写入内容 with open('example.txt', 'w') as file: file.write('Hello, world!') # 打开文件并读取内容 with open('example.txt', 'r') as file: content = file.read() print(content) |
迭代器
与 C++ 中的迭代器相同。
迭代器(Iterator)是Python中一种用于遍历可迭代对象(Iterable)的对象。可迭代对象是可以返回一个迭代器的任何对象,包括列表、元组、字典、集合、字符串等。
迭代器提供了一种惰性计算的方式,它允许你逐个访问可迭代对象的元素,而不需要一次性将所有元素加载到内存中。这对于处理大型数据集或无限序列(如生成器)非常有用,因为它可以节省内存并提高效率。
迭代器对象必须实现两个方法:
__iter__()
方法:返回迭代器对象自身,通常直接返回self
。__next__()
方法:返回可迭代对象的下一个元素,如果没有元素可以返回,则抛出StopIteration
异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 创建一个迭代器对象 my_iterator = iter([1, 2, 3, 4, 5]) # 使用 next() 函数获取下一个元素 print(next(my_iterator)) # 输出: 1 print(next(my_iterator)) # 输出: 2 print(next(my_iterator)) # 输出: 3 print(next(my_iterator)) # 输出: 4 print(next(my_iterator)) # 输出: 5 # 在迭代器耗尽时,next() 函数会抛出 StopIteration 异常 try: print(next(my_iterator)) except StopIteration: print("迭代器已经耗尽") |
生成器
生成器(Generator)是一种特殊的迭代器,它以一种延迟计算的方式生成值,而不是一次性产生所有值并保存在内存中。生成器可以通过函数中的 yield
关键字来定义,也可以使用生成器表达式或生成器函数来创建。
生成器函数:通过在函数中使用 yield
关键字来定义生成器。
1 2 3 4 5 6 7 |
def my_generator(): yield 1 yield 2 yield 3 # 使用生成器函数创建生成器对象 gen = my_generator() |
生成器表达式:类似于列表推导式,但使用圆括号而不是方括号。
1 2 3 |
# 使用生成器表达式创建生成器对象 gen = (x for x in range(3)) |
修饰器
修饰器(Decorator)是 Python 中一种强大的元编程特性,它允许修改或增强函数或类的行为,而无需修改它们的源代码。修饰器本质上是一个可调用的对象,它接受一个函数或类作为参数,并返回一个新的函数或类。通过将修饰器应用于函数或类,我们可以在不修改原始函数或类定义的情况下,实现一些额外的功能,如日志记录、性能分析、权限控制等。
修饰器的基本结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def decorator(func): def wrapper(*args, **kwargs): # 在函数调用之前可以执行一些操作 result = func(*args, **kwargs) # 在函数调用之后可以执行一些操作 return result return wrapper # 使用 @ 符号将修饰器应用于函数 @decorator def some_function(): # 函数的主体逻辑 pass |
下面是一个统计函数运行时间的修饰器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import time def calculate_time(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"函数 {func.__name__} 运行时间为: {end_time - start_time} 秒") return result return wrapper # 使用 @ 符号将修饰器应用于函数 @calculate_time def my_function(): # 模拟函数执行一些耗时操作 time.sleep(2) print("函数执行完成") # 调用被修饰的函数 my_function() |
在这个示例中,我们定义了一个名为 calculate_time
的修饰器,它接受一个函数作为参数,并返回一个新的包装函数 wrapper
。在 wrapper
函数中,我们记录了函数调用开始和结束的时间,并计算了函数的运行时间。最后,我们使用 @calculate_time
将修饰器应用于 my_function
函数,这样当我们调用 my_function()
时,修饰器就会自动记录函数的运行时间,并输出到控制台。
面向对象和魔术方法
之后的内容有时间再写。
发表回复