跳至主要內容

Python 语法总结

2023年10月25日大约 43 分钟

Python 语法总结

参考教程 https://docs.python.org/zh-cn/3/tutorial/index.htmlopen in new window

基础语法

基本语法

环境说明

行和缩进

注释

变量定义

运算符

算数运算

符号含义符号含义
+加法运算*乘法运算
-减法运算/除法运算
%求余运算**幂运算
//整除运算, 向 0 取整

赋值运算符

符号含义解释
=赋值通过赋值运算即可创建新的变量
+=运算赋值将右侧的值与被赋值变量运算后赋值, 可用任意算数运算符替换 +
:=海象赋值赋值同时将右侧的值作为结果返回, 可用于简化代码, 例如 (n := 5) > 5

比较与逻辑运算

符号含义符号含义
==等于!=不等于
>大于<小于
>=大于等于<=小于等于
and逻辑与 (短路求值)or逻辑或 (短路求值)
not逻辑非

0, 空字符串, False 表示逻辑假
其余数值与字符串, True 表示逻辑真

位运算

将参与运算的变量视为二进制
最好仅用于整数

符号含义符号含义
&按位与|按位或
^按位异或~按位取反
<<左移运算符>>右移运算符

特殊运算符

符号含义解释
is身份运算符判断两个变量是否引用同一个对象
in成员运算符运算 b in a 中, a 为一个字符串或元组等容器, 当容器中有元素与 b 相同时, 返回 True

流程控制

if 条件语句

if <条件1> :
    <语句1>
elif <条件2> :
    <语句2>
else: 
    <语句3>

match 条件匹配语句

在 3.10 版本加入

match <val>:
    case <n1>:
        ...
    case <n2>:
        ...

for 循环语句

for <it> in <a>:
    ...

while 循环语句

while <exp>:
    ...

控制语句

实用函数与操作

生成整数序列

range([start, ]stop, step = 1)

要求

打印对象到控制台

print(*args)

注意

获取控制台输入

input([s])

注意

获取对象的长度

len(x)

该方法时获取任意类型长度的通用一般方法

删除变量与列表

del x

变量类型判断

isinstance(x, type) 判断变量 x 是否是类 type 的实例 (即判断类型)

类型与容器

Python 主要有以下基本内置类型

Python 中一切变量皆为对象, 一切类型皆为类, 因此使用这些类型对应名称的函数即对应的构造函数, 将其他参数传入构造函数 Python 将尝试进行变量转换, 如 int(x) 将尝试将 x 转换为整数类

数值类型

字符串

字符串表示

字符串常用操作

格式化字符串

格式化字符串时, 字符串将根据给定的参数转换格式化符号, 得到实际字符串
使用以下方式表示格式化字符串

格式化字符串的表示方法见附录字符串格式化表示方法

bytes 对象

对于 Python 的字符串, 每个索引对应一个字符, 但根据编码不同字符的实际长度不同, 默认使用的是 utf-8 编码
与字符串类似的, Python 还提供了 bytes 对象, 该对象更类似于 C++ 中的字符串, 每个索引对应一个字节即 uint8 类型的值
通过该对象可用于实现访问二进制对象内存等操作

表示 bytes 对象时

一般类型与 bytes 对象之间转换

列表

列表表示

列表常用操作

元组

元组常用操作

字典

字典由一系列键值对组成
键与值可以时任意类型, 但一般以字符串作为键类型
键一旦创建后就不可修改, 但键对应的值可以修改

字典表示

字典常用操作

容器的通用操作

对于容器类型, 有以下常用的通用操作

序列类型

对于字符串, 列表, 元组均属于序列 (Sequence) 类型, 均可使用 [] 运算符可索引字符串

此外, 类似字符串的运算, 序列均存在运算

序列解包语法, 即可将序列中个元素分别赋给一系列变量

容器迭代

容器均为可迭代对象, 可使用 for 循环迭代

可变对象与不可变对象

