当前位置:首页>python>Python3 面向对象:把代码组织得像现实世界一样

Python3 面向对象:把代码组织得像现实世界一样

  • 2026-10-11 08:36:46
Python3 面向对象:把代码组织得像现实世界一样

Python3 面向对象:把代码组织得像现实世界一样

我是陈默,一个正拼命上岸的码农。

你有没有想过,为什么现实世界这么好理解?

因为一切都是"对象"。狗有名字、有品种、会叫。车有品牌、有颜色、会跑。每个对象都有自己的属性和行为。

面向对象编程就是把这种思维搬进代码里。

今天我们用一个实际的例子,把 Python 面向对象的核心概念一次性讲清楚。


1. 类和对象:图纸和产品

类是图纸,对象是按图纸造出来的产品。

定义一个类

classDog:def__init__(self, name, breed):        self.name = name      # 属性:名字        self.breed = breed    # 属性:品种defbark(self):        print(f"{self.name}:汪汪!")definfo(self):        print(f"我是{self.name},品种是{self.breed}")

创建对象

dog1 = Dog("旺财", "柴犬")dog2 = Dog("来福", "金毛")dog1.info()    # 输出: 我是旺财,品种是柴犬dog2.info()    # 输出: 我是来福,品种是金毛dog1.bark()    # 输出: 旺财:汪汪!dog2.bark()    # 输出: 来福:汪汪!

同一张图纸,不同的产品。每个对象有自己的数据,共享相同的方法。

__init__ 和 self

  • __init__ 是初始化方法,创建对象时自动调用
  • self 代表对象自己,相当于"我"
# 这两行做的事情一样dog1 = Dog("旺财", "柴犬")# Python 内部大概是这样:# dog1 = Dog.__new__(Dog)# Dog.__init__(dog1, "旺财", "柴犬")# self 就是 dog1

self 必须写,但调用的时候不用传。Python 自动帮你传。


2. 属性:对象的数据

实例属性:每个对象独有

classStudent:def__init__(self, name, score):        self.name = name        self.score = scores1 = Student("陈默", 85)s2 = Student("小明", 92)print(s1.name)     # 输出: 陈默print(s2.name)     # 输出: 小明

类属性:所有对象共享

classStudent:    school = "Python 大学"# 类属性,所有学生共享    count = 0def__init__(self, name, score):        self.name = name        self.score = score        Student.count += 1# 每创建一个学生,计数加1s1 = Student("陈默", 85)s2 = Student("小明", 92)print(s1.school)          # 输出: Python 大学print(s2.school)          # 输出: Python 大学print(Student.count)      # 输出: 2

实例属性是"我的",类属性是"大家的"。


3. 方法:对象的行为

实例方法

最普通的方法,第一个参数是 self:

classCircle:def__init__(self, radius):        self.radius = radiusdefarea(self):return3.14 * self.radius ** 2defperimeter(self):return2 * 3.14 * self.radiusc = Circle(5)print(c.area())       # 输出: 78.5print(c.perimeter())  # 输出: 31.400000000000002

__str__:打印对象时显示什么

classStudent:def__init__(self, name, score):        self.name = name        self.score = scoredef__str__(self):returnf"{self.name}({self.score}分)"s = Student("陈默", 85)print(s)    # 输出: 陈默(85分)

不加 __str__,print 输出的是 <__main__.Student object at 0x...>,没人看得懂。


4. 继承:孩子继承父母的基因

子类可以继承父类的属性和方法,还能扩展自己的。

基本继承

classAnimal:def__init__(self, name):        self.name = namedefeat(self):        print(f"{self.name}在吃东西")defsleep(self):        print(f"{self.name}在睡觉")# Dog 继承 AnimalclassDog(Animal):defbark(self):        print(f"{self.name}:汪汪!")# Cat 继承 AnimalclassCat(Animal):defmeow(self):        print(f"{self.name}:喵喵~")dog = Dog("旺财")cat = Cat("小花")dog.eat()     # 输出: 旺财在吃东西(继承来的)dog.bark()    # 输出: 旺财:汪汪!(自己的)cat.eat()     # 输出: 小花在吃东西(继承来的)cat.meow()    # 输出: 小花:喵喵~(自己的)

Dog 和 Cat 自动拥有 eat() 和 sleep(),不用重写。

方法重写(Override)

子类可以覆盖父类的方法:

classAnimal:defspeak(self):        print("...")classDog(Animal):defspeak(self):        print("汪汪!")classCat(Animal):defspeak(self):        print("喵喵~")animals = [Dog(), Cat()]for a in animals:    a.speak()# 输出:# 汪汪!# 喵喵~

同一个方法,不同的表现。这就是多态。

super():调用父类的方法

classStudent:def__init__(self, name, score):        self.name = name        self.score = scoreclassGraduateStudent(Student):def__init__(self, name, score, research):        super().__init__(name, score)    # 调用父类的 __init__        self.research = research         # 添加自己的属性definfo(self):        print(f"{self.name}:{self.score}分,研究方向:{self.research}")gs = GraduateStudent("陈默", 92, "人工智能")gs.info()    # 输出: 陈默:92分,研究方向:人工智能

super() 让你不用重复写父类的初始化逻辑。


