变量

变量类型

  • int: 二进制 (0b100); 八进制 (0o100); 十六进制 (0x100); 十进制 (100)
  • float: 数学写法 (123.456); 科学计数法 (1.23456e2)
  • str: ‘’; “”
  • bool: True; False

变量命名

  • 惯例 1:受保护的变量通常用单个下划线开头
  • 惯例 2:私有的变量通常用两个下划线开头

操作变量方法

  • type(a): 检查类型 <class 'int'>
  • iint(): 将一个数值或字符串转换成整数,可以指定进制
  • float(): 将一个字符串转换成浮点数
  • str(): 将指定的对象转换成字符串形式,可以指定编码方式
  • chr(): 将整数转换成对应的字符串
  • ord(): 将字符串转换成对应的整数

运算符

运算符 描述
[][:] 索引、切片
**
~+- 按位取反、正号、负号
*/%// 乘、除、模、整除
+- 加、减
>><< 右移、左移
& 按位与
^ 按位异或、按位或
<=<>>= 小于等于、小于、大于、大于等于
==!= 等于、不等于
isis not 身份运算符
innot in 成员运算符
notorand 逻辑运算符
=+=-=*=/=%=//=**=&=丨=^=>>=<<= 赋值运算符
  • 算数运算符
  • 赋值运算法
    • 海象运算符

      Python 3.8 中引入了一个新的赋值运算符 :=, 将运算符右侧的值赋值给左边的变量,与赋值运算符不同的是,运算符右侧的值也是整个表达式的值

      1
      2
      print((a := 10))  # 10
      print(a) # 10
  • 比较运算符
  • 逻辑运算符

格式化

  1. %s 格式

    1
    print('%.1f千米 = %.1f米' % (m, n))
    • %s, 表示 str 类型变量; %d, 表示 int 类型变量; %f, 表示 float 类型变量。.1 表示一位小数
  2. f-string 格式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    print(f'{m:.1f}千米 = {n:.1f}米')
    print(f'The number {number:0>5d} is padded with zeros.') # 左填充零,宽度为 5

    name = "Charlie"
    message = f"""
    Hello, {name}!
    Welcome to our website.
    """
    print(message)
    • 指定格式: :.xf 表示保留 x 位小数;:.x% 表示百分比格式;:.xe 表示科学计数法;:, 表示逗号隔开
    • 填充和对齐: 0>5d, 左填充零,宽度为 5; <5d, 左对齐,宽度为 5; ^5d, 居中对齐,宽度为 5
    • 多行f-string: 使用三引号 (‘’’ 或 “””) 定义字符串

分支

if / elif / else

match / case

1
2
3
4
match code:
case 404 | 403: xxx
case 500 | 501: xxx
case _: xxx

循环

for-in

1
2
for _ in range(10):
print('hello, world')
  • range(start, end, step): 区间 [start, end), step 步长

while

列表

创建列表

1
2
3
4
5
# 直接定义
listArr = []

# list()
listArr = list(range(10))

列表运算

1
2
3
4
5
6
7
8
9
10
11
baseList1 = [1, 2, 3]
baseList2 = [4, 5, 6]
# 拼接 +
print(baseList1 + baseList2)
# 重复 *
print(baseList1 * 2)
# in / not in
print(10 in baseList1)
# 切片 [start:end:stride]
print(baseList1[1:3:1])
baseList1[1:3] = [10, 11] # 修改元素

列表方法

  • append(): 添加到最后一个
  • remove(): 删除元素,多个元素只会删除第一个匹配到的元素
  • pop(): 默认删除列表中的最后一个元素,也可以给一个位置,删除指定位置的元素,并返回
    • del 关键字: 删除位置元素
  • clear(): 清空
  • index(ele, start, end): 查找元素索引,可选 start end,查找的起始结束位置
  • count(): 统计元素在列表中出现的次数
  • sort(cmp=None, key=None, reverse=False): 排序
  • reverse(): 反转

列表生成式

列表生成式创建简单,性能也会优于循环操作。Python 解释器的字节码指令中有专门针对生成式的指令 (LIST_APPEND 指令);而for循环是通过方法调用 (LOAD_METHODCALL_METHOD 指令)的方式为列表添加元素,方法调用本身就是一个相对比较耗时的操作

1
2
3
4
5
6
7
8
9
# 创建一个取值范围在 1 到 99 且能被 3 或者 5 整除的数字构成的列表
items = [i for i in range(1, 100) if i % 3 == 0 or i % 5 == 0]

# 创建一个平方数的列表
nums1 = [35, 12, 97, 64, 55]
nums2 = [num ** 2 for num in nums1]

# 创建一个二维数组
items = [[random.randrange(60, 101) for _ in range(3)] for _ in range(5)]

元组

元组是不可变类型,其他方法基本和 list 一致

  • 定义一元组需要加一个逗号,避免和 () 字面量冲突
