你好,我是大虫,哈哈,我们又见面啦!
由于之前写的一篇《【全网最全】50个Python处理Excel示例代码,覆盖95%日常使用场景》 大家反馈不错,于是就筹划了本系列教程。
如果你已经完成了【入门篇】的学习,那么恭喜你已经踏入了编程的世界!
在【进阶篇】中,我们将深入探讨Python的一些核心概念,比如面向对象编程、装饰器、生成器等。
这些内容会让你更深入地理解Python的设计哲学,也会让你的代码更加优雅和高效。
学习过程中可能会遇到一些挑战,但请记住:每个优秀的程序员都是从不断解决问题中成长起来的。
让我们一起继续这段精彩的Python学习之旅吧!记住,编程没有捷径,但有乐趣!
目录
1. 面向对象编程
面向对象编程(OOP)是一种编程范式,通过将数据和操作数据的方法封装在对象中,让程序更易于理解和维护。就像现实世界中的对象一样,每个对象都有自己的属性和行为,这样代码就更贴近我们的思维方式了。
面向对象编程(OOP)是Python的重要特性,它能帮助我们更好地组织和管理代码。
类和对象
面向对象编程(OOP)是Python的重要特性。
python
# 定义一个类
class Dog:
# 类变量(所有实例共享)
species = "犬类"
# 构造方法,初始化对象
def __init__(self, name, age):
# 实例变量(每个实例独有)
self.name = name
self.age = age
# 实例方法
def bark(self):
return f"{self.name}在汪汪叫!"
# 另一个实例方法
def get_info(self):
return f"我是{self.name},今年{self.age}岁,属于{self.species}"
# 创建对象(实例化)
dog1 = Dog("小白", 3)
dog2 = Dog("小黑", 5)
# 调用对象的方法
print(dog1.bark())
print(dog2.get_info())
# 访问对象的属性
print(f"{dog1.name}是{dog1.species}")
# 继承
class Puppy(Dog):
def __init__(self, name, age, toy):
# 调用父类的构造方法
super().__init__(name, age)
self.toy = toy
# 重写父类的方法
def bark(self):
return f"{self.name}在轻轻叫,还不会大声汪汪!"
# 子类特有的方法
def play(self):
return f"{self.name}在玩{self.toy}"
# 创建子类对象
puppy = Puppy("小花", 1, "球")
print(puppy.bark())
print(puppy.play())
print(puppy.get_info()) # 调用继承自父类的方法
# 封装示例
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
# 使用双下划线表示私有属性(名称改写)
self.__balance = balance
# 提供公共方法来访问私有属性
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"存款{amount}元成功"
return "存款金额必须大于0"
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return f"取款{amount}元成功"
return "余额不足或金额无效"
def get_balance(self):
return f"账户余额: {self.__balance}元"
# 使用银行账户类
account = BankAccount("大虫", 1000)
print(account.deposit(500))
print(account.withdraw(200))
print(account.get_balance())
# print(account.__balance) # 这会报错,因为是私有属性
2. 模块与包
模块是包含Python代码的文件,包是组织模块的目录结构。使用模块和包可以让我们更好地组织代码,实现代码的重用。这就像图书馆的分类系统,帮你快速找到需要的书籍(代码)。
模块是一个包含Python代码的文件,包是包含多个模块的目录。
python
# 导入标准库模块
import math
print(math.sqrt(16)) # 4.0
# 导入模块中的特定函数
from math import pi, cos
print(f"圆周率: {pi}")
print(f"cos(0): {cos(0)}")
# 导入模块并给它起别名
import datetime as dt
now = dt.datetime.now()
print(f"当前时间: {now}")
# 创建自己的模块
# 假设我们创建了一个名为 my_utils.py 的文件,内容如下:
"""
def greet(name):
return f"你好, {name}!"
def calculate_area(radius):
import math
return math.pi * radius ** 2
"""
# 然后在其他文件中导入:
# import my_utils
# print(my_utils.greet("大虫"))
# print(my_utils.calculate_area(5))
# 包是包含__init__.py文件的目录
# 目录结构示例:
# mypackage/
# __init__.py
# module1.py
# module2.py
#
# 使用方式:
# from mypackage import module1
# from mypackage.module1 import some_function
3. 常用标准库
Python标准库提供了丰富的功能模块。
python
# 日期和时间处理
import datetime
import time
# 获取当前时间
now = datetime.datetime.now()
print(f"当前时间: {now}")
# 创建特定日期
birthday = datetime.datetime(2000, 1, 1)
print(f"生日: {birthday}")
# 时间计算
today = datetime.date.today()
future_date = today + datetime.timedelta(days=100)
print(f"100天后是: {future_date}")
# 暂停执行
print("开始等待...")
time.sleep(2) # 暂停2秒
print("等待结束!")
# 随机数生成
import random
# 生成随机整数
print(random.randint(1, 10)) # 1到10之间的随机整数
# 从列表中随机选择
colors = ["红", "黄", "蓝", "绿"]
print(random.choice(colors))
# 打乱列表顺序
numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers)
# 文件和路径操作
import os
import pathlib
# 获取当前工作目录
print(f"当前目录: {os.getcwd()}")
# 列出目录内容
print(f"目录内容: {os.listdir('.')}")
# 使用pathlib(更现代的方式)
current_path = pathlib.Path('.')
print(f"当前路径: {current_path}")
print(f"目录中的文件: {[f.name for f in current_path.iterdir() if f.is_file()]}")
# JSON处理
import json
# Python对象转JSON
data = {
"name": "大虫",
"age": 25,
"skills": ["Python", "Java", "C++"]
}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
# JSON转Python对象
json_data = '{"name": "小虫", "age": 30}'
person = json.loads(json_data)
print(person)
4. 列表推导式与生成器
列表推导式提供了一种简洁的创建列表的方式。
python
# 传统方式创建列表
squares = []
for x in range(10):
squares.append(x**2)
print(squares)
# 使用列表推导式
squares = [x**2 for x in range(10)]
print(squares)
# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)
# 处理字符串列表
words = ["hello", "world", "python", "programming"]
upper_words = [word.upper() for word in words]
print(upper_words)
lengths = [len(word) for word in words]
print(lengths)
# 嵌套列表推导式
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)
# 字典推导式
square_dict = {x: x**2 for x in range(5)}
print(square_dict)
# 集合推导式
unique_lengths = {len(word) for word in words}
print(unique_lengths)
# 生成器表达式(节省内存)
# 与列表推导式的区别是使用圆括号而不是方括号
gen = (x**2 for x in range(10))
print(gen) # <generator object <genexpr> at ...>
print(list(gen)) # 转换为列表查看内容
# 生成器函数
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用生成器
fib = fibonacci(10)
print(list(fib))
# 生成器的优点是节省内存,只在需要时计算值
5. 装饰器
装饰器是修改或扩展函数行为的强大工具。
python
# 简单装饰器示例
def my_decorator(func):
def wrapper():
print("函数执行前的操作")
func()
print("函数执行后的操作")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 带参数的装饰器
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"你好, {name}!")
greet("大虫")
# 计算函数执行时间的装饰器
import time
def timer(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:.4f}秒")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "完成"
print(slow_function())
# 使用functools.wraps保持原函数属性
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@my_decorator
def example_function():
"""这是一个示例函数"""
return "示例结果"
print(example_function.__name__) # 如果没有@wraps,这里会显示wrapper
print(example_function.__doc__) # 如果没有@wraps,这里会是None
6. 上下文管理器
上下文管理器用于确保资源得到正确管理(如文件的打开和关闭)。
python
# 使用with语句(上下文管理器)
with open("example.txt", "w", encoding="utf-8") as file:
file.write("使用上下文管理器写入文件")
# 文件会自动关闭,即使发生异常
# 自定义上下文管理器
class MyContextManager:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("退出上下文")
if exc_type is not None:
print(f"发生了异常: {exc_type.__name__}: {exc_value}")
return False # 返回False表示不抑制异常
# 使用自定义上下文管理器
with MyContextManager() as cm:
print("在上下文内部")
# raise ValueError("故意引发异常") # 取消注释查看异常处理
# 使用contextlib模块创建上下文管理器
from contextlib import contextmanager
@contextmanager
def my_context():
print("上下文开始")
try:
yield "上下文中的值"
finally:
print("上下文结束")
with my_context() as value:
print(f"获取到值: {value}")
# 重定向标准输出的示例
from contextlib import redirect_stdout
import io
# 捕获print输出
f = io.StringIO()
with redirect_stdout(f):
print("这段话不会显示在控制台")
print("而是被捕获了")
output = f.getvalue()
print(f"捕获到的输出: {output}")
7. 正则表达式
正则表达式用于匹配字符串模式。
python
import re
# 基本匹配
text = "我的电话号码是13812345678"
pattern = r'1[3-9]\d{9}' # 匹配中国大陆手机号
match = re.search(pattern, text)
if match:
print(f"找到手机号: {match.group()}")
# 查找所有匹配项
text = "Python是一种编程语言,python很受欢迎"
pattern = r'python'
matches = re.findall(pattern, text, re.IGNORECASE) # 忽略大小写
print(f"找到{len(matches)}个匹配项: {matches}")
# 替换文本
text = "我的生日是2023-10-01"
pattern = r'(\d{4})-(\d{2})-(\d{2})'
replacement = r'\3/\2/\1' # 改为日/月/年格式
new_text = re.sub(pattern, replacement, text)
print(new_text)
# 分割字符串
text = "apple,banana;orange:grape"
pattern = r'[,;:]'
parts = re.split(pattern, text)
print(parts)
# 编译正则表达式(提高性能)
pattern = re.compile(r'\b\w+@\w+\.\w+\b') # 匹配邮箱
text = "联系我: zhang@example.com 或 li@test.org"
emails = pattern.findall(text)
print(emails)
# 常用正则表达式模式
# \d 匹配数字
# \w 匹配字母、数字、下划线
# \s 匹配空白字符
# . 匹配任意字符(除换行符)
# * 匹配前一个字符0次或多次
# + 匹配前一个字符1次或多次
# ? 匹配前一个字符0次或1次
# {n} 匹配前一个字符n次
# {n,m} 匹配前一个字符n到m次
# ^ 匹配字符串开头
# $ 匹配字符串结尾
# [] 匹配方括号内的任意字符
# | 或运算
8. 多线程与多进程
多线程和多进程用于并发执行任务。
python
# 多线程示例
import threading
import time
def worker(name, duration):
print(f"线程 {name} 开始工作")
time.sleep(duration)
print(f"线程 {name} 工作完成")
# 创建线程
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(f"Worker-{i}", 2))
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
print("所有线程执行完毕")
# 线程锁(解决资源竞争问题)
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
with lock: # 使用锁保护共享资源
counter += 1
# 创建多个线程修改共享变量
threads = []
for _ in range(5):
t = threading.Thread(target=increment)
threads.append(t)
t.start()
for t in threads:
t.join()
print(f"最终计数器值: {counter}")
# 多进程示例
from multiprocessing import Process, Pool
import os
def worker(name):
print(f"进程 {name} (PID: {os.getpid()}) 开始工作")
time.sleep(2)
print(f"进程 {name} 工作完成")
# 创建进程
processes = []
for i in range(3):
p = Process(target=worker, args=(f"Process-{i}",))
processes.append(p)
p.start()
# 等待所有进程完成
for p in processes:
p.join()
print("所有进程执行完毕")
# 进程池
def square(x):
return x * x
if __name__ == "__main__":
with Pool(4) as pool:
results = pool.map(square, [1, 2, 3, 4, 5])
print(f"平方结果: {results}")
9. 虚拟环境与包管理
虚拟环境用于隔离项目依赖。
python
# 创建虚拟环境 (Python 3.3+)
# python -m venv myenv
# 激活虚拟环境
# Windows: myenv\Scripts\activate
# macOS/Linux: source myenv/bin/activate
# 在虚拟环境中安装包
# pip install requests numpy pandas
# 查看已安装的包
# pip list
# 导出依赖列表
# pip freeze > requirements.txt
# 从依赖列表安装包
# pip install -r requirements.txt
# 退出虚拟环境
# deactivate
# 示例:使用requests库(需先安装)
# import requests
#
# response = requests.get("https://api.github.com")
# if response.status_code == 200:
# print("请求成功")
# print(response.json())
# else:
# print(f"请求失败,状态码: {response.status_code}")
10. 单元测试
单元测试用于验证代码的正确性。
python
import unittest
# 被测试的函数
def add(a, b):
return a + b
def is_even(number):
return number % 2 == 0
# 测试类
class TestMathFunctions(unittest.TestCase):
# 每个测试方法必须以test_开头
def test_add_positive_numbers(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative_numbers(self):
self.assertEqual(add(-1, -1), -2)
def test_add_mixed_numbers(self):
self.assertEqual(add(-1, 1), 0)
def test_is_even_true(self):
self.assertTrue(is_even(4))
def test_is_even_false(self):
self.assertFalse(is_even(5))
# 测试异常
def test_add_with_strings(self):
with self.assertRaises(TypeError):
add("2", 3)
# 运行测试
if __name__ == "__main__":
unittest.main()
# 使用setUp和tearDown
class TestStringMethods(unittest.TestCase):
def setUp(self):
# 在每个测试方法执行前运行
self.test_string = "HelloWorld"
def tearDown(self):
# 在每个测试方法执行后运行
pass
def test_upper(self):
self.assertEqual(self.test_string.upper(), "HELLOWORLD")
def test_isupper(self):
self.assertFalse(self.test_string.isupper())
self.assertTrue("HELLO".isupper())
# 运行特定测试:
# python -m unittest test_module.TestClass
# python -m unittest test_module.TestClass.test_method
11. 实战项目:个人博客系统CLI版本
项目介绍
这个项目将综合运用面向对象编程、文件操作、异常处理等多个知识点,创建一个命令行界面的个人博客系统。通过这个项目,你可以体验到如何构建一个完整的应用程序。虽然界面简陋了点,但"麻雀虽小,五脏俱全",该有的功能一个不少!
个人博客系统(命令行版本), 综合运用面向对象、文件操作、异常处理等知识点。
python
import json
import os
from datetime import datetime
class BlogPost:
def __init__(self, title, content, author, date=None):
self.title = title
self.content = content
self.author = author
self.date = date or datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def to_dict(self):
return {
"title": self.title,
"content": self.content,
"author": self.author,
"date": self.date
}
@classmethod
def from_dict(cls, data):
return cls(data["title"], data["content"], data["author"], data["date"])
class BlogSystem:
def __init__(self, filename="blog_posts.json"):
self.filename = filename
self.posts = self.load_posts()
def load_posts(self):
if os.path.exists(self.filename):
try:
with open(self.filename, "r", encoding="utf-8") as f:
data = json.load(f)
return [BlogPost.from_dict(post) for post in data]
except (json.JSONDecodeError, KeyError):
return []
return []
def save_posts(self):
data = [post.to_dict() for post in self.posts]
with open(self.filename, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def add_post(self, title, content, author):
post = BlogPost(title, content, author)
self.posts.append(post)
self.save_posts()
print("博客发布成功!")
def list_posts(self):
if not self.posts:
print("暂无博客文章")
return
print("\n=== 博客文章列表 ===")
for i, post in enumerate(self.posts, 1):
print(f"{i}. {post.title}")
print(f" 作者: {post.author}")
print(f" 发布时间: {post.date}")
print()
def view_post(self, index):
if 1 <= index <= len(self.posts):
post = self.posts[index-1]
print(f"\n标题: {post.title}")
print(f"作者: {post.author}")
print(f"发布时间: {post.date}")
print(f"内容:\n{post.content}")
else:
print("无效的文章编号")
def delete_post(self, index):
if 1 <= index <= len(self.posts):
deleted = self.posts.pop(index-1)
self.save_posts()
print(f"已删除文章: {deleted.title}")
else:
print("无效的文章编号")
def main():
blog = BlogSystem()
while True:
print("\n=== 个人博客系统 ===")
print("1. 发布新文章")
print("2. 查看文章列表")
print("3. 查看文章详情")
print("4. 删除文章")
print("5. 退出")
choice = input("请选择操作 (1-5): ")
try:
if choice == "1":
title = input("请输入文章标题: ")
content = input("请输入文章内容: ")
author = input("请输入作者姓名: ")
blog.add_post(title, content, author)
elif choice == "2":
blog.list_posts()
elif choice == "3":
blog.list_posts()
if blog.posts:
index = int(input("请输入要查看的文章编号: "))
blog.view_post(index)
elif choice == "4":
blog.list_posts()
if blog.posts:
index = int(input("请输入要删除的文章编号: "))
blog.delete_post(index)
elif choice == "5":
print("感谢使用博客系统!")
break
else:
print("无效的选择,请重新输入")
except ValueError:
print("请输入有效的数字")
except Exception as e:
print(f"发生错误: {e}")
if __name__ == "__main__":
main()
恭喜你完成了进阶篇的学习!现在你已经掌握了Python的核心概念,能够编写更加复杂和结构化的程序了。继续加油,高阶篇在等着你!
后续我将会继续分享本系列教程最后一篇《高阶篇》。敬请期待!
关注"大虫小呓"(全网同名),第一时间获得更多技术干货。