1 基础

Python是一种高级、通用、解释型的编程语言,由荷兰的吉多·范罗苏姆于1990年代初设计。它因其简单易学、功能强大和广泛的应用领域而备受欢迎。

2 基本数据类型

2.1 python数字类型

2.1.1 数据类型的组成

2.1.1.1 整数—不同进制的转换

默认输入十进制

  • 注:二进制0b、八进制0o、十六进制0x
2.1.1.1.1 十进制与其他进制的转换
1
2
3
4
a = bin(16)
b = oct(16)
c = hex(16)
print(a,b,c)

image-20240613165329877

  • 注:上述转化后均为字符串型
2.1.1.1.2 其他进制转换成十进制
1
2
d = int(a,2)
e = int(b,8)

2.1.1.2 浮点数—不确定性

不确定小数问题

1
print(0.1+0.2)

image-20240614121041171

  • 注:计算机采用二进制小数来表示小数部分
  • 部分小数不能完全用二进制小数表示
  • 通常情况下不会影响精度

四舍五入获取精度解

1
2
b = roud(a,1)
print(b)

2.1.1.3 复数—a+bj

j可大写小写

2.1.2 数学运算操作符

1
2
3
4
5
6
7
 1.加减乘除 +-\*/

2.取反 -

3.乘方运算 **

4.整数商// 和模运算%
1
13//5 #2
1
13%5 #3
2.1.2.1.1 几点说明
  • 整数与浮点数运算为浮点数
  • 除法运算为浮点数

2.1.3 数字运算操作函数

2.1.3.1 求绝对值 abs()

2.1.3.2 求幕次方 pow()

1
pow(2,5)#等价于2**5
1
pow(2,5,3)#等价于2**5%3

2.1.3.3 四舍五入 round(x,n)

默认四舍五入为整数

1
round(1.612,2)

2.1.3.4 整数商和模运算 divmod(x,y)

等价于返回二元元组(x//y,x%y)

1
divmod(13,5)//(2,3)

2.1.3.5 序列最大/最小值 max() min()

1
max(3,2,6,9,4,5)//9
1
2
a = [3,2,3,6,9,4,5]
print(max(a))//9

2.1.3.6 求和sum(x)

1
print(sum([1,2,3,4,5,6,7,8,9]))//45

2.1.3.7 借助科学计算库 math\scipy\numpy

1
2
3
4
import math
print(math.exp(1)) //指数运算 e^x
print(math.log2(2)) //对数运算
print(math.sqrt(4)) //开平方运算 等价于4^0.5
1
2
3
4
5
import numpy as np
a = [1,2,3,4,5]
np.mean(a) //求均值
np.media(a) //求中位数
np.sta(a) //求标准差

3 python字符串类型

3.1 字符串

3.1.1 用””或’’括起来的任意字符

3.1.1.1 双中有单

1
print("'python'")

3.1.1.2 单中有双

1
print('"python"')

3.1.1.3 双中有双,单中有单

1
print("\python\ is good")

3.1.1.4 转义符可以用来换行

1
2
a = "pyth\
n"

3.2 字符串的索引

3.2.1 正向索引

1
s = 'My name is Peppa pig'
1
2
print(s[0]) //M
print(s[1]) //y

3.2.2 反向索引

1
print(s[-1]) //g

3.3 字符串的切片

1
2
3
s = 'python'
print(s[0:3:1]) \\pyt,1可以省略
print(s[0:3:2]) \\pt

3.4 字符串的处理

3.4.1 strip()切割函数

Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。**

3.4.1.1 语法

1
2
3
strip()方法语法:

str.strip([chars]);

3.4.1.2 参数

  • chars — 移除字符串头尾指定的字符序列。

    3.4.1.3 返回值

    返回移除字符串头尾指定的字符生成的新字符串。

4 python逻辑

在Python中,控制流(Control Flow)主要通过条件判断和循环语句来实现。Python 摒弃了传统语言中的大括号 {},严格采用 缩进(Indentation) 来定义代码块的作用域。

4.1 判断(条件控制)

4.1.1 关系运算符与逻辑运算符

在进行条件判断前,通常需要构建条件表达式。表达式的结果为布尔值(TrueFalse)。

4.1.1.1 关系运算符

用于比较两个值的大小或等值关系。

  • == (等于), != (不等于)
  • > (大于), < (小于)
  • >= (大于等于), <= (小于等于)

4.1.1.2 逻辑运算符

用于连接多个条件表达式。

  • and (逻辑与):所有条件均为True时返回True。
  • or (逻辑或):任意一个条件为True时返回True。
  • not (逻辑非):对布尔值取反。

4.1.2 if 语句的基础与进阶

4.1.2.1 单分支结构:if

当条件满足时,执行特定的代码块。

1
2
3
age = 20
if age >= 18:
print("已成年") # 条件为True,执行该语句

4.1.2.2 双分支结构:if-else

当条件满足时执行一个代码块,不满足时执行另一个。

1
2
3
4
5
score = 59
if score >= 60:
print("及格")
else:
print("不及格") # 59 < 60,因此执行else分支

4.1.2.3 多分支结构:if-elif-else

用于处理多种互斥的条件情况。Python 中使用 elif 代替 else if

1
2
3
4
5
6
7
8
9
score = 85
if score >= 90:
print("优秀")
elif score >= 80:
print("良好") # 匹配此分支,后续elif将被忽略
elif score >= 60:
print("及格")
else:
print("不及格")
  • 注:条件判断是从上到下依次匹配的,一旦某个条件满足,执行对应代码块后就会自动跳出整个 if-elif-else 结构。

4.2 循环(迭代控制)

Python 提供了两种基本的循环机制:遍历循环(for)和条件循环(while)。

4.2.1 for 循环 (遍历循环)

for 循环主要用于遍历序列(如字符串、列表、元组)或任何可迭代对象。

4.2.1.1 遍历字符串与列表

1
2
3
4
5
6
7
8
# 遍历字符串
for char in "Python":
print(char)

# 遍历列表
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)

