0/0

从零开始学习Python编程

这是一份专为初学者设计的Python入门教程,通过简单易懂的讲解和丰富的实例,帮助你快速掌握Python编程基础。

开始学习

Python简介

Python是一种高级编程语言,由吉多·范罗苏姆(Guido van Rossum)于1991年创建。它以其简洁的语法和强大的功能而闻名,被广泛应用于Web开发、数据分析、人工智能、科学计算等领域。

为什么选择Python?

提示:Python的名字来源于英国喜剧团体"Monty Python",而不是蟒蛇。

小测验

Python是由谁创建的?

安装与环境配置

在开始学习Python之前,你需要在你的计算机上安装Python。以下是安装步骤:

1. 下载Python

访问Python官方网站 https://www.python.org/downloads/ 下载最新版本的Python。

2. 安装Python

运行下载的安装程序,在安装过程中,请确保勾选"Add Python to PATH"选项,这将使你能够在命令行中直接使用Python。

3. 验证安装

打开命令行工具(Windows上的命令提示符或PowerShell,Mac或Linux上的终端),输入以下命令:

python --version

如果安装成功,你将看到安装的Python版本号。

4. 选择代码编辑器

虽然你可以使用任何文本编辑器编写Python代码,但使用专门的代码编辑器可以提高效率。以下是一些流行的选择:

提示:对于初学者,推荐使用Visual Studio Code,它轻量级且易于使用。

Python基础

变量与数据类型

在Python中,变量是用来存储数据的容器。你可以把变量想象成一个标签,它指向内存中的某个值。

创建变量

在Python中创建变量非常简单,只需给变量赋值即可:

# 创建变量并赋值
name = "小明"
age = 25
height = 1.75
is_student = True

Python的基本数据类型

  • 整数(int):表示整数,如 10, -5, 0
  • 浮点数(float):表示小数,如 3.14, -0.5, 2.0
  • 字符串(str):表示文本,如 "Hello", 'Python'
  • 布尔值(bool):表示真或假,只有两个值:True 和 False

查看变量类型

使用type()函数可以查看变量的数据类型:

name = "小明"
age = 25
height = 1.75
is_student = True

print(type(name))    # <class 'str'>
print(type(age))     # <class 'int'>
print(type(height))  # <class 'float'>
print(type(is_student))  # <class 'bool'>

小测验

以下哪个是Python中的浮点数?

运算符

Python支持多种运算符,用于执行各种数学和逻辑运算。

算术运算符

  • +:加法
  • -:减法
  • *:乘法
  • /:除法
  • %:取模(求余数)
  • **:幂运算
  • //:整除
# 算术运算符示例
a = 10
b = 3

