面向对象基础
本教程共 70 篇 · 第 31 篇 · 更新于 2026-07-22 · 约 5 分钟阅读
31. 面向对象基础
本节目标:理解「类」和「对象」的区别,学会用
class定义类,用__init__初始化实例,搞懂self到底是什么。
前面我们写的代码都是面向过程(procedure-oriented)的:把问题拆成一个个函数,按顺序调用。这种写法在小项目里没问题,但代码一多,数据和函数散落在各处,维护起来很头疼。
面向对象编程(Object-Oriented Programming,简称 OOP)换了一种思路:把数据和操作数据的方法打包在一起,形成一个「类(class)」。类就像一张设计图纸,而根据图纸造出来的东西叫「实例(instance)」或「对象(object)」。
从一个例子感受 OOP
假设你要管理学生信息。面向过程的写法可能是这样的:
stu1 = {'name': '张三', 'score': 85}
stu2 = {'name': '李四', 'score': 92}
def print_score(stu):
print(f"{stu['name']}: {stu['score']}")
print_score(stu1)
数据是字典,操作数据的函数单独定义。如果字段多了、逻辑复杂了,这种写法会越来越乱。
用面向对象改写:
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print(f"{self.name}: {self.score}")
stu1 = Student('张三', 85)
stu2 = Student('李四', 92)
stu1.print_score()
stu2.print_score()
name 和 score 跟操作它们的方法绑在了一起。逻辑清晰,扩展也方便。
定义类和创建实例
在 Python 里,用 class 关键字定义类:
class Dog:
pass
d = Dog()
print(type(d)) # <class '__main__.Dog'>
类名通常用大驼峰命名法(CamelCase),比如 StudentInfo、HttpRequest。
init 方法:初始化实例
类里可以定义一个特殊方法 __init__,它在创建实例时自动执行,用来给实例设置初始状态:
class Cat:
def __init__(self, name, age):
self.name = name
self.age = age
c = Cat('咪咪', 2)
print(c.name) # 咪咪
print(c.age) # 2
__init__ 的第一个参数固定叫 self,代表实例本身。后面跟的参数,在创建实例时传入。
Note
__init__方法返回None,不能显式写return其他值。你只管在里面给实例绑定属性就好。
self 是什么
self 这个单词不是关键字,你可以改成别的名字,但全世界都用 self,你也跟着用。
它代表「当前实例」。当你调用 stu1.print_score() 时,Python 在背后做了这件事:Student.print_score(stu1)。也就是说,实例方法会自动把调用者当成第一个参数传进去。
class Demo:
def show(self):
print(f"self 的 id: {id(self)}")
d = Demo()
print(f"d 的 id: {id(d)}")
d.show()
运行后你会发现两个 id 完全一样。这就是 self 的本质:它就是实例自己。
实例属性和方法
绑定属性
属性可以动态绑定,不限于 __init__ 里定义的那些:
class Book:
def __init__(self, title):
self.title = title
b = Book('Python 入门')
b.price = 39.9 # 动态绑定新属性
print(b.price) # 39.9
Warning动态绑定属性很灵活,但也会让代码变得难以追踪。建议把实例该有的属性都在
__init__里声明,方便别人阅读。
定义方法
类里的函数叫「方法(method)」。第一个参数必须是 self,这样它才能访问实例的属性:
class Rectangle:
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)
r = Rectangle(3, 4)
print(r.area()) # 12
print(r.perimeter()) # 14
方法内部通过 self.width、self.height 读写实例属性。
类属性 vs 实例属性
类属性是定义在类体里、不在任何方法内的变量。它属于类本身,所有实例共享同一份:
class Dog:
kind = 'canine' # 类属性
def __init__(self, name):
self.name = name # 实例属性
d1 = Dog('旺财')
d2 = Dog('来福')
print(d1.kind) # canine
print(d2.kind) # canine
print(d1.name) # 旺财
print(d2.name) # 来福
如果通过实例去修改类属性,Python 会给这个实例新建一个同名的实例属性,并不会影响类本身:
d1.kind = 'husky'
print(d1.kind) # husky(实例属性)
print(d2.kind) # canine(类属性没变)
print(Dog.kind) # canine
Tip类属性适合放「所有实例都一样」的数据,比如计数器、常量配置。实例属性放「每个实例各自不同」的数据。
给类加计数器
一个类属性的经典用法:统计一共创建了多少个实例。
class User:
count = 0
def __init__(self, name):
self.name = name
User.count += 1
u1 = User('Alice')
u2 = User('Bob')
print(User.count) # 2
注意这里用 User.count += 1,不是 self.count += 1。如果用后者,会变成给实例绑定新属性,计数就失效了。
小结
- 类是模板,实例是根据模板创建的对象。
__init__在实例创建时自动执行,用来初始化属性。self代表实例本身,是实例方法的第一个参数。- 实例属性每个对象独立;类属性所有对象共享。
你可以把类想象成一个模具厂。class 是模具的设计图,__init__ 是每次开模时的初始化操作,self 就是流水线上当前那块正在加工的材料。
来源:参考了 runoob「Python3 面向对象」、liaoxuefeng「面向对象编程」和「类和实例」、pythondoc「9. 类」等,改写后所得。