4.2.1.2 结合 range() 函数

range(start, stop, step) 函数常用于生成等差整数序列,配合 for 循环控制执行次数。

1
2
3
4
5
6
7
# 生成从 0 到 4 的整数
for i in range(5):
print(i) # 输出 0, 1, 2, 3, 4

# 生成从 2 到 8,步长为 2 的整数
for i in range(2, 9, 2):
print(i) # 输出 2, 4, 6, 8
  • 注:range() 函数生成的序列遵循“左闭右开”原则,即包含 start,但不包含 stop

    4.2.2 while 循环 (条件循环)

while 循环在条件表达式为 True 的前提下,不断重复执行代码块,直到条件变为 False

4.2.2.1 基本语法

1
2
3
4
count = 0
while count < 3:
print("计数:", count)
count += 1 # 必须有修改条件的语句,否则会陷入死循环
  • 注:在编写 while 循环时,务必确保循环内部存在改变判断条件的逻辑,以避免程序发生无限循环(Memory Out)。

    4.2.3 循环控制保留字

在循环执行过程中,有时需要提前改变循环的默认执行流程,主要使用 breakcontinue

4.2.3.1 break:跳出整个循环

立刻终止当前所在的循环,不再执行循环体中剩余的语句,也不再进行下一次迭代。

1
2
3
4
for i in range(1, 10):
if i == 4:
break # 当 i 等于 4 时,彻底结束整个 for 循环
print(i) # 仅输出 1, 2, 3

4.2.3.2 continue:跳过本次循环

结束当前这一轮迭代,直接跳到循环的开头,判断条件并准备进行下一次迭代。

1
2
3
4
for i in range(1, 6):
if i == 3:
continue # 当 i 等于 3 时,跳过本次打印,继续 i=4 的循环
print(i) # 输出 1, 2, 4, 5

5 python 格式化输出

在Python中,字符串占位符是一种常见的格式化字符串的方法。它允许我们通过模板来创建字符串,并在稍后插入具体的值。