在 Python 中, 类被分为两种类型, 即可变对象与不可变对象
二者最基本的区别即

引用与拷贝

赋值与传递

在赋值与函数参数传递时

函数

函数基本使用

使用如下方式定义函数

def fun(a, b):
'''
<docs>    
'''
    ...
    return val

定义函数时

使用函数时

参数限定

默认值参数

变长参数与解包参数

限定参数

在实际使用时

函数的高级使用

Lambda 表达

Lambda 表达式可用于将复杂函数包装为简单形式并作为参数传递供其他函数调用
其基本语法如下

# 基本语法
fun = lambda [[参数1], [参数2], ...] : 函数体
# 示例
z = lambda x, y: x ** 3 - y

python 中的 Lambda 表达式有如下特点

flist1 = []
flist2 = []

for i in range(10):
    flist1.append(lambda val = i: print(val))
    flist2.append(lambda : print(i))

flist1[2]() # 输出 2, 循环中 i 的值作为默认值被保存下来
flist2[2]() # 输出 9, 根据函数定义, 将使用变量 i 的最新值

变量作用域

闭包与修饰器

参考 https://www.runoob.com/w3cnote/python-func-decorators.htmlopen in new window

对于闭包

对于修饰器

import time
from functools import wraps

def simple_timer(fun):
    @wraps(fun)
    def wrap_function(*args, **kwargs):
        ticks = time.perf_counter()
        res = fun(*args, **kwargs)
        used_times = time.perf_counter() - ticks
        print(f"{fun.__name__} used {used_times} second")
        return res
    return wrap_function

# 创建方法 1
@simple_timer
def fun(n):
    res = 1
    for i in range(n):
        res = res * i
    return res

# 创建方法 2
wrap_fun = simple_timer(fun)

模块

在 Python 中, 将单个 Python 文件视为一个模块, 模块名即 Python 文件名 (不包括后缀)

模块导入命令

模块导入行为

异常与错误

处理异常

异常处理语句的基本结构如下

try:
    ...
except <exc1> [as <exc_name1>]:
    ...
[except <exc2> [as <exc_name2>]:
    ...]
[else:
    ...]
[finally:
    ...]

触发异常

预定义异常处理

主要用于资源管理类

with <exp> as <target>:
    ...

该语句等价于

try:
    target = exp.__enter__()
    ...
except ... as e:
    hit_exp = True
    if not target.__exit__(e_type, e_val, traceback):
        raise
finally:
    if not hit_exp:
        target.__exit__(None, None, None)

因此

异常回溯

标准模块 traceback 可用于异常信息的回溯
虽然一般情况下 Python 能自动打印异常回溯信息, 但对于多线程等特殊情况, 可能需要手动获取异常回溯信息

模块方法 traceback.print_exception(exc, /, limit = None, file = None, chain = True) 获取异常回溯信息

警告

除了一般的异常, 还存在警告这一类特殊的异常, 警告同样继承自异常基类 Exception

警告一般使用 warning 模块下的方法 warn 触发
方法 warning.warn(message, category = ...) 触发警告

类的基础

类的使用

类的定义

使用如下的语法定义一个类

class <ClassName>[(...)]:
['''
<docs>
''']
    def __init__(self, ...):
        ...

    def fun(self, ...):
        ...

    val = ...
    ...

公有成员定义

class Example:
    # 静态成员常量
    STATIC_VARIABLE = 0

    # 类构造函数
    def __init__(self, value):
        # 公有成员变量与常量
        self.public_variable = 1
        self.PUBLIC_CONST = 2

        # 私有成员变量
        self._private_variable = value

    # 属性的创建与常见用途 (创建只读量)
    @property
    def class_value(self):
        return self._private_variable

    # 一般函数
    def set_fun(self, value):
        # 注意, 可通过 self 直接访问静态成员
        print(self.STATIC_VARIABLE)
        self._private_variable = value

    # 静态方法
    @classmethod
    def info(cls):
        # 静态成员在静态方法中的访问
        print(cls.STATIC_VARIABLE)

