Python 的面向对象编程

Posted on Tue, 09 Sep 2025 17:28:37 +0800 by LiangMingJian


基本概念

面向对象编程(Object Oriented Programming,OOP)是一种常用的程序设计思想。它要求将对象作为程序的基本单元,一个对象包括了数据属性和操作数据的方法,一堆具有相同数据属性和操作方法的对象就会被抽象为一个类。

简单来说,类(Class)就是工厂生产过程中的模具,对象(Object)就是使用模具生产出的零件,对象又称为类的实例(Instance)。

面向对象编程的三个基本特征是继承、多态和封装。

  • 继承:允许子类继承父类的属性和方法,实现代码复用和层次分类。
  • 多态:同一操作数据方法支持通过重写或重载在不同对象中产生不同结果。
  • 封装:将数据和操作数据的方法绑定在一起,隐藏内部实现细节,只暴露必要接口。

对象 Object:在 Python 中,所有的数据类型,值,变量,函数,类,实例等一切可操作的基本单元是对象,每个对象有三个基本属性:ID,类型和值。

实例 Instance:实例和对象是一个东西,说法的不同主要是应用语境的不同。对一般数据,往往称之为对象,对于类的实现,则称之为实例。

类 Class:类是相似的一组对象的抽象,它能通过代码描述怎么实现这一组对象中所有的成员,并具备这组对象中所有相同的数据属性和操作方法。

类的实现

通过关键字 class 可以定义一个类。然后在对类进行实例时,只需调用函数一样即可。

# 创建一个 People 类
class People:
    pass

# 创建一个 People 类的实例
teacher = People()

类的属性

一个类是可以具有自己的属性的,这个支持的属性又称为类属性。

类属性支持通过类名访问,也支持通过实例访问。另外,类属性的赋值支持在类定义时赋值,也支持在实例化时赋值

通过构建实例化方法 __init__() 可以完成诸如类属性赋值,类初始化等工作。

class People:  
    version = 'v1.0'  
  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
  
teacher = People('Jack', 20) 
print(f'版本: {People.version}')  # 版本: v1.0
print(f'姓名: {teacher.name}')     # 姓名: Jack
print(f'年龄: {teacher.age}')      # 年龄: 20

此外,类属性分为公有属性和私有属性两种。公有属性允许在类实例化之后访问和修改,私有属性则禁止在类实例化后访问和修改,只能由类里面的方法进行访问修改。两种属性的区分通过是否在变量名前具有两个下划线 __

class People:  
    __version = 'v1.0'  
  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
  
    def get_version(self):  
        return self.__version  
  
teacher = People('Jack', 20)  

# 类的公有属性支持修改和访问
teacher.age = 21  
print(f'年龄: {teacher.age}')  # 年龄: 21

# 类的私有属性只能由类方法进行访问和修改,不能直接通过实例访问
print(f'版本: {teacher.get_version()}')  # 版本: v1.0
print(f'版本: {teacher.__version}')  
# AttributeError: 'People' object has no attribute '__version'

特别的,类实例后的对象是允许动态新增属性和方法的,但一般不建议这么使用。

from types import MethodType  
  
class People:  
    __version = 'v1.0'  
  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  

teacher = People('Jack', 20)  
  
# 给实例对象添加属性
teacher.height = 180  

# 给实例对象添加属性
def get_height(self):  
    print(f"身高: {self.height}")  
teacher.get_height = MethodType(get_height, teacher)  

# 支持调用
teacher.get_height()   # 身高: 180
print(teacher.height)  # 180

最后,类提供一个特殊变量 __slots__ 用以限制类属性和方法

__slots__ 是一个字符串元组,它要求类所有的属性名必须在其中声明,没有声明的属性名,禁止被生成,包括实例对象的动态生成(可以不包括类定义的属性)。

此外,在定义特殊变量 __slots__ 后,所有类方法都会变为只读禁止实例化时重写,也禁止实例化之后动态生成。

class People:  
    __slots__ = ('name', 'age')  
    __version = 'v1.0'  # 类定义的属性允许不声明 
  
    def __init__(self, name, age, ids):  
        self.name = name  
        self.age = age  
        self.id = ids  # 这个属性没有被声明,禁止使用
  
    def get_version(self):  
        return self.__version  
  
teacher = People('Jack', 20)
teacher.height = 30  # 这个属性也禁止被添加
teacher.get_height = MethodType(get_height, teacher)  # 这个方法也禁止被添加

类的方法

类方法是指哪些调用了类属性来完成相关功能的方法,它是类各种功能的接口。