5.1 使用 % 运算符

1
2
3
4
5
name = "Alice"

age = 25

print("Hello, my name is %s and I am %d years old" % (name, age))

输出结果将是 Hello, my name is Alice and I am 25 years old

5.2 使用 format() 方法

1
2
3
4
5
name = "Alice"

age = 25

print("Hello, my name is {} and I am {} years old".format(name, age))

输出结果将是 Hello, my name is Alice and I am 25 years old

5.3 使用 f-string(格式化字符串)

1
2
3
4
5
name = "Alice"

age = 25

print(f"Hello, my name is {name} and I am {age} years old")

输出结果将是 Hello, my name is Alice and I am 25 years old

6 容错机制

1
2
3
4
5
6
7
8
9
try:
正常的操作
......................
except:
发生异常,执行这块代码
......................
else:
如果没有异常执行这块代码

7 Python 魔术方法 (Magic Methods) 全解析

在类中定义的名字前后各有两个下划线的方法,称为魔术方法或特殊方法。这些方法是Python实现“面向对象”底层行为的基石。我们可以使用 dir() 函数来查看一个对象拥有的魔术方法。

由于魔术方法体系庞大,我们根据功能将其详细分类:

7.1 生命周期与基础魔法方法

控制对象的创建、初始化、销毁以及基础形态展示。

  • __new__(cls[, ...]):在一个对象实例化时所调用的第一个方法,负责真正在内存中创建并返回实例对象。
  • __init__(self[, ...]):构造器,当一个实例被创建后,立即调用的初始化方法,用于绑定属性。
  • __del__(self):析构器,当一个实例被垃圾回收销毁时调用的方法。
  • __call__(self[, args...]):允许一个类的实例像函数一样被直接调用。例如执行 x(a, b) 实际上调用了 x.__call__(a, b)

格式化与表现行为

  • __str__(self):定义当被 str() 调用(或被 print 打印)时的行为,应返回人类可读的字符串。
  • __repr__(self):定义当被 repr() 调用时的行为,应返回机器可读、且最好能用 eval() 重建对象的字符串。
  • __len__(self):定义当被 len() 调用时的行为,返回长度。
  • __bool__(self):定义当被 bool() 调用时的行为,必须返回 True 或 False。
  • __format__(self, format_spec):定义当被 format() 格式化函数调用时的行为。
  • __bytes__(self)__hash__(self):分别定义被 bytes()hash() 调用时的行为。

7.2 属性访问拦截

这些方法允许你在获取、设置或删除属性时介入,实现高度定制化的逻辑。

  • __getattr__(self, name):定义当用户试图获取一个不存在的属性时的兜底行为。
  • __getattribute__(self, name):定义当该类的任何属性被访问时的拦截行为(非常底层,谨慎使用以防无限递归)。
  • __setattr__(self, name, value):定义当一个属性被设置或赋值时的行为。
  • __delattr__(self, name):定义当一个属性被删除时的行为。
  • __dir__(self):定义当 dir() 被调用时的行为,用于自定义列出的属性列表。

描述符协议

用于在类级别控制属性的访问逻辑。

  • __get__(self, instance, owner):定义当描述符的值被取得时的行为。
  • __set__(self, instance, value):定义当描述符的值被改变时的行为。
  • __delete__(self, instance):定义当描述符的值被删除时的行为。

7.3 运算符重载 (Operator Overloading)

让自定义对象支持常见的数学与比较运算。

7.3.1 比较操作符

  • __lt__(self, other):定义小于号 < 的行为。
  • __le__(self, other):定义小于等于号 <= 的行为。
  • __eq__(self, other):定义等于号 == 的行为。
  • __ne__(self, other):定义不等号 != 的行为。
  • __gt__(self, other):定义大于号 > 的行为。
  • __ge__(self, other):定义大于等于号 >= 的行为。

