尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python面向对象编程(一)
前言面向对象编程Object-Oriented ProgrammingOOP的教科书通常会列出三大特性封装、继承、多态。但把这套从 Java、C 课本里搬来的说法直接套到 Python 上很容易写出别扭的代码因为 Python 的 OOP 有自己的脾气。最大的误解是Python 的私有属性用双下划线实现。实际上 Python 没有强制访问控制双下划线只是名字改写name mangling。第二个误解是多态必须靠继承实现——Python 是靠鸭子类型duck typing实现多态的只要对象有需要的方法它就能用跟继承关系无关。作为系列第一篇本文讲清类与实例、self的含义、封装、继承和多态在 Python 里的真实形态并给出可以直接运行的示例。一、从类到实例类是模板实例是具体对象。创建实例的过程叫实例化会调用__init__做初始化。# 适用于 Python 3.8class Cat:species 猫科 # 类属性def __init__(self, name, age):self.name name # 实例属性self.age agedef meow(self):return f{self.name}: 喵def birthday(self):self.age 1return self.agec Cat(咪咪, 2)print(c.meow()) # 咪咪: 喵print(c.birthday()) # 3print(c.species) # 猫科print(Cat.species) # 猫科print(c.__dict__) # {name: 咪咪, age: 3}self不是关键字只是第一个参数的习惯命名它指向调用方法的那个实例。写成def meow(this)也能跑但没人这么写。二、封装约定优于强制Python 的封装靠的是命名约定和接口设计而不是访问修饰符。约定有三档写法约定含义是否被语言强制name公开否_name内部使用请勿依赖否__name触发名字改写_类名__name仅防子类重名__name__特殊方法/属性由解释器使用# 适用于 Python 3.8class BankAccount:def __init__(self, owner, balance0):self.owner ownerself._balance balance # 内部使用def deposit(self, amount):if amount 0:raise ValueError(金额必须为正)self._balance amountpropertydef balance(self):return self._balance # 只读视图acc BankAccount(Ada, 100)acc.deposit(50)print(acc.balance) # 150try:acc.balance 0 # 只读会报错except AttributeError as e:print(AttributeError:, e)property把balance变成只读属性这是 Python 里表达对外只读的正规做法比到处写_balance更清晰。三、继承复用与扩展继承用class Sub(Base):。子类获得父类的属性和方法并可以重写。# 适用于 Python 3.8class Employee:def __init__(self, name, salary):self.name nameself.salary salarydef annual(self):return self.salary * 12def describe(self):return f{self.name}: 年薪 {self.annual()}class Manager(Employee):def __init__(self, name, salary, bonus):super().__init__(name, salary)self.bonus bonusdef annual(self):return super().annual() self.bonusm Manager(Bob, 10000, 50000)print(m.describe()) # Bob: 年薪 170000print(isinstance(m, Employee)) # Truem.describe()调用的是父类的方法但内部self.annual()走的是子类的重写版本。这就是多态的基础父类代码无需知道子类细节也能调用到子类的实现。四、多态与鸭子类型Python 的多态不要求共享基类。只要对象看起来像鸭子、叫起来像鸭子就能当鸭子用# 适用于 Python 3.8class Duck:def speak(self):return 嘎嘎class Robot:def speak(self):return 哔哔def make_speak(obj):return obj.speak() # 不检查类型只要求有 speakfor thing in (Duck(), Robot()):print(make_speak(thing))上面make_speak既不检查类型也不要求它们有共同父类。这种风格叫鸭子类型duck typing是 Python 动态类型系统的直接体现。如果确实需要必须是某类可以用isinstance()或抽象基类来显式约束。多态实现方式依赖关系适用场景继承 重写共享基类有明确层次结构的领域模型鸭子类型只依赖方法名通用工具函数、协议式接口抽象基类显式接口契约库的公开扩展点协议typing.Protocol结构化类型提示静态检查、类型注解五、特殊方法让对象融入语言实现了特殊方法dunder method你的对象就能像内置类型一样工作支持len()、、for、in等。# 适用于 Python 3.8class Playlist:def __init__(self, songsNone):self._songs list(songs) if songs is not None else []def add(self, song):self._songs.append(song)def __len__(self):return len(self._songs)def __getitem__(self, index):return self._songs[index]def __contains__(self, song):return song in self._songsdef __repr__(self):return fPlaylist({self._songs!r})p Playlist([a, b])p.add(c)print(len(p)) # 3print(p[0]) # aprint(b in p) # Trueprint(p) # Playlist([a, b, c])六、综合示例一个简单的形状体系# 适用于 Python 3.8class Shape:def area(self):raise NotImplementedErrordef describe(self):return f{type(self).__name__}: 面积 {self.area()}class Rect(Shape):def __init__(self, w, h):self.w, self.h w, hdef area(self):return self.w * self.hclass Square(Rect):def __init__(self, side):super().__init__(side, side)for s in (Rect(2, 3), Square(4)):print(s.describe())type(self).__name__让父类方法拿到实际子类的名字这比写死字符串更稳。常见坑点把双下划线当私有❌python # 适用于 Python 3.8 class A: def __init__(self): self.__v 1 # 以为外部完全访问不到✅python # 适用于 Python 3.8 class A: def __init__(self): self._v 1 # 约定式内部属性子类忘记调super().__init__()❌python # 适用于 Python 3.8 class Manager(Employee): def __init__(self, name, salary, bonus): self.bonus bonus # name、salary 都没设✅python # 适用于 Python 3.8 class Manager(Employee): def __init__(self, name, salary, bonus): super().__init__(name, salary) self.bonus bonus用type(x) T做多态分发❌python # 适用于 Python 3.8 if type(x) Employee: # 子类匹配不上 ...✅python # 适用于 Python 3.8 if isinstance(x, Employee): # 含子类 ...可变默认参数❌python # 适用于 Python 3.8 class A: def __init__(self, items[]): self.items items✅python # 适用于 Python 3.8 class A: def __init__(self, itemsNone): self.items [] if items is None else list(items)父类方法里硬编码父类名导致子类行为失效❌python # 适用于 Python 3.8 class Shape: def describe(self): return f{Shape.__name__}: {self.area()}✅python # 适用于 Python 3.8 class Shape: def describe(self): return f{type(self).__name__}: {self.area()}接口只写在文档里忘了用NotImplementedError兜底❌python # 适用于 Python 3.8 class Shape: def area(self): pass # 子类忘了实现也不会报错✅python # 适用于 Python 3.8 class Shape: def area(self): raise NotImplementedError鸭子类型忘了做属性检查❌python # 适用于 Python 3.8 def make_speak(obj): return obj.speak() # 传错对象时是 AttributeError信息不明确✅python # 适用于 Python 3.8 def make_speak(obj): if not hasattr(obj, speak): raise TypeError(对象必须提供 speak()) return obj.speak()总结特性Python 的实现方式封装命名约定 property非强制继承class Sub(Base)super()沿 MRO多态鸭子类型为主继承/抽象基类为辅特殊方法让对象融入len、、for等语法私有双下划线仅做名字改写Python 的 OOP 是约定 鸭子类型的组合封装靠命名和接口多态靠方法名匹配而非继承树。写类时先把方法和属性想清楚再考虑要不要继承能用鸭子类型解决的不必强加继承层次。
RELATED

