当前位置: 首页 > news >正文

Day 2 学习主题「面向对象 + Pythonic 风格」

导语:为什么你必须掌握这些技能?

写 Python,不只是会用语法,更关键在于写出优雅、可维护、具备“Python味儿”的代码。今天这篇,我们将聚焦在 Python 面向对象的核心特性 + Pythonic 风格写法,掌握这些,代码瞬间高级起来,职场加分必备!

知识点预览

本篇你将学到:

  • 如何使用类、继承、多态构建可拓展的结构

  • 魔法方法:__init____str____repr__ 的使用场景

  • @staticmethod@classmethod 的实际用途

  • 常用 Pythonic 内置函数:map()filter()sorted()

  • with 和上下文管理器,轻松优雅资源管理

1️⃣ 背景介绍:为什么要学面向对象 + Pythonic 写法?

Python 既是面向对象语言,也是功能强大的脚本语言。但真正能写出“高级感”的 Python 代码,往往离不开:

  • 清晰的类结构设计(面向对象思想)

  • 简洁的语法表达能力(Pythonic 写法)

这两者结合,能让你的代码可复用、易维护、开发效率高,还能让团队成员读得懂、用得爽。


2️⃣ 技术方案拆解:关键概念与语法详解

✅ 类与对象基础
class Animal:def __init__(self, name):self.name = namedef speak(self):return f"{self.name} makes a sound"dog = Animal("Buddy")
print(dog.speak())  # Buddy makes a sound
✅ 继承、多态、组合
class Dog(Animal):def speak(self):return f"{self.name} says Woof!"class Cat(Animal):def speak(self):return f"{self.name} says Meow!"def make_sound(animal):print(animal.speak())  # 多态:传不同对象,行为不同make_sound(Dog("Max"))
make_sound(Cat("Luna"))

组合示例:

class Engine:def run(self):print("Engine running")class Car:def __init__(self):self.engine = Engine()def start(self):self.engine.run()
✅ 魔法方法精讲
class User:def __init__(self, name):self.name = namedef __str__(self):  # 面向用户return f"User: {self.name}"def __repr__(self):  # 面向开发者/调试return f"User(name='{self.name}')"print(str(User("Alice")))
print(repr(User("Bob")))
class User:

定义了一个名为 User 的类,表示“用户”对象。


def __init__(self, name):

这是 Python 中的 构造方法(构造函数),当我们创建对象时会自动调用它。

User("Alice")

这行代码会触发:

__init__(self="实例本身", name="Alice")

它的作用是给对象绑定一个属性 self.name = name,即将 "Alice" 存入该实例的 name 属性中。


def __str__(self):

这是 Python 的 魔法方法之一,用于定义对象被 str() 函数或 print() 打印时的“用户友好”展示形式。

str(User("Alice"))  
# 调用的是 __str__,输出是:
# User: Alice

📌 设计意图:

  • 给终端用户看的(比如打印日志)

  • 强调可读性


def __repr__(self):

同样是魔法方法,用于定义对象被 repr() 或直接在解释器中回显时的表现形式。

repr(User("Bob"))  
# 调用的是 __repr__,输出是:
# User(name='Bob')

📌 设计意图:

  • 面向程序员和调试者

  • 目标是“清晰明确”且尽可能“可复现”这个对象(repr 的本意就是“representation”)

一个优秀的 __repr__ 通常写成能被 eval() 复现的格式,比如:

user = eval(repr(User("Bob")))  # 理论上能还原一个等价对象

两者区别对比
特性__str____repr__
触发方式print(obj) or str(obj)repr(obj) or 直接在解释器中输出
面向谁用户开发者
目的可读性明确性 / 可复现性
优先级__str__print 用它没有 __str__print 会 fallback 到 __repr__

输出结果解析
print(str(User("Alice")))
# 输出:User: Aliceprint(repr(User("Bob")))
# 输出:User(name='Bob')

✔️ str() 调用用户友好的展示形式
✔️ repr() 调用程序员友好的调试形式