# 类的实例化
a = Example(10)
# 属性的使用
print(a.class_value)

私有成员定义

类的继承

参考自 https://docs.python.org/zh-cn/3/tutorial/classes.html#inheritanceopen in new window

在类创建时, 使用类名后的 () 内传入父类, 即可创建继承自父类的子类, 关于定义示例见访问父类
虽然 Python 也支持多重继承, 但除了特殊情况不建议使用, 应当通过组合代替, 因此此处不介绍

通过类的继承

访问父类

使用子类的实例时, 将首先搜索子类命名空间内的对象成员, 如果搜索不到将尝试寻找父类的属性与方法
因此对于 Python, 所有的对象方法都等同于 C++ 中的虚函数

当子类与父类具有相同名称的方法, 且需要访问父类方法时

以下为继承与父类访问的示例

class A:
    def __init__(self, value):
        self.v_A = value
        print("in A init")

    def fun(self):
        print("in A fun")

class C(A):
    def __init__(self, value):
        # 注意在子类中显式的调用父类构造函数
        super().__init__(value)
        print("in C init")
    
    def fun(self):
        print("in C fun")

obj = C(10)
# 类外调用父类方法
super(C, obj).fun()
# 没有冲突时, 则可以直接调用父类的成员
print(obj.v_A)

抽象基类

Python 中, 需要通过继承模块 abc 下的类 ABC 创建抽象基类

from abc import ABC, abstractmethod

class Base(ABC):
    def __init__(self, a):
        self.a = a

    def fun(self):
        print(self.a)

    # 一般抽象方法
    @abstractmethod
    def set_value(self, value):
        ...

    # 抽象属性
    @property
    @abstractmethod
    def value(self) -> int:
        ...

    # 抽象静态方法
    @classmethod
    @abstractmethod
    def count(cls):
        ...

使用抽象基类时注意

运算符重载与类型转换

类的函数使用名称 __xxx__ 时表示的是特殊方法, 这些方法通常都有实际含义, 如构造函数 __init__
以下为一些用于运算符重载与类型转换的特殊方法

注意到, 重载运算符时, 对象总是位于运算符的左侧, 因此如果希望正确发挥重载运算符的效果, 二元运算时尽量让对象位于运算符左侧, 一般值位于右侧

类的高级使用

类型模拟

通过重载一套运算符, 可以完成类关于特定类型的模拟, 具体可参考官方文档

数据类

在部分情况下, 希望将类以类似 C++ 的 struct 的方式使用, 则可以通过来自模块 dataclasses 的修饰器 dataclass 创建修饰类
示例如下

from dataclasses import dataclass

@dataclass
class <DataClass>:
    <key1> : <type1>
    <key2> : <type2> = <default_val2>

数据类的高级使用

枚举类

参考文档 https://docs.python.org/zh-cn/3/howto/enum.htmlopen in new window

在 Python 中, 没有直接提供枚举类型, 但可通过继承模块 emun 下的类实现各种特性的枚举类

枚举类基础定义

基础枚举基类为 Enum, 定义枚举类型时, 继承枚举基类, 通过定义类的静态成员确定枚举量的名称, 将静态成员的值作为枚举量对应的值
例如

from enum import Enum
class Color(Enum):
    RED = 0
    BLUE = 1
    GREEN = 2

定义枚举类时注意

枚举类型的使用

对于继承自 Enum 的枚举类型, 有以下常用操作 (此处以上文定义的枚举类型举例)

标志位类型

from enum import Flag, auto

class Color(Flag):
    RED = auto()
    BLUE = auto()
    GREEN = auto()
    WHITE = RED | BLUE | GREEN
    BLACK = 0

数据类支持枚举类

如果希望以数据类对象作为枚举类的值, 应使用以下方式定义枚举类

from enum import Enum
from dataclasses import dataclass

@dataclass
class ColorInfo:
    color_name : str
    color_value : int