5. 封装:把细节藏起来

私有属性

用双下划线 __ 开头的属性,外面不能直接访问:

classBankAccount:def__init__(self, owner, balance):        self.owner = owner        self.__balance = balance    # 私有属性defdeposit(self, amount):if amount > 0:            self.__balance += amount            print(f"存入{amount}元,余额{self.__balance}元")defwithdraw(self, amount):if amount > self.__balance:            print("余额不足")elif amount > 0:            self.__balance -= amount            print(f"取出{amount}元,余额{self.__balance}元")defget_balance(self):return self.__balanceaccount = BankAccount("陈默", 1000)account.deposit(500)       # 输出: 存入500元,余额1500元account.withdraw(200)      # 输出: 取出200元,余额1300元# 不能直接改余额# account.__balance = 999999    # 不管用print(account.get_balance())    # 输出: 1300

封装的核心:数据只能通过方法修改,防止外部乱改。

用 property 更优雅

classStudent:def__init__(self, name, score):        self.name = name        self.__score = score    @propertydefscore(self):return self.__score    @score.setterdefscore(self, value):ifnot0 <= value <= 100:raise ValueError("分数必须在0-100之间")        self.__score = values = Student("陈默", 85)print(s.score)       # 输出: 85(像属性一样访问)s.score = 92# 调用 setter,带验证print(s.score)       # 输出: 92s.score = 150# 报错!ValueError: 分数必须在0-100之间

@property 让方法用起来像属性,但背后有验证逻辑。


6. 类方法和静态方法

类方法:操作类级别的数据

classStudent:    school = "Python 大学"    count = 0def__init__(self, name):        self.name = name        Student.count += 1    @classmethoddefget_count(cls):return cls.count    @classmethoddefchange_school(cls, new_name):        cls.school = new_names1 = Student("陈默")s2 = Student("小明")print(Student.get_count())      # 输出: 2Student.change_school("Java 大学")print(Student.school)           # 输出: Java 大学

静态方法:跟类和对象都没关系的工具

classMathTools:    @staticmethoddefadd(a, b):return a + b    @staticmethoddefis_even(n):return n % 2 == 0print(MathTools.add(3, 5))       # 输出: 8print(MathTools.is_even(4))      # 输出: True

三种方法怎么选?

  • 需要访问实例数据 → 实例方法(self)
  • 需要访问类级别的数据 → 类方法(@classmethod)
  • 跟类和实例都没关系 → 静态方法(@staticmethod)

7. 魔术方法:让对象更像内置类型

classScoreList:def__init__(self, scores):        self.scores = scoresdef__len__(self):return len(self.scores)def__getitem__(self, index):return self.scores[index]def__contains__(self, item):return item in self.scoresdef__str__(self):returnf"成绩列表:{self.scores}"def__add__(self, other):return ScoreList(self.scores + other.scores)scores = ScoreList([85, 92, 78])print(len(scores))       # 输出: 3print(scores[0])         # 输出: 85print(92in scores)      # 输出: Trueprint(scores)            # 输出: 成绩列表:[85, 92, 78]combined = scores + ScoreList([90, 88])print(combined)          # 输出: 成绩列表:[85, 92, 78, 90, 88]

魔术方法让你的自定义对象用起来像列表、像数字、像字符串。


8. 实战:一个完整的类

classTodoList:"""待办事项管理器"""def__init__(self, owner):        self.owner = owner        self.__todos = []defadd(self, task):        self.__todos.append({"task": task, "done": False})        print(f"添加:{task}")defcomplete(self, index):if0 <= index < len(self.__todos):            self.__todos[index]["done"] = True            print(f"完成:{self.__todos[index]['task']}")else:            print("序号不存在")defshow(self):        print(f"\n{self.owner} 的待办:")for i, item in enumerate(self.__todos):            status = "✓"if item["done"] else"○"            print(f"  {i}. [{status}] {item['task']}")        pending = sum(1for t in self.__todos ifnot t["done"])        print(f"  共{len(self.__todos)}项,待完成{pending}项\n")def__len__(self):return len(self.__todos)def__str__(self):        pending = sum(1for t in self.__todos ifnot t["done"])returnf"{self.owner}的待办:{pending}项待完成"# 使用my_list = TodoList("陈默")my_list.add("学 Python 面向对象")my_list.add("写一篇公众号文章")my_list.add("跑步 5 公里")my_list.complete(0)my_list.show()print(my_list)        # 输出: 陈默的待办:2项待完成print(len(my_list))   # 输出: 3

最后

面向对象不是什么高深的东西。它就是把现实世界的思维方式搬进代码。

记住三件事:

  1. 类是图纸,对象是产品。__init__ 是初始化,self 是"我"
  2. 继承让代码复用,封装让数据安全,多态让接口统一
  3. 先写简单的类,再慢慢加继承和封装。别一开始就想太多

我的建议:

挑一个你熟悉的东西——手机、图书、订单——用类把它描述出来。给它属性,给它方法。先跑起来,再慢慢优化。

面向对象不是学出来的,是写出来的。

今天就到这里。

我是陈默,我们下期再见。


如果你觉得这篇文章有帮助,欢迎关注我。我会持续分享 Python 学习的干货。

最新文章

随机文章