一个标准类方法的第一个参数必定是 self,它指代类自身,在调用时被隐式传递,主要作用是用于获取类属性。

class People:  
    __version = 'v1.0'  
  
    def __init__(self, name, age):  
        self.__name = name  
        self.__age = age  
  
    # 类方法
    def get_version(self):  
        return self.__version  
  
    def get_name(self):  
        return self.__name  
  
    def get_age(self):  
        return self.__age  
  
teacher = People('Jack', 20)  
print(f'版本: {teacher.get_version()}')  # 版本: v1.0  
print(f'姓名: {teacher.get_name()}')     # 姓名: Jack  
print(f'年龄: {teacher.get_age()}')      # 年龄: 20

特别的,Python 提供装饰器 @staticmethod@classmethod@property 来实现一些特别的类方法定义。

@staticmethod 实现不调用类属性,并支持不创建类实例就可以直接通过类名调用的类静态方法。

class People:  
  
    @staticmethod  
    def static():  
        print("hello")  

# 直接类名调用
People.static()   # hello v1.0

# 当然,实例化之后调用也支持
teacher = People()  
teacher.static()  # hello v1.0

@classmethod 实现可调用类属性,并·支持不创建类实例就可以直接通过类名调用的类的类方法。

特别的,使用该装饰器的方法的第一个参数必定是 cls,与 self 进行区分,但同样代表类自身。

class People:  
    __version = 'v1.0'  
  
    @classmethod  
    def static(cls):  
        print(f"hello {cls.__version}")  

# 直接类名调用
People.static()   # hello v1.0

# 实例化之后也支持
teacher = People()  
teacher.static()  # hello v1.0

@property 实现实例方法的的属性化,可以将对私有属性的获取,设置,删除方法封装为一个类属性,然后直接通过类属性调用对应方法。

注意,@property 需要指向获取方法,然后记录获取方法,比如为 argopt。然后需要用获取方法的名称结合 setter@argopt.setter 指向设置方法。接着使用 @argopt.deleter 指向删除方法。同时,所有指向的方法名必须相同。

class People:  
    __arg = 0  
  
    @property  
    def argopt(self):  
        return self.__arg  
  
    @argopt.setter  # 装饰器是获取函数名
    def argopt(self, value):  
        self.__arg = value  
  
    @argopt.deleter  # 装饰器是获取函数名
    def argopt(self):  
        del self.__arg
  
teacher = People()  

# 通过类属性调用 setarg 方法
teacher.arg = 21  
# 通过类属性调用 getarg 方法
print(teacher.arg)  
# 通过类属性调用 delarg 方法
del teacher.arg

最后,Python 为类提供了一些默认的属性和方法,以便更好的使用类。

常用的内置属性和方法有:__doc__(类文档),__str__()(类默认输出),__call__()(类默认执行)。

class People:  
    """  
    这里是类的描述  
    """  
    def __str__(self):  
        return '我是默认输出'  
  
    def __call__(self, *args, **kwargs):  
        print('我是默认执行')  
        return 0  
  
teacher = People()  
print(teacher.__doc__)  # 这里是类的描述
print(teacher)         # 我是默认输出
print(teacher())      # 我是默认执行 和 0

类的继承

继承是面向对象编程的一大特征,继承可以使得子类具有父类的属性和方法,并允许对属性和方法进行扩展。

如下述代码,通过继承类 People,类 Teacher 和 Student 复用了类 People 的属性和方法,并自行扩展了更多的属性。

class People:  
  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  

# 继承 People 类
class Teacher(People):  
  
    def __init__(self, name, age, major, school):  
        super().__init__(name, age)  
        self.major = major  
        self.school = school  

# 继承 People 类
class Student(People):  
  
    def __init__(self, name, age, class_id):  
        super().__init__(name, age)  
        self.class_id = class_id  
  
teacher = Teacher("John", 21, "Math", 23)  
student = Student("Tony", 10, 1)

除了常规的单个继承,Python 还提供多重继承的方法,让一个类同时继承多个类。

class People:  
  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
  
class School:  
  
    def __init__(self, school_name, employee_id):  
        self.school_name = school_name  
        self.employee_id = employee_id  

# 同时继承 People 和 School 类
class Teacher(People, School):  
  
    def __init__(self, name, age, school_name, employee_id, major):  
        People.__init__(self, name, age)  
        School.__init__(self, school_name, employee_id)  
        self.major = major  
  
teacher = Teacher("Jack", 35, "MyShcool", "100", "Math")