print(a + b)   # 13
print(a - b)   # 7
print(a * b)   # 30
print(a / b)   # 3.333...
print(a % b)   # 1
print(a ** b)  # 1000
print(a // b)  # 3

比较运算符

  • ==:等于
  • !=:不等于
  • >:大于
  • <:小于
  • >=:大于等于
  • <=:小于等于
# 比较运算符示例
a = 10
b = 20

print(a == b)  # False
print(a != b)  # True
print(a > b)   # False
print(a < b)   # True
print(a >= b)  # False
print(a <= b)  # True

逻辑运算符

  • and:逻辑与
  • or:逻辑或
  • not:逻辑非
# 逻辑运算符示例
a = True
b = False

print(a and b)  # False
print(a or b)   # True
print(not a)    # False

字符串操作

字符串是Python中最常用的数据类型之一。在Python中,字符串可以用单引号(')、双引号(")或三引号('''或""")表示。

创建字符串

# 创建字符串
str1 = 'Hello, World!'
str2 = "Python编程"
str3 = """这是一个
多行字符串"""

字符串拼接

可以使用+运算符或f-string来拼接字符串:

# 字符串拼接
first_name = "张"
last_name = "三"

# 使用+运算符
full_name = first_name + last_name
print(full_name)  # 张三

# 使用f-string(推荐)
full_name = f"{first_name}{last_name}"
print(full_name)  # 张三

# 带格式的f-string
age = 25
intro = f"我叫{first_name}{last_name},今年{age}岁。"
print(intro)  # 我叫张三,今年25岁。

字符串方法

Python提供了许多内置的字符串方法,用于处理字符串:

# 字符串方法示例
text = "Hello, World!"

# 转换为大写
print(text.upper())  # HELLO, WORLD!

# 转换为小写
print(text.lower())  # hello, world!

# 去除首尾空格
text_with_spaces = "  Hello, World!  "
print(text_with_spaces.strip())  # Hello, World!

# 查找子字符串
print(text.find("World"))  # 7

# 替换子字符串
print(text.replace("World", "Python"))  # Hello, Python!

# 分割字符串
csv_data = "apple,banana,orange"
fruits = csv_data.split(",")
print(fruits)  # ['apple', 'banana', 'orange']

小测验

以下哪个方法可以将字符串转换为大写?

控制流

条件语句

条件语句允许程序根据不同的条件执行不同的代码块。Python中的条件语句使用if、elif和else关键字。

if语句

最基本的条件语句是if语句,它只在条件为True时执行代码块:

# if语句示例
age = 18

if age >= 18:
    print("你已经成年了!")

if-else语句

if-else语句在条件为True时执行一个代码块,在条件为False时执行另一个代码块:

# if-else语句示例
age = 16

if age >= 18:
    print("你已经成年了!")
else:
    print("你还未成年。")

if-elif-else语句

当需要检查多个条件时,可以使用if-elif-else语句:

# if-elif-else语句示例
score = 85

if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

嵌套条件语句

可以在一个条件语句中嵌套另一个条件语句:

# 嵌套条件语句示例
age = 20
has_id = True

if age >= 18:
    if has_id:
        print("你可以进入酒吧。")
    else:
        print("你需要身份证才能进入酒吧。")
else:
    print("你还未成年,不能进入酒吧。")

注意:在Python中,代码块是通过缩进来定义的,而不是使用大括号{}。通常使用4个空格作为缩进。

循环语句

循环语句允许程序重复执行一段代码。Python提供了两种主要的循环语句:for循环和while循环。

for循环

for循环用于遍历序列(如列表、元组、字符串等)或其他可迭代对象:

# for循环示例
# 遍历列表
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
    print(fruit)

# 遍历字符串
for char in "Python":
    print(char)

# 使用range()函数
for i in range(5):  # 0, 1, 2, 3, 4
    print(i)

# 指定范围的range()
for i in range(2, 6):  # 2, 3, 4, 5
    print(i)

# 指定步长的range()
for i in range(0, 10, 2):  # 0, 2, 4, 6, 8
    print(i)

while循环

while循环在条件为True时重复执行代码块:

# while循环示例
count = 0
while count < 5:
    print(count)
    count += 1  # 等同于 count = count + 1

循环控制语句

Python提供了几个循环控制语句,用于改变循环的正常执行流程:

  • break:立即退出循环
  • continue:跳过当前迭代,继续下一次迭代
  • pass:空操作,用于保持程序结构的完整性
# 循环控制语句示例
# break示例
for i in range(10):
    if i == 5:
        break
    print(i)  # 输出: 0, 1, 2, 3, 4

# continue示例
for i in range(10):
    if i % 2 == 0:
        continue
    print(i)  # 输出: 1, 3, 5, 7, 9

# pass示例
for i in range(5):
    if i == 2:
        pass  # 什么都不做
    print(i)  # 输出: 0, 1, 2, 3, 4

嵌套循环

可以在一个循环中嵌套另一个循环:

# 嵌套循环示例
# 打印乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j} × {i} = {i * j}", end="\t")
    print()  # 换行

小测验

以下哪个语句可以立即退出循环?

数据结构

列表

列表是Python中最常用的数据结构之一,它是一个有序、可变的集合,可以包含任意类型的元素。

创建列表

# 创建列表
fruits = ["apple", "banana", "orange"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]

# 创建空列表
empty_list = []
empty_list = list()

访问列表元素

列表中的元素可以通过索引访问,索引从0开始:

# 访问列表元素
fruits = ["apple", "banana", "orange"]

# 访问第一个元素
print(fruits[0])  # apple

# 访问最后一个元素
print(fruits[-1])  # orange

# 访问第二个元素
print(fruits[1])  # banana

修改列表

# 修改列表
fruits = ["apple", "banana", "orange"]

# 修改元素
fruits[1] = "grape"
print(fruits)  # ['apple', 'grape', 'orange']

# 添加元素到末尾
fruits.append("pear")
print(fruits)  # ['apple', 'grape', 'orange', 'pear']

# 在指定位置插入元素
fruits.insert(1, "banana")
print(fruits)  # ['apple', 'banana', 'grape', 'orange', 'pear']

# 删除指定位置的元素
fruits.pop(2)
print(fruits)  # ['apple', 'banana', 'orange', 'pear']

# 删除指定值的元素
fruits.remove("pear")
print(fruits)  # ['apple', 'banana', 'orange']

列表切片

可以使用切片操作获取列表的子集:

# 列表切片
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 获取前三个元素
print(numbers[0:3])  # [0, 1, 2]

# 获取从索引2到5的元素
print(numbers[2:6])  # [2, 3, 4, 5]

# 获取从索引3到末尾的元素
print(numbers[3:])  # [3, 4, 5, 6, 7, 8, 9]

# 获取从开始到索引5的元素
print(numbers[:6])  # [0, 1, 2, 3, 4, 5]

# 获取所有元素
print(numbers[:])  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 使用步长
print(numbers[::2])  # [0, 2, 4, 6, 8]

列表排序

# 列表排序
numbers = [3, 1, 4, 1, 5, 9, 2, 6]

# 升序排序(修改原列表)
numbers.sort()
print(numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

# 降序排序(修改原列表)
numbers.sort(reverse=True)
print(numbers)  # [9, 6, 5, 4, 3, 2, 1, 1]

# 返回排序后的新列表(不修改原列表)
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers)
print(numbers)  # [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted_numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

元组

元组与列表类似,但是元组是不可变的,一旦创建就不能修改。元组使用圆括号()表示。

创建元组

# 创建元组
fruits = ("apple", "banana", "orange")
numbers = (1, 2, 3, 4, 5)
mixed = (1, "hello", 3.14, True)

# 创建单元素元组(需要加逗号)
single_element = (1,)

# 创建空元组
empty_tuple = ()
empty_tuple = tuple()

访问元组元素

元组元素的访问方式与列表相同:

# 访问元组元素
fruits = ("apple", "banana", "orange")

# 访问第一个元素
print(fruits[0])  # apple

# 访问最后一个元素
print(fruits[-1])  # orange

# 元组切片
print(fruits[1:3])  # ('banana', 'orange')

元组与列表的区别

  • 元组是不可变的,而列表是可变的
  • 元组使用圆括号(),而列表使用方括号[]
  • 元组通常用于存储不应修改的数据
  • 元组比列表更节省内存
# 元组与列表的区别
# 列表是可变的
fruits_list = ["apple", "banana", "orange"]
fruits_list[1] = "grape"  # 可以修改
print(fruits_list)  # ['apple', 'grape', 'orange']

# 元组是不可变的
fruits_tuple = ("apple", "banana", "orange")
# fruits_tuple[1] = "grape"  # 这会引发TypeError

字典

字典是Python中的一种键值对集合,每个键都与一个值相关联。字典使用花括号{}表示,键和值之间用冒号:分隔。

创建字典

# 创建字典
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机科学",
    "grades": [85, 90, 78, 92]
}

# 创建空字典
empty_dict = {}
empty_dict = dict()

访问字典元素

# 访问字典元素
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机科学"
}

# 使用键访问值
print(student["name"])  # 张三
print(student["age"])   # 20

# 使用get()方法访问值(如果键不存在,返回None或默认值)
print(student.get("name"))  # 张三
print(student.get("grade"))  # None
print(student.get("grade", "N/A"))  # N/A

修改字典

# 修改字典
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机科学"
}

# 修改值
student["age"] = 21
print(student)  # {'name': '张三', 'age': 21, 'major': '计算机科学'}

# 添加键值对
student["grade"] = "A"
print(student)  # {'name': '张三', 'age': 21, 'major': '计算机科学', 'grade': 'A'}

# 删除键值对
del student["grade"]
print(student)  # {'name': '张三', 'age': 21, 'major': '计算机科学'}

# 使用pop()方法删除键值对并返回值
major = student.pop("major")
print(major)    # 计算机科学
print(student)  # {'name': '张三', 'age': 21}

遍历字典

# 遍历字典
student = {
    "name": "张三",
    "age": 21,
    "major": "计算机科学"
}

# 遍历键
for key in student:
    print(key)

# 遍历值
for value in student.values():
    print(value)

# 遍历键值对
for key, value in student.items():
    print(f"{key}: {value}")

集合

集合是一个无序、不重复的元素集合。集合使用花括号{}表示,或者使用set()函数创建。

创建集合

# 创建集合
fruits = {"apple", "banana", "orange"}
numbers = {1, 2, 3, 4, 5}

# 从列表创建集合(会自动去除重复元素)
numbers_list = [1, 2, 2, 3, 4, 4, 5]
unique_numbers = set(numbers_list)
print(unique_numbers)  # {1, 2, 3, 4, 5}

# 创建空集合(必须使用set(),因为{}创建的是空字典)
empty_set = set()

修改集合

# 修改集合
fruits = {"apple", "banana", "orange"}

# 添加元素
fruits.add("pear")
print(fruits)  # {'orange', 'pear', 'banana', 'apple'}

# 添加多个元素
fruits.update(["grape", "mango"])
print(fruits)  # {'orange', 'pear', 'mango', 'banana', 'apple', 'grape'}

# 删除元素
fruits.remove("banana")
print(fruits)  # {'orange', 'pear', 'mango', 'apple', 'grape'}

# 如果元素不存在,remove()会引发错误,而discard()不会
fruits.discard("banana")  # 不会引发错误
# fruits.remove("banana")  # 会引发KeyError

集合操作

# 集合操作
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 并集(包含两个集合中的所有元素)
union_set = set1 | set2
print(union_set)  # {1, 2, 3, 4, 5, 6, 7, 8}

# 交集(包含两个集合中都存在的元素)
intersection_set = set1 & set2
print(intersection_set)  # {4, 5}

# 差集(包含在第一个集合中但不在第二个集合中的元素)
difference_set = set1 - set2
print(difference_set)  # {1, 2, 3}

# 对称差集(包含在任一集合中但不同时存在于两个集合中的元素)
symmetric_difference_set = set1 ^ set2
print(symmetric_difference_set)  # {1, 2, 3, 6, 7, 8}

小测验

以下哪种数据结构是无序且不重复的?

函数

函数是一段可重复使用的代码,用于执行特定的任务。在Python中,使用def关键字定义函数。

定义和调用函数

# 定义函数
def greet():
    print("Hello, World!")

# 调用函数
greet()  # 输出: Hello, World!

带参数的函数

# 带参数的函数
def greet(name):
    print(f"Hello, {name}!")

# 调用函数
greet("Alice")  # 输出: Hello, Alice!
greet("Bob")    # 输出: Hello, Bob!

带默认值的参数

# 带默认值的参数
def greet(name="World"):
    print(f"Hello, {name}!")

# 调用函数
greet()        # 输出: Hello, World!
greet("Alice") # 输出: Hello, Alice!

返回值

# 带返回值的函数
def add(a, b):
    return a + b

# 调用函数并使用返回值
result = add(3, 5)
print(result)  # 输出: 8

# 直接在表达式中使用返回值
print(add(10, 20))  # 输出: 30

多返回值

# 返回多个值
def calculate(a, b):
    sum = a + b
    difference = a - b
    product = a * b
    return sum, difference, product

# 调用函数并接收多个返回值
s, d, p = calculate(10, 5)
print(f"和: {s}, 差: {d}, 积: {p}")  # 输出: 和: 15, 差: 5, 积: 50

# 也可以将返回值作为一个元组接收
result = calculate(10, 5)
print(result)  # 输出: (15, 5, 50)

关键字参数

# 关键字参数
def describe_person(name, age, gender):
    print(f"姓名: {name}, 年龄: {age}, 性别: {gender}")

# 使用位置参数
describe_person("张三", 25, "男")

# 使用关键字参数(可以不按顺序)
describe_person(age=25, name="张三", gender="男")

# 混合使用位置参数和关键字参数
describe_person("张三", age=25, gender="男")

可变参数

# 可变位置参数 (*args)
def sum_all(*numbers):
    total = 0
    for num in numbers:
        total += num
    return total

# 调用函数
print(sum_all(1, 2, 3))        # 输出: 6
print(sum_all(10, 20, 30, 40)) # 输出: 100

# 可变关键字参数 (**kwargs)
def print_info(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

# 调用函数
print_info(name="张三", age=25, city="北京")
# 输出:
# name: 张三
# age: 25
# city: 北京

匿名函数(lambda)

# lambda函数
multiply = lambda x, y: x * y

# 调用lambda函数
print(multiply(3, 4))  # 输出: 12

# 常用于高阶函数
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers)  # 输出: [1, 4, 9, 16, 25]

even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出: [2, 4]

小测验

以下哪个关键字用于定义函数?

模块与包

模块是包含Python定义和语句的文件,包是包含多个模块的目录。模块和包是Python代码组织和重用的重要方式。

导入模块

# 导入整个模块
import math
print(math.sqrt(16))  # 输出: 4.0

# 导入模块中的特定函数
from math import sqrt
print(sqrt(16))  # 输出: 4.0

# 导入模块中的所有函数(不推荐)
from math import *
print(sqrt(16))  # 输出: 4.0

# 给模块起别名
import math as m
print(m.sqrt(16))  # 输出: 4.0

常用标准模块

# math模块 - 数学函数
import math
print(math.pi)       # 输出: 3.141592653589793
print(math.sin(0))   # 输出: 0.0
print(math.cos(0))   # 输出: 1.0

# random模块 - 随机数生成
import random
print(random.randint(1, 10))  # 输出1到10之间的随机整数
print(random.choice(["apple", "banana", "orange"]))  # 随机选择一个元素

# datetime模块 - 日期和时间处理
import datetime
now = datetime.datetime.now()
print(now)  # 输出当前日期和时间
print(now.strftime("%Y-%m-%d %H:%M:%S"))  # 格式化输出

# os模块 - 操作系统接口
import os
print(os.getcwd())  # 输出当前工作目录
print(os.listdir("."))  # 列出当前目录的文件和文件夹

创建自定义模块

创建一个名为mymodule.py的文件:

# mymodule.py
def greet(name):
    return f"Hello, {name}!"

def add(a, b):
    return a + b

PI = 3.14159

然后在另一个文件中使用这个模块:

# main.py
import mymodule

print(mymodule.greet("Alice"))  # 输出: Hello, Alice!
print(mymodule.add(3, 5))       # 输出: 8
print(mymodule.PI)              # 输出: 3.14159

创建包

包是一个包含__init__.py文件的目录,__init__.py文件可以为空,也可以包含包的初始化代码。

创建以下目录结构:

            mypackage/
            ├── __init__.py
            ├── module1.py
            └── module2.py
            

在module1.py中:

# module1.py
def function1():
    return "This is function1 from module1"

在module2.py中:

# module2.py
def function2():
    return "This is function2 from module2"

然后在另一个文件中使用这个包:

# main.py
from mypackage import module1, module2

print(module1.function1())  # 输出: This is function1 from module1
print(module2.function2())  # 输出: This is function2 from module2

安装第三方包

使用pip工具可以安装第三方包:

# 安装包
pip install numpy

# 升级包
pip install --upgrade numpy

# 卸载包
pip uninstall numpy

# 查看已安装的包
pip list

使用第三方包

# 使用numpy包
import numpy as np

# 创建数组
a = np.array([1, 2, 3, 4, 5])
print(a)

# 数组运算
b = np.array([6, 7, 8, 9, 10])
print(a + b)  # [ 7  9 11 13 15]

# 使用requests包
import requests

# 发送HTTP请求
response = requests.get("https://www.example.com")
print(response.status_code)  # 200
print(response.text[:100])   # 输出网页内容的前100个字符

文件操作

文件操作是编程中常见的任务,Python提供了简单而强大的文件操作功能。

打开和关闭文件

# 打开文件
f = open("example.txt", "r")  # "r"表示读取模式

# 关闭文件
f.close()

# 使用with语句自动关闭文件(推荐)
with open("example.txt", "r") as f:
    content = f.read()
    # 文件会在with块结束时自动关闭

文件打开模式

读取文件

# 读取整个文件
with open("example.txt", "r") as f:
    content = f.read()
    print(content)

# 逐行读取
with open("example.txt", "r") as f:
    for line in f:
        print(line.strip())  # strip()去除行尾的换行符

# 读取指定数量的字符
with open("example.txt", "r") as f:
    content = f.read(10)  # 读取前10个字符
    print(content)

# 读取所有行到一个列表
with open("example.txt", "r") as f:
    lines = f.readlines()
    print(lines)

写入文件

# 写入字符串
with open("output.txt", "w") as f:
    f.write("Hello, World!\n")
    f.write("This is a test.\n")

# 写入多行
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open("output.txt", "w") as f:
    f.writelines(lines)

# 追加内容
with open("output.txt", "a") as f:
    f.write("This line is appended.\n")

文件和目录操作

import os

# 检查文件是否存在
if os.path.exists("example.txt"):
    print("文件存在")
else:
    print("文件不存在")

# 检查是否是文件
if os.path.isfile("example.txt"):
    print("这是一个文件")

# 检查是否是目录
if os.path.isdir("my_folder"):
    print("这是一个目录")

# 创建目录
os.mkdir("new_folder")  # 创建单级目录
os.makedirs("parent/child")  # 创建多级目录

# 删除文件
os.remove("example.txt")

# 删除目录
os.rmdir("empty_folder")  # 只能删除空目录
os.removedirs("parent/child")  # 删除多级空目录

# 重命名文件或目录
os.rename("old_name.txt", "new_name.txt")

# 获取当前工作目录
current_dir = os.getcwd()
print(current_dir)

# 改变当前工作目录
os.chdir("/path/to/directory")

# 获取文件大小
file_size = os.path.getsize("example.txt")
print(f"文件大小: {file_size} 字节")

使用pathlib模块

pathlib模块提供了面向对象的文件系统路径操作方式:

from pathlib import Path

# 创建Path对象
p = Path("example.txt")

# 检查文件是否存在
if p.exists():
    print("文件存在")

# 获取文件名
print(p.name)  # example.txt

# 获取文件扩展名
print(p.suffix)  # .txt

# 获取文件所在目录
print(p.parent)  # .

# 读取文件内容
content = p.read_text()
print(content)

# 写入文件内容
p.write_text("Hello, World!")

# 创建目录
dir_path = Path("new_folder")
dir_path.mkdir(exist_ok=True)  # exist_ok=True表示目录已存在时不报错

# 遍历目录
for item in Path(".").iterdir():
    if item.is_file():
        print(f"文件: {item.name}")
    elif item.is_dir():
        print(f"目录: {item.name}")

小测验

以下哪种文件打开模式会覆盖已有文件?

异常处理

异常是程序运行时发生的错误。Python提供了异常处理机制,使程序能够在遇到错误时优雅地处理,而不是直接崩溃。

常见的异常类型

try-except语句

# 基本的try-except语句
try:
    result = 10 / 0
except ZeroDivisionError:
    print("除数不能为零")

# 捕获多个异常
try:
    num = int("abc")
except ValueError:
    print("无法将字符串转换为整数")
except TypeError:
    print("类型错误")

# 捕获所有异常
try:
    result = 10 / 0
except Exception as e:
    print(f"发生错误: {e}")

try-except-else语句

# try-except-else语句
try:
    num = int("123")
except ValueError:
    print("无法将字符串转换为整数")
else:
    print(f"转换成功: {num}")

try-except-finally语句

# try-except-finally语句
try:
    f = open("example.txt", "r")
    content = f.read()
except FileNotFoundError:
    print("文件不存在")
finally:
    # 无论是否发生异常,finally块中的代码都会执行
    if 'f' in locals():
        f.close()
    print("文件操作完成")

抛出异常

# 使用raise语句抛出异常
def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

try:
    result = divide(10, 0)
except ValueError as e:
    print(f"错误: {e}")

# 抛出内置异常
age = -5
if age < 0:
    raise ValueError("年龄不能为负数")

# 创建自定义异常
class CustomError(Exception):
    pass

def check_value(value):
    if value < 0:
        raise CustomError("值不能为负数")
    return value

try:
    check_value(-5)
except CustomError as e:
    print(f"自定义错误: {e}")

异常的层次结构

Python中的所有异常都继承自BaseException类,常见的异常类继承自Exception类:

# 异常的层次结构示例
try:
    # 可能引发多种异常的代码
    num = int("abc")
    result = 10 / num
except ValueError as e:
    print(f"值错误: {e}")
except ZeroDivisionError as e:
    print(f"除零错误: {e}")
except Exception as e:
    print(f"其他错误: {e}")
else:
    print(f"结果: {result}")
finally:
    print("操作完成")

使用with语句处理资源

with语句可以自动管理资源,如文件、网络连接等,即使在处理过程中发生异常也能正确释放资源:

# 使用with语句处理文件
try:
    with open("example.txt", "r") as f:
        content = f.read()
        # 这里可能会发生异常
        num = int(content)
except ValueError:
    print("文件内容不是有效的整数")
except FileNotFoundError:
    print("文件不存在")
# 文件会自动关闭,无论是否发生异常

面向对象编程

面向对象编程(OOP)是一种编程范式,它使用"对象"来设计应用程序和计算机程序。Python是一种面向对象的语言,支持面向对象编程的所有特性。

类和对象

类是创建对象的蓝图,对象是类的实例。类定义了对象的属性和方法。

# 定义一个简单的类
class Person:
    # 类属性
    species = "人类"
    
    # 初始化方法(构造函数)
    def __init__(self, name, age):
        # 实例属性
        self.name = name
        self.age = age
    
    # 实例方法
    def introduce(self):
        return f"我叫{self.name},今年{self.age}岁。"
    
    # 另一个实例方法
    def celebrate_birthday(self):
        self.age += 1
        return f"生日快乐!我现在{self.age}岁了。"

# 创建对象(实例化)
person1 = Person("张三", 25)
person2 = Person("李四", 30)

# 访问属性
print(person1.name)  # 输出: 张三
print(person2.age)   # 输出: 30

# 访问类属性
print(person1.species)  # 输出: 人类

# 调用方法
print(person1.introduce())  # 输出: 我叫张三,今年25岁。
print(person2.celebrate_birthday())  # 输出: 生日快乐!我现在31岁了。

继承

继承允许我们定义一个类,该类继承另一个类的所有方法和属性。父类是被继承的类,子类是继承父类的类。

# 定义父类
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        raise NotImplementedError("子类必须实现此方法")
    
    def eat(self):
        return f"{self.name}正在吃东西。"

# 定义子类
class Dog(Animal):
    def __init__(self, name, breed):
        # 调用父类的初始化方法
        super().__init__(name)
        self.breed = breed
    
    # 重写父类的方法
    def speak(self):
        return f"{self.name}说:汪汪!"
    
    # 子类特有的方法
    def fetch(self):
        return f"{self.name}正在取球。"

# 定义另一个子类
class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color
    
    def speak(self):
        return f"{self.name}说:喵喵!"
    
    def climb(self):
        return f"{self.name}正在爬树。"

# 创建子类对象
dog = Dog("旺财", "金毛")
cat = Cat("咪咪", "白色")

# 调用方法
print(dog.speak())  # 输出: 旺财说:汪汪!
print(cat.speak())  # 输出: 咪咪说:喵喵!

# 调用继承的方法
print(dog.eat())    # 输出: 旺财正在吃东西。
print(cat.eat())    # 输出: 咪咪正在吃东西。

# 调用子类特有的方法
print(dog.fetch())  # 输出: 旺财正在取球。
print(cat.climb())  # 输出: 咪咪正在爬树。

封装

封装是指将数据(属性)和操作数据的方法捆绑在一起,形成一个独立的对象。在Python中,可以使用访问修饰符来实现封装。

# 封装示例
class BankAccount:
    def __init__(self, account_number, balance=0):
        # 公有属性
        self.account_number = account_number
        
        # 受保护的属性(以单下划线开头)
        self._balance = balance
        
        # 私有属性(以双下划线开头)
        self.__transactions = []
    
    # 公有方法
    def deposit(self, amount):
        if amount > 0:
            self._balance += amount
            self.__transactions.append(f"存款: +{amount}")
            return True
        return False
    
    def withdraw(self, amount):
        if 0 < amount <= self._balance:
            self._balance -= amount
            self.__transactions.append(f"取款: -{amount}")
            return True
        return False
    
    def get_balance(self):
        return self._balance
    
    def get_transactions(self):
        return self.__transactions

# 创建对象
account = BankAccount("1234567890")

# 访问公有属性和方法
print(account.account_number)  # 输出: 1234567890
account.deposit(1000)
account.withdraw(500)

# 访问受保护的属性(不推荐,但可以访问)
print(account._balance)  # 输出: 500

# 尝试访问私有属性(会引发错误)
# print(account.__transactions)  # AttributeError: 'BankAccount' object has no attribute '__transactions'

# 通过方法访问私有属性
print(account.get_transactions())  # 输出: ['存款: +1000', '取款: -500']

多态

多态是指不同类的对象对同一消息(方法调用)可以做出不同的响应。在Python中,多态是通过继承和方法重写实现的。

# 多态示例
class Shape:
    def area(self):
        raise NotImplementedError("子类必须实现此方法")
    
    def perimeter(self):
        raise NotImplementedError("子类必须实现此方法")

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

class Triangle(Shape):
    def __init__(self, base, height, side1, side2, side3):
        self.base = base
        self.height = height
        self.side1 = side1
        self.side2 = side2
        self.side3 = side3
    
    def area(self):
        return 0.5 * self.base * self.height
    
    def perimeter(self):
        return self.side1 + self.side2 + self.side3

# 创建不同形状的对象
rectangle = Rectangle(5, 4)
circle = Circle(3)
triangle = Triangle(4, 3, 3, 4, 5)

# 使用多态
shapes = [rectangle, circle, triangle]

for shape in shapes:
    print(f"形状: {shape.__class__.__name__}")
    print(f"面积: {shape.area()}")
    print(f"周长: {shape.perimeter()}")
    print()

特殊方法(魔术方法)

Python类中有很多以双下划线开头和结尾的特殊方法,它们用于实现类的特定行为。

# 特殊方法示例
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # 字符串表示
    def __str__(self):
        return f"Vector({self.x}, {self.y})"
    
    # 官方字符串表示
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"
    
    # 加法运算
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    # 减法运算
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    
    # 乘法运算(与标量)
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    # 等于比较
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    # 小于比较
    def __lt__(self, other):
        return self.x ** 2 + self.y ** 2 < other.x ** 2 + other.y ** 2

# 创建对象
v1 = Vector(3, 4)
v2 = Vector(1, 2)

# 使用特殊方法
print(v1)  # 调用__str__,输出: Vector(3, 4)
print(repr(v1))  # 调用__repr__,输出: Vector(3, 4)

v3 = v1 + v2  # 调用__add__
print(v3)  # 输出: Vector(4, 6)

v4 = v1 - v2  # 调用__sub__
print(v4)  # 输出: Vector(2, 2)

v5 = v1 * 2  # 调用__mul__
print(v5)  # 输出: Vector(6, 8)

print(v1 == v2)  # 调用__eq__,输出: False
print(v1 < v2)  # 调用__lt__,输出: False

静态方法和类方法

# 静态方法和类方法示例
class MathUtils:
    # 类属性
    PI = 3.14159
    
    # 静态方法(不需要self或cls参数)
    @staticmethod
    def add(a, b):
        return a + b
    
    @staticmethod
    def multiply(a, b):
        return a * b
    
    # 类方法(需要cls参数)
    @classmethod
    def circle_area(cls, radius):
        return cls.PI * radius ** 2
    
    @classmethod
    def circle_circumference(cls, radius):
        return 2 * cls.PI * radius

# 调用静态方法
print(MathUtils.add(5, 3))  # 输出: 8
print(MathUtils.multiply(4, 6))  # 输出: 24

# 调用类方法
print(MathUtils.circle_area(5))  # 输出: 78.53975
print(MathUtils.circle_circumference(5))  # 输出: 31.4159

小测验

在Python中,以下哪个关键字用于调用父类的方法?