[二、属性:类变量 vs 实例变量](#二、属性:类变量 vs 实例变量)
前言
Python 从诞生之初就是一门纯面向对象的语言------一切皆对象。无论是数字、字符串,还是函数、模块,背后都是对象的体现。掌握面向对象编程(Object-Oriented Programming, OOP),不仅能让你写出结构清晰、可复用、易维护的代码,更是深入理解 Python 语言本质的关键。
本文将系统讲解 Python 面向对象的核心概念:类与对象、属性与方法、继承与多态、封装与私有性、特殊方法,并通过大量实例助你构建完整的 OOP 思维体系。
一、面向对象基础:类与对象
1. 类(Class)
类是对象的模板, 如果对标游戏的话就是"板子"的意思,它定义了一组具有**相同属性(数据)和方法(行为)**的对象。
2. 对象(Object)
对象是类的具体实例。一个类可以创建多个对象,每个对象拥有独立的状态。放到人类社会的话,意思就是,人类也分为各色各样的人。
例如:定义一个简单的类(狗类)
python
class Dog:
"""狗类"""
# 类变量(所有实例共享)
species = "Canis familiaris"
def __init__(self, name, age):
# 实例变量(每个对象独有)
self.name = name
self.age = age
# 实例方法
def bark(self):
return f"{self.name} says woof!"
# 创建对象(实例化)
my_dog = Dog("Buddy", 3)
your_dog = Dog("Lucy", 5)
print(my_dog.name) # Buddy
print(your_dog.species) # Canis familiaris
print(my_dog.bark()) # Buddy says woof!
关键点:
__init__是构造方法,用于初始化新对象。self代表当前实例,是方法的第一个参数(可改名,但强烈建议用self)。- 不改
self原因主要是因为,当别人看你的代码时能够知道这个参数来自哪里。
二、属性:类变量 vs 实例变量
| 类型 | 定义位置 | 作用域 | 访问方式 |
|---|---|---|---|
| 类变量 | 类内部,方法外部 | 所有实例共享 | ClassName.var 或 obj.var |
| 实例变量 | __init__ 或其他方法中 |
每个实例独有 | self.var |
python
class Counter:
class_count = 0 # 类变量
def __init__(self):
self.instance_count = 0 # 实例变量
Counter.class_count += 1
c1 = Counter()
c2 = Counter()
print(Counter.class_count) # 2(共享)
print(c1.instance_count) # 0(独立)
print(c2.instance_count) # 0(独立)
三、方法类型详解
1. 实例方法(Instance Method)
- 默认类型,第一个参数为
self - 可访问实例变量和类变量
2. 类方法(Class Method)
- 使用
@classmethod装饰器 - 第一个参数为
cls(代表类本身) - 常用于替代构造器或操作类变量
python
class Person:
population = 0
def __init__(self, name):
self.name = name
Person.population += 1
@classmethod
def get_population(cls):
return cls.population
print(Person.get_population()) # 0
p = Person("Alice")
print(Person.get_population()) # 1
3. 静态方法(Static Method)
- 使用
@staticmethod装饰器 - 无
self或cls参数 - 与类相关但不依赖实例或类状态
python
class MathUtils:
@staticmethod
def add(a, b):
return a + b
print(MathUtils.add(2, 3)) # 5
四、继承:代码复用的核心机制
继承允许子类(派生类)获得父类(基类)的属性和方法,实现"is-a"关系。
基本继承
python
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现此方法")
class Cat(Animal):
def speak(self):
return f"{self.name} says meow!"
class Dog(Animal):
def speak(self):
return f"{self.name} says woof!"
animals = [Cat("Whiskers"), Dog("Rex")]
for animal in animals:
print(animal.speak())
# Whiskers says meow!
# Rex says woof!
调用父类方法
使用 super() 显式调用父类方法:
python
class Bird(Animal):
def __init__(self, name, can_fly=True):
super().__init__(name) # 调用父类构造器
self.can_fly = can_fly
多重继承
Python 支持多重继承(谨用):
python
class Flyable:
def fly(self):
return "Flying high!"
class Penguin(Bird, Flyable):
def __init__(self, name):
super().__init__(name, can_fly=False)
def fly(self): # 方法重写
return "Penguins cannot fly!"
注意 :多重继承可能引发"菱形问题",Python 使用 MRO(Method Resolution Order) 解决,可通过
ClassName.__mro__查看。
五、封装与私有性
Python 通过命名约定实现封装:
| 命名方式 | 含义 | 访问建议 |
|---|---|---|
public |
公共属性/方法 | 任意访问 |
_protected |
单下划线 | "内部使用",子类可访问 |
__private |
双下划线 | 名称修饰(name mangling),仅类内访问 |
私有属性示例
python
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 私有属性
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
account = BankAccount(100)
print(account.get_balance()) # 100
# print(account.__balance) # AttributeError!
print(account._BankAccount__balance) # 100(不推荐!)
建议 :使用属性(
@property)提供受控访问:
@property def balance(self): return self.__balance # 使用: print(account.balance)
六、特殊方法
以双下划线开头和结尾的方法称为特殊方法,又称为魔术方法,用于重载运算符或内置函数行为。
常用特殊方法
| 方法 | 用途 | 对应操作 |
|---|---|---|
__str__ |
用户友好字符串 | str(obj) |
__repr__ |
开发者友好字符串 | repr(obj) |
__len__ |
长度 | len(obj) |
__add__ |
加法 | obj1 + obj2 |
__eq__ |
相等比较 | obj1 == obj2 |
运算符重载示例
python
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(1, 4)
print(v1 + v2) # Vector(3, 7)
七、对象生命周期:创建与销毁
构造与析构
__init__: 初始化对象(构造)__del__: 对象销毁前清理(析构,不保证立即调用)
python
class FileManager:
def __init__(self, filename):
self.filename = filename
self.file = open(filename, 'w')
print(f"文件 {filename} 已打开")
def __del__(self):
if hasattr(self, 'file') and not self.file.closed:
self.file.close()
print(f"文件 {filename} 已关闭")
推荐使用上下文管理器(
with):
pythonclass FileManager: def __enter__(self): self.file = open(self.filename, 'w') return self.file def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() with FileManager("data.txt") as f: f.write("Hello")
八、内置工具与反射
动态属性操作
python
emp = Employee("Alice", 5000)
# 检查属性
if hasattr(emp, 'salary'):
print(getattr(emp, 'salary')) # 5000
# 设置属性
setattr(emp, 'department', 'Engineering')
print(emp.department) # Engineering
# 删除属性
delattr(emp, 'department')
内置类属性
python
print(Employee.__doc__) # 类文档字符串
print(Employee.__name__) # 'Employee'
print(Employee.__module__) # '__main__'
print(Employee.__bases__) # 父类元组
print(Employee.__dict__) # 类命名空间字典
九、建议与使用原则
- 优先组合而非继承:避免深层继承树
- 小而专注的类:单一职责原则
- 使用
@property控制属性访问 - 抛出有意义的异常 :如
NotImplementedError - 文档化公共接口:使用 docstring
- 避免过度使用私有属性:Python 信奉"我们都是 consenting adults"
小结
面向对象编程不是语法特性,而是一种思维方式。它帮助我们将复杂问题分解为相互协作的对象,使代码更接近现实世界的模型。
"好的 OOP 不是为了炫技,而是为了让代码更容易理解、扩展和维护。"
从定义第一个类开始,到设计复杂的继承体系,再到利用特殊方法定制对象行为------每一步都在让你离"Pythonic"代码更近。现在,就用面向对象的思想,去构建你的下一个项目吧!
希望这篇文章对大家能够有所帮助,你们的点赞和关注是对我最大的支持和帮助!