建议与实践
  • 如果你只定义了 __repr__print(obj) 也会自动 fallback 使用它;

  • 日常写类时,建议至少实现 __repr__

  • 如果你的对象有日志或打印需求,同时实现两者更好,分别服务不同人群。


@staticmethod vs @classmethod
class MathTool:@staticmethoddef add(a, b):return a + b  # 与类无关@classmethoddef from_string(cls, data):a, b = map(int, data.split(','))return cls(a + b)  # 依赖类信息def __init__(self, value):self.value = valueprint(MathTool.add(3, 5))  # 8
obj = MathTool.from_string("10,20")
print(obj.value)  # 30
类定义与构造方法
class MathTool:def __init__(self, value):self.value = value
  • 这个类用于封装一个数值(value)。
  • 实例化时传入一个数值,存到 self.value 中。
@staticmethod:静态方法
@staticmethod
def add(a, b):return a + b
特点:
  • 不需要访问类(cls)或实例(self
  • 就是一个“和类放在一起的普通函数”,逻辑上属于类,但技术上和类无关
使用方式:
MathTool.add(3, 5)  # 输出:8

你也可以通过对象调用,但本质一样:

obj = MathTool(0)
obj.add(1, 2)  # 也是 3

📌 适用场景: 工具类、纯函数逻辑封装,不依赖对象或类状态。

@classmethod:类方法
@classmethod
def from_string(cls, data):a, b = map(int, data.split(','))return cls(a + b)
特点:
  • 第一个参数是 cls(当前类),不是实例
  • 可用于“构造器方法”:根据特定格式构建实例
  • cls(...) 可以调用构造方法创建实例(和 __init__ 绑定)
使用方式:
obj = MathTool.from_string("10,20")

等价于:

a, b = 10, 20
value = a + b  # 30
obj = MathTool(30)

📌 适用场景:

  • 多个“构造入口”需求(常见于数据解析、工厂模式)
  • 要兼容子类返回对象

总结对比:@staticmethod vs @classmethod
特性@staticmethod@classmethod
参数无默认参数第一个参数是 cls
是否可创建对象❌ 无法访问类信息✅ 可返回类的实例
是否访问类状态可以
场景工具方法、无状态逻辑多构造方法、工厂方法
调用方式ClassName.method()ClassName.method()

最后两行输出解析
print(MathTool.add(3, 5))  # 输出:8
  • 调用静态方法,简单加法运算
obj = MathTool.from_string("10,20")
print(obj.value)  # 输出:30
  • 调用类方法,将字符串 "10,20" 拆解为 10 和 20,加和后传入构造器
  • 返回一个 MathTool(30) 对象,obj.value == 30

实战建议
  • 若你只是想组织函数,不依赖类:用 @staticmethod
  • 若你要构造对象(甚至考虑子类化扩展):用 @classmethod
  • 实际项目中,from_xxx 类方法很常见(如:from_dictfrom_json

3️⃣ Pythonic 写法提升代码气质

内置函数妙用
# map:批量转换
names = ['alice', 'bob', 'charlie']
print(list(map(str.title, names)))  # ['Alice', 'Bob', 'Charlie']# filter:条件筛选
scores = [60, 75, 82, 40]
passed = list(filter(lambda x: x >= 60, scores))
print(passed)  # [60, 75, 82]# sorted:支持 key 自定义
students = [{'name': 'Tom', 'score': 88}, {'name': 'Jerry', 'score': 95}]
print(sorted(students, key=lambda s: s['score'], reverse=True)) #[{'name': 'Jerry', 'score': 95}, {'name': 'Tom', 'score': 88}]

4️⃣ with 语句 & 上下文管理器:优雅资源控制

with open("data.txt", "r") as f:content = f.read()
# 自动关闭文件,无需 f.close()
#写入文件
with open("output.txt", "w") as f:f.write("Hello, World!")
#逐行读取
with open("data.txt", "r") as f:for line in f:print(line.strip())

自定义上下文管理器:

class Timer:def __enter__(self):import timeself.start = time.time()return selfdef __exit__(self, *args):print(f"Time used: {time.time() - self.start:.2f}s")with Timer():sum(range(1000000))
什么是上下文管理器?
  • 上下文管理器是指实现了 __enter__()__exit__() 方法的对象。

  • 它可以与 with 语句一起使用,用于自动处理资源获取和释放,比如打开/关闭文件、连接数据库、计时器等。

1. __enter__(self)
def __enter__(self):import timeself.start = time.time()return self
  • with Timer() 执行时,会首先调用 __enter__()

  • 这里记录了当前时间 self.start,作为起始时间戳。

  • return self 表示可以通过 as 关键字获得这个对象(本例没用 as 但依然返回了)。

2. __exit__(self, *args)
def __exit__(self, *args):print(f"Time used: {time.time() - self.start:.2f}s")
  • with 代码块执行完之后(无论是否报错),都会自动调用 __exit__() 方法。

  • 它会再次获取当前时间,与开始时间 self.start 相减,输出耗时。

3. with Timer(): ...

这行执行过程如下:

步骤发生了什么
1调用 Timer().__enter__(),记录开始时间
2执行 sum(range(1000000))
3调用 Timer().__exit__(),计算并输出耗时
输出示例(根据运行速度不同略有差异):
Time used: 0.04s

表示 sum(range(1000000)) 执行用了大约 0.04 秒。


实战扩展:使用 with Timer() as t

你可以拓展它,让用户使用 as 获得 Timer 实例,从而访问时间值:

class Timer:def __enter__(self):import timeself.start = time.time()return selfdef __exit__(self, *args):self.end = time.time()self.interval = self.end - self.startprint(f"耗时:{self.interval:.4f} 秒")with Timer() as t:total = sum(range(1000000))# 你也可以访问 t.interval
小结:自定义计时器的常见用途
用途示例
性能测试检查某段代码执行是否过慢
自动记录脚本运行耗时CLI 工具、批处理脚本
替代手动打 log 时间戳简化日志输出逻辑

5️⃣ 常见问题与踩坑提醒

问题原因解决方案
@staticmethod 无法访问类属性它不绑定类@classmethod
__str__ 显示乱码没有实现添加 __str__ 方法
with open() 报错文件不存在或编码问题加入异常处理,检查路径

6️⃣ 拓展建议与进阶路径

  • 探索 Python 的数据模型(Data Model)完整魔法方法表

  • 阅读优秀开源项目源码(Flask, FastAPI)看他们如何组织类

  • 深入理解组合 vs 继承设计模式

总结 & 实用建议

掌握面向对象,不仅仅是会写类,更重要的是如何设计结构和行为;掌握 Pythonic 写法,不只是记语法,而是理解 Python 的「表达哲学」。这两者结合,将让你写出既专业又易读的 Python 程序,迈向高级工程师之路。

相关文章:

  • Linux服务器部署Leantime与cpolar构建低成本团队协作环境
  • 数据分享:汽车行业-汽车属性数据集
  • 英特尔汽车业务败走中国,喊出“All in”才过两个月
  • 测试方法的分类
  • 香港维尔利健康科技集团推出AI辅助医学影像训练平台,助力医护人才数字化转型
  • aws(学习笔记第四十七课) codepipeline-docker-build
  • 深入解析设备管理系统新趋势:物联网与云原生驱动的智能化实践
  • 软件测试之基于博客系统项目的性能测试
  • 大数据赋能智慧城市:从数据洪流到科学规划的“智慧之匙”
  • 互联网医院系统源码解析:如何实现视频问诊、电子处方等核心功能?
  • 详解零拷贝
  • 面试150 验证回文串
  • 七天学会SpringCloud分布式微服务——02——第一个微服务项目
  • Redis-基本命令
  • Tailwind CSS 尺寸控制
  • 兰洋科技上合组织论坛发表专题分享,全球液冷布局引领绿色算力未来
  • 开发基于Jeston Orin Nx 开发版 16G的实现
  • YOLO+ONNX+PyQt打包为exe踩坑记录
  • ASP.NET Core Web API 实现 JWT 身份验证
  • (LeetCode 面试经典 150 题 ) 55. 跳跃游戏 (贪心)