7.3.2 算术与位运算

  • 加减乘除__add__ (+), __sub__ (-), __mul__ (*), __truediv__ (真除法 /), __floordiv__ (整数除法 //)。
  • 模与幂__mod__ (%), __divmod__ (divmod()调用), __pow__ (**)。
  • 位运算__lshift__ (<<), __rshift__ (>>), __and__ (&), __xor__ (^), __or__ (|)。

(注:Python同样支持右侧/反向运算魔术方法,如 __radd__, __rsub__ 等,当左操作数不支持相应操作时会被调用。以及增量赋值运算如 __iadd__ (+=), __isub__ (-=) 等。)

7.3.3 一元操作符

  • __pos__(self):定义正号 +x 的行为。
  • __neg__(self):定义负号 -x 的行为。
  • __abs__(self):定义被 abs() 调用时的行为。
  • __invert__(self):定义按位求反 ~x 的行为。

7.4 容器与迭代器协议

让对象表现得像列表或字典。

  • __len__(self):返回容器元素的个数。
  • __getitem__(self, key):定义获取指定元素的行为,支持 self[key] 语法。
  • __setitem__(self, key, value):定义设置元素的行为,支持 self[key] = value 语法。
  • __delitem__(self, key):定义删除元素的行为 del self[key]
  • __iter__(self):定义迭代容器元素的行为(需返回迭代器对象)。
  • __reversed__(self):定义被 reversed() 调用时的行为。
  • __contains__(self, item):定义使用成员测试符 innot in 时的行为。

7.5 上下文管理器

用于 with 语句,优雅地管理资源(如文件的打开与关闭)。

  • __enter__(self):定义进入 with 代码块时的初始化行为。其返回值会被绑定到 as 后的变量名上。
  • __exit__(self, exc_type, exc_value, traceback):定义代码块执行完毕或发生异常时应当执行的清理工作。

7.6 类型强制转换

  • __complex____int____float____round__:分别定义被 complex(), int(), float(), round() 调用时的行为。
  • __index__(self):当对象应用在切片表达式中时,实现整型强制转换。如果定义了此方法,通常也需要定义 __int__ 并返回相同值。

8 类

面向对象编程 (OOP) 核心精讲

面向对象设计是一种使用对象进行程序设计的方法,目的是实现代码复用和设计复用,使软件开发更高效快捷。

类 (Class) 与 对象 (Object) 的概念

  • :是一种对象的模板和数据类型。它定义了对象的属性(数据、变量),并提供用于初始化对象的初始化程序和操作这些属性的方法(函数)。
  • 对象:是类的一个具体实例。我们使用构造方法来创建一个对象,并使用圆点运算符 (.) 通过引用方法和变量来访问对象的成员。
    • 属性:表明对象的状态,相当于变量,一般用名词或形容词表示。
    • 方法:表示对象所具有的行为和功能,相当于类中的函数,一般用动词表示。

类的定义与对象的实例化

在Python中,使用 class 关键字来定义类。按照惯例,类名的首字母应该大写(内置系统类如 int, list 除外)。

如果类暂时没有内容,可以使用 pass 占位符:

1
2
class Student:
pass

完整类的定义与实例化实战

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
class StudentGPA:
# 构造方法(初始化方法),在创建对象实例的过程中自动调用
# self 参数是必须的,它代表对象本身
def __init__(self, name, num, credits, qpoints):
# 属性的定义与初始化
self.name = name #
self.num = num #
self.credits = float(credits) #
self.qpoint = float(qpoints) #
self.course_grade = {} # 初始化一个空字典属性
self.GPA = 0 # 初始化GPA为0

# 方法的定义
# 方法与一般函数相似,用 def 定义,但第一个参数总是 self
def get_info(self):
# 在类中定义的方法,都可以使用 “self.属性名” 来访问自己的变量
print(f"Name: {self.name}, Number: {self.num}")

# 创建对象的实例(实例化)
# 将参数传递给 __init__ 方法进行初始化
stu_c = StudentGPA("陈十", "3100010", 160, 606) #

# 访问对象的数据属性
print(stu_c.name)

# 调用对象的方法
stu_c.get_info()

# 也可以在外部直接给对象实例赋予新的属性
stu_c.age = 20

面向对象的高级特性:封装、继承与多态

面向对象的三大基本特性是:封装、继承、多态。

类的封装 (Encapsulation)

概念:封装是将数据和操作数据的方法包装在一起,隐藏数据的内部细节,防止外界的直接访问和修改。封装后,只能通过对外提供的接口,对封装在内部的属性和方法进行访问和操作。

私有成员的实现机制

在Python中,一个类的成员是否为私有,由成员的名称决定。

  • 私有成员:如果名字以两条下划线 __ 开头,且不以两个下划线 __ 结尾,则该元素为私有。
  • 公有成员:不符合上述命名规则的成员。

私有成员只能在类的内部访问,不会被继承和覆盖。如果在类的外部强行访问,Python解释器会提示该成员不存在。

封装实战代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A:
def __init__(self):
self.__a = 0 # 私有属性,外部不可见
self.b = 0 # 公有属性,外部可见

def print_v1(self):
print(self.__a) # 类内部可以正常访问私有属性

def print_v2(self):
print(self.b) # 类内部访问公有属性

def __print_v3(self): # 私有方法
print(self.b)

o = A()
# o.__a = 1 # 错误!无法在外部赋值,会报错提示不存在
o.print_v1() # 正常运行,输出 0
o.print_v2() # 正常运行,输出 0
# o.__print_v3() # 错误!私有方法在外部不可访问

类的继承 (Inheritance)

概念:继承是指可以使用现有类的所有功能,而无需重新编写原来类的情况下对这些功能进行扩展。

通过继承得到的类称为子类,被继承的类称为父类。父类包括所有直接或间接被继承的类。

子类自动继承父类的状态和方法,同时可以修改父类的状态、重载父类的行为,并添加新的状态和行为。如果定义类时缺省父类名,则默认继承自 object,因此Python中所有的类最终都继承自 object

派生与基础继承语法

在定义类时,使用括号 () 来指明父类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def sayHello(self):
print("Hello!")

# Student 继承自 Person
class Student(Person):
pass

s = Student("李雷", 18)
s.sayHello() # 子类自动继承父类的方法

使用 super() 进行扩展与重写

super() 函数在继承中极其重要,主要用途包括:

  1. 避免在改动父类名称时还需修改子类调用方法的代码。

  2. 在子类中按照一套内置的顺序自动调用父类的方法。

  3. 处理多继承问题。

  4. 在子类的 __init__ 中初始化父类的属性。

继承扩展实战代码

1
2
3
4
5
6
7
8
9
10
11
class Employee(Person):
# 子类重写 __init__ 方法,添加新的属性
def __init__(self, name, age, job_title):
# 使用 super() 调用父类的初始化方法,避免重复代码
super().__init__(name, age)
self.job_title = job_title # 子类新增属性

# 子类重写父类的方法
def sayHello(self):
super().sayHello() # 先执行父类的行为
print(f"I am a {self.job_title}.") # 再添加子类独有的行为

多继承与继承顺序 (MRO)

Python允许一个子类继承多个父类。但当继承关系极其复杂时,决定优先调用哪个父类的方法就成为了一个难题。

Python使用 C3线性化算法 来计算类的 MRO (Method Resolution Order, 方法解析顺序)。该算法合并所有相关父类的方法,消除多重继承的解析歧义。

C3算法的三个重要特性:

  1. 保持继承拓扑图的一致性。

  2. 保证局部优先原则(如 A 继承 C,C 继承 B,则 A 优先使用 C 的方法而非 B 的)。

  3. 保证单调性原则(子类不改变父类的方法搜索顺序)。

使用 __mro__ 属性或 .mro() 方法可以直观查看类的继承顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A:
def say(self): print("A")

class B:
def say(self): print("B")

class C(A):
pass

# M 继承了 C 和 B
class M(C, B):
pass

m = M()
# 查看 M 类的继承顺序
print(M.mro()) # 输出结果展示了 C3 算法计算出的搜索路径