class Color(ColorInfo, Enum):
    RED = ("red", 0xFF0000)
    BLUE = ("blue", 0x0000FF)
    GREEN = ("green", 0x00FF00)

# 使用示例, 创建枚举量与颜色名的映射
color_name_dict = {value : value.color_name for value in Color.__members__.values()}

附录

字符串格式化表示方法

格式化字符串的表示方法如下
参考自
http://www.cppcns.com/jiaoben/python/287553.htmlopen in new window
https://zhuanlan.zhihu.com/p/295621558open in new window

# 基本替换
"y = {}x + {}".format("a", 12)
# 输出 "y = ax + 12"

# 按参数位置替换
"y = {0}x^2 +{1}x + {0}".format("a", 12)
# 输出 "y = ax^2 +12x + a"

# 按参数名称替换
"y = {num}x^2 +{param}x + {num}".format(num = 12, param = "a")
# 输出 "y = 12x^2 +ax + 12"
# 宽度控制
# 左对齐
print("out:{str:<10}\n    0123456789".format(str = "Hello"))
# 输出
# out:Hello     
#     0123456789

# 右对齐
print("out:{str:>10}\n    0123456789".format(str = "Hello"))
# 输出
# out:     Hello
#     0123456789

# 居中对齐
print("out:{str:^10}\n    0123456789".format(str = "Hello"))
# 输出
# out:  Hello   
#     0123456789
# 保留 n 位小数
print("{pi:.3f}".format(pi = 3.14159))
# 输出 3.142

# 百分数
print("{pi:.2%}".format(pi = 3.14159))
# 输出 314.16%

# 科学计数法
print("{pi:.3e}".format(pi = 314159))
# 输出 3.142e+05

# 带符号保留
print("{pi:+.3f}".format(pi = 3.14159))
# 输出 +3.142

# 千位分隔符
print("{num:,}".format(num = 3141.5926))
# 输出 3,141.5926

# 对齐
print("out: {pi:0^10.2f}".format(pi = 3.14159))
# 输出 out: 0003.14000

# 十六进制
print("{pi:#X}".format(pi = 314159))
# 输出 0X4CB2F
"\\frac{{{y}}}{{x}}".format(y = 10)
> '\frac{10}{x}'

对于以上各种格式可以混合使用, 具体规则如下

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill            ::=  <any character>
align           ::=  "<" | ">" | "=" | "^"
sign            ::=  "+" | "-" | " "
width           ::=  digit
grouping_option ::=  "_" | ","
precision       ::=  digit
type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

推导式

通过字符串, 从一个数据序列构建另一个序列, 可以被 input 函数解析或直接使用表示变量的值

列表推导式

res = [out_exp_res for out_exp in input_list if condition]
  1. res 结果列表
  2. out_exp_res 遍历列表元素的表达式, 返回值作为列表元素
  3. out_exp 表达式中的迭代变量
  4. input_list 输入列表(可迭代类型)
  5. condition 迭代变量满足条件
* new_names = [it.upper() for it in names if len(it) > 3]

字典推导式

res = { key_expr: value_expr for value in collection if condition }
  1. res 结果字典
  2. key_expr 遍历列表元素的表达式, 返回值作为键名
  3. value_expr 遍历列表元素的表达式, 返回值作为键值
  4. value 表达式中的迭代变量
  5. collection 输入列表(可迭代类型)
  6. condition 迭代变量满足条件
newdict = {key:len(key) for key in listdemo}

集合推导式

res = { expression for item in Sequence if conditional }

与列表相同, 使用 {} 包裹

元组推导式

res = (expression for item in Sequence if conditional )

与列表相同, 使用 () 包裹
注意元组推导式返回的是生成器对象, 不是元组
生成器对象不直接保存数据, 而是在迭代时计算结果
需要使用方法 res = tuple([生成器]) 生成元组
例如 name_list = tuple(name_list[key] for key in bind_enum.__members__.keys())

分支推导式

res = [结果1 if 判断条件 else 结果2 for 变量名 in 原列表]