相关推荐

多AI助手协同下的凭证泄露与RCE风险:从SSO到命令执行的完整链路

多AI助手协同下的凭证泄露与RCE风险:从SSO到命令执行的完整链路

1. 事件还原:一个标题引发的技术圈震荡“离谱,OpenAI被Opus 5黑了!”——这个标题在技术社区刷屏的时候,我正蹲在工位上调试一个CI流水线。第一反应是:又是标题党吧?但点进去看了几眼讨论,发现事…

📅 2026/10/17 12:19:39
AI大模型当复习搭子:从费曼讲解到错题归因的完整备考闭环

AI大模型当复习搭子:从费曼讲解到错题归因的完整备考闭环

备考这种事,最磨人的往往不是知识本身,而是那种一个人闷头刷题、错了还不知道错在哪儿的无力感。我也是在准备一门硬核专业认证时才真正把AI大模型当成“复习搭子”来用——不是临时查资料,而是让它从讲解、出题、判分到归因,全程…

📅 2026/10/17 12:14:39
Scala+Spark实战:WordCount与TopKey完整实现及性能调优

Scala+Spark实战:WordCount与TopKey完整实现及性能调优

1. 从一个WordCount说起:为什么它成了大数据入门的“必修课” 但凡接触过分布式计算的人,几乎都绕不开WordCount这个例子。它就像编程语言里的“Hello World”,看似简单,却把分布式计算最核心的几个概念—— 数据分片、并行处理…

📅 2026/10/17 12:14:39
MORE NEWS

更多资讯

📰

Stable Diffusion室内设计实战:从毛坯房到风格效果图的AI辅助流程

Stable Diffusion这名字刚火起来的时候,我周围大部分设计师朋友都在拿它画二次元头像或者魔改人像。直到有一天,我试着把一张空荡荡的毛坯房照片丢进图生图,让它“重装修”了一遍,出来的画面真的让我愣了好几秒——原本灰扑扑的水…

📰

用视频生成搭一座桥:动作剪影如何让机器人学会预演未来

我最近在调试一个机械臂抓取实验时,发现一个挺扎心的事实:机器人缺的不是“看见”的能力,而是“预见”的能力。现在的视觉系统能把每一个像素都拍得清清楚楚,但你问它“做完这个动作之后画面会变成什么样”,它答不上来…

📰

为什么new出来的MonoBehaviour不执行Start?深度解析Unity生命周期调用链

写这篇文章之前,我想先聊一个很典型的场景:某开发者A在项目里写了一个继承自MonoBehaviour的脚本,里面定义了Start方法,然后在另一个脚本里直接new了一个这个类,结果发现Start压根没执行。他跑来问我,说Uni…

📰

YOLOv11农业病害识别实战:从数据准备到部署全流程

1. 项目思路拆解:为什么拿YOLOv11做农业病害识别1.1 病害识别的本质不是分类,是定位农业病害识别这个需求,我刚接触时也有人拿图像分类模型直接怼。比如弄一个 ResNet,把一张叶子照片丢进去,告诉你是“有锈病”还是“没…

📰

九宫格与方块轮盘抽奖H5实现:核心逻辑、性能优化与避坑指南

九宫格抽奖和方块轮盘抽奖,这两个东西听起来像是运营活动页面的“标配”,但真正动手写的时候,你会发现坑比想象中多得多。我做过不下十个类似的抽奖H5,从最早的纯CSS动画硬怼,到后来用Canvas重写,再到现在的…

📰

AI接入飞书机器人:基于OpenClaw的完整实践与排错指南

先说结论:把 AI 接进飞书这件事,难点从来不在模型本身,而在于如何把一个跑在终端里的原型,变成一个同事真的愿意在群里 的常驻机器人。我上个月用 OpenClaw 做了一个完整的飞书机器人接入,现在它在好几个测试群里稳定…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