1
2
3
4
5
6
7
8
9
10
a = ()
print(type(a)) # <class 'tuple'>
b = ('hello')
print(type(b)) # <class 'str'>
c = (100)
print(type(c)) # <class 'int'>
d = ('hello', )
print(type(d)) # <class 'tuple'>
e = (100, )
print(type(e)) # <class 'tuple'>

打包和解包

解包操作要求元素个数和变量个数严格对应,否则会报错
* 变量解包余下的值,此变量会输出一个列表
解包语法对所有可序列的都成立,比如列表、range()、字符串等

1
2
3
4
5
6
7
8
9
10
11
12
# 打包操作
a = 1, 10, 100, 1000
print(type(a)) # <class 'tuple'>
print(a) # (1, 10, 100, 1000)
# 解包操作
i, j, k, l = a
print(i, j, k, l) # 1 10 100 1000
# i, j, k = a # ValueError: too many values to unpack (expected 3)
# i, j, k, l, m, n = a # ValueError: not enough values to unpack (expected 6, got 4)

i, j, *k = a
print(i, j, k) # 1 10 [100, 1000]

变量交换

对于两个或三个变量,交换操作直接使用 ROT_TWOROT_THREE 指令实现;对于多个变量交换,需要借助打包解包的方式实现

1
2
a, b = b, a
a, b, c = b, c, a

tuple vs list

  1. tuple 不可变,更适合多线程环境,减少并发访问变量的同步开销
  2. 不可变类型的创建花销明显优于可变类型。可以使用 timeit 模块进行测试

    1
    2
    3
    4
    import timeit

    print('%.3f 秒' % timeit.timeit('[1, 2, 3, 4, 5, 6, 7, 8, 9]', number=10000000)) # 0.740 秒
    print('%.3f 秒' % timeit.timeit('(1, 2, 3, 4, 5, 6, 7, 8, 9)', number=10000000)) # 0.118 秒
  3. 相互转换: list(),tuple()

字符串

字符串表示

  • \: 转义
  • rR: 原始字符串
  • 进制及 Unicode 编码
1
2
3
4
5
6
7
8
9
10
s1 = 'hello, world!'
s2 = '''hello,
wonderful
world!'''

t1 = '\'hello, world!\''
t2 = r'\\hello, world!\\'

r1 = '\141\142\143\x61\x62\x63'
r2 = '\u4F60\u597D'

字符串运算

  • +*: 拼接、重复
  • innot in: 包含
  • [][:]: 切片
  • ord(): 获取字符编码进行比较

字符串方法

大小写

  • capitalize(): 首字母大写
  • title(): 每个单词首字母大写
  • upper(): 大写
  • lower(): 小写

查找

  • find(str, start=0): 查找,返回索引,失败返回 -1
  • index(str, start=0): 查找,返回索引,失败报错
  • rfind(): 逆向查找
  • rindex(): 逆向查找

性质判断

  • startswith()
  • endswith()
  • isdigit(): 完全由数字构成
  • isalpha(): 完全由字母构成
  • isalnum(): 由字母和数字构成

格式化

  • center(width, fillchar): 居中
  • ljust(width, fillchar): 左对齐
  • rjust(width, fillchar): 右对齐
  • zfill(width): 左侧填充零,保留正负号的位置。print(‘-33’.zfill(5)) # -0033

修剪

  • strip(char): 修剪左右两端指定字符,默认空格
  • lstrip()
  • rstrip()

集合

集合运算

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
34
35
36
37
set1 = {1, 2, 3, 4, 5, 6, 7}
set2 = {2, 4, 6, 8, 10}

# 交集
print(set1 & set2) # {2, 4, 6}
print(set1.intersection(set2)) # {2, 4, 6}

# 并集
print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8, 10}
print(set1.union(set2)) # {1, 2, 3, 4, 5, 6, 7, 8, 10}

# 差集
print(set1 - set2) # {1, 3, 5, 7}
print(set1.difference(set2)) # {1, 3, 5, 7}

# 对称差
print(set1 ^ set2) # {1, 3, 5, 7, 8, 10}
print(set1.symmetric_difference(set2)) # {1, 3, 5, 7, 8, 10}

# |=
set1 |= set2
# set1.update(set2)
print(set1) # {1, 2, 3, 4, 5, 6, 7, 8, 10}

# &=
set1 &= set2
# set1.intersection_update(set2)
print(set1) # {2, 4, 6}

# -=
set2 -= set1
# set2.difference_update(set1)
print(set2) # {8, 10}

# 子集、超集 > < <= >= issubset issuperset
print(set1.issubset(set2))
print(set2.issuperset(set1))

集合方法

  • add()
  • discard(): 删除
  • remove(): 删除,不存在报错
  • pop(): 随机删除一个元素并返回
  • clear()
  • isdisjoint(): 判断两个集合是否有相同元素

frozenset

简单理解为不可变的 set,拥有相同的方法

字典

创建字典

1
2
3
4
5
6
7
8
9
10
11
12
13
# dict 构造器
dic = dict(a='1', b=2, c=3, d=4, e='5')
print(dic) # {'a': '1', 'b': 2, 'c': 3, 'd': 4, 'e': '5'}

# 内置函数zip压缩两个序列
items1 = dict(zip('ABCDE', '12345'))
print(items1) # {'A': '1', 'B': '2', 'C': '3', 'D': '4', 'E': '5'}
items2 = dict(zip('ABCDE', range(1, 10)))
print(items2) # {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5}

# 字典生成式
items3 = {x: x ** 3 for x in range(1, 6)}
print(items3) # {1: 1, 2: 8, 3: 27, 4: 64, 5: 125}

字典方法

  • get(key, defaut=None): 获取,获取不到则返回默认值
  • keys(): 键列表
  • values(): 值列表
  • items(): 键值元组列表
  • update()、|: 合并字典
  • pop(): 删除,返回键对应的值,键不存在报错
  • popitem(): 删除,返回键值的元组
  • clear()

函数

参数

强制位置参数: / 之前的参数只能按照参数位置来接收参数; 关键字参数: *之后的参数只能通过 “参数名=参数值” 的方式来传递和接收参数

1
2
3
4
5
6
7
8
9
def func(a, b, /, c, *, d):
print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)

func(1, 2, 3, d=4) # 输出结果为:a: 1, b: 2, c: 3, d: 4
func(1, b=2, c=3, d=4) # 报错,因为参数 b 是位置参数,不能使用关键字传参
func(1, 2, c=3, d=4) # 输出结果为:a: 1, b: 2, c: 3, d: 4,使用了位置传参和关键字传参

可变参数: *args 表示 args 可以接收0个或任意多个参数,args 会组装成一个元组; *kwargs 表示 kwargs可以接收0个或任意多个关键字参数,kwargs 会组装成一个字典

1
2
3
4
5
def func(*args, **kwargs):
print(args)
print(kwargs)

func(1, 2, 3, a=10, b=20, c=30) # (1, 2, 3) {'a': 10, 'b': 20, 'c': 30}

内置函数

内置函数

函数应用

高阶函数

Lambda函数

偏函数

固定函数的某些参数,生成一个新的函数。使用 functools 模块的 partial 函数来创建偏函数

1
2
3
4
5
import functools

int2 = functools.partial(int, base=2)
int8 = functools.partial(int, base=8)
int16 = functools.partial(int, base=16)

装饰器

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
34
35
36
37
import random
import time

from functools import wraps # 取消装饰器

def record_time(func):

@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__}执行时间: {end - start:.2f}秒')
return result

return wrapper


@record_time
def download(filename):
print(f'开始下载{filename}.')
time.sleep(random.random() * 6)
print(f'{filename}下载完成.')


@record_time
def upload(filename):
print(f'开始上传{filename}.')
time.sleep(random.random() * 8)
print(f'{filename}上传完成.')

# 调用装饰后的函数会记录执行时间
download('JavaScript从入门到精通.pdf')
upload('JavaScript从入门到放弃.pdf')
# 取消装饰器的作用不记录执行时间
download.__wrapped__('Python从入门到精通.pdf')
upload.__wrapped__('Python从入门到放弃.pdf')

带参数的装饰器,lru_cache 装饰器缓存函数执行结果

1
2
3
4
5
6
7
8
9
10
11
12
from functools import lru_cache


@lru_cache()
def fib(n):
if n in (1, 2):
return 1
return fib(n - 1) + fib(n - 2)


for i in range(1, 51):
print(i, fib(i))

class

__init__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Point:

def __init__(self, x=0, y=0, name='X点'):
"""初始化方法
:param x: 横坐标
:param y: 纵坐标
:param name: 点名称
"""
self.x = x
self.y = y
self.__name = name # __ 表示私有变量,外部无法直接访问

A = Point(1, 1, 'A点')
print(A.__name) # AttributeError: 'Point' object has no attribute '__name'
print(A._Point__name) # A点

__slots__

限制类添加动态属性

1
2
3
4
5
6
7
8
9
10
11
class Student:
__slots__ = ('name', 'age')

def __init__(self, name, age):
self.name = name
self.age = age


stu = Student('小明', 12)
# AttributeError: 'Student' object has no attribute 'sex'
stu.sex = '男'

staticmethod

声明静态方法

1
2
3
4
5
6
7
8
class Person(obj):

def __init__:
pass

@staticmethod
def is_male(sex):
pass

classmethod

声明类方法,第一个参数为类对象本身

1
2
3
4
5
6
7
8
class Person(obj):

def __init__:
pass

@classmethod
def is_male(self, sex):
pass