Python 面向对象基础:从类到实例,再到方法与属性

在 Python 中,面向对象编程(OOP)是一种重要的编程范式,它通过“类”和“对象”来组织代码,使程序更易于扩展和维护。本文将带你从零开始理解 Python 中的类、对象、属性以及各种方法,并通过大量代码示例巩固概念。

1. 类与对象:蓝图与实体

1.1 什么是类?

是创建对象的蓝图或模板。它定义了一组属性和方法,描述了对象“长什么样”以及“能做什么”。在 Python 中使用 class 关键字定义类。

class Dog:
    pass          # 一个空类

1.2 什么是对象?

对象 是根据类创建出来的具体实体。同一个类可以实例化出多个对象,每个对象拥有自己的数据(实例属性),但共享相同的行为(方法)。

class Dog:
    def bark(self):
        print("Woof!")

# 创建对象(实例化)
my_dog = Dog()
my_dog.bark()     # 输出: Woof!

创建对象的语法是 类名(),这个过程称为实例化

1.3 类本身也是对象

在 Python 中,类本身也是一个对象,它属于 type 类型。这意味着你可以像操作普通对象一样操作类:将其赋值给变量、作为函数参数等。

class Car:
    pass

print(type(Car))          # <class 'type'>
print(isinstance(Car, type))  # True

2. 属性:描述对象的状态

属性分为类属性实例属性,它们的作用域和生命周期不同。

2.1 实例属性(属于具体对象)

实例属性是绑定到每个具体对象上的数据,不同对象的实例属性互不影响。通常在 __init__ 方法中通过 self.属性名 = 值 来定义。

class Student:
    def __init__(self, name, score):
        self.name = name      # 实例属性
        self.score = score

s1 = Student("Alice", 95)
s2 = Student("Bob", 87)

print(s1.name, s1.score)   # Alice 95
print(s2.name, s2.score)   # Bob 87

2.2 类属性(属于类对象)

类属性直接定义在类内部,所有实例共享同一个类属性。可以通过 类名.属性名实例.属性名 访问,但推荐使用类名访问以避免歧义。

class Teacher:
    school = "第一中学"      # 类属性

    def __init__(self, name):
        self.name = name

t1 = Teacher("张老师")
t2 = Teacher("李老师")

print(t1.school)   # 第一中学
print(t2.school)   # 第一中学

# 修改类属性会影响所有实例(通过类名修改)
Teacher.school = "第二中学"
print(t1.school)   # 第二中学
print(t2.school)   # 第二中学

注意:如果通过实例对类属性赋值,并不会修改类属性,而是为该实例动态创建了一个同名的实例属性,这会遮蔽类属性。

3. 方法:定义对象的行为

在类中定义的函数称为方法。根据第一个参数和装饰器的不同,分为实例方法、类方法和静态方法。

3.1 实例方法

最常见的类型,第一个参数为 self,指向调用该方法的实例。实例方法可以访问实例属性和类属性。

class Counter:
    count = 0                 # 类属性,记录实例个数

    def __init__(self):
        Counter.count += 1
        self.id = Counter.count

    def show_id(self):        # 实例方法
        print(f"我是第 {self.id} 个实例")

c1 = Counter()
c2 = Counter()
c1.show_id()   # 我是第 1 个实例
c2.show_id()   # 我是第 2 个实例

3.2 类方法

使用 @classmethod 装饰器,第一个参数为 cls,指向类本身。类方法可以访问和修改类属性,但不能直接访问实例属性。常用于工厂模式或操作类级别的数据。

class Person:
    species = "Human"

    def __init__(self, name):
        self.name = name

    @classmethod
    def change_species(cls, new_species):
        cls.species = new_species

    @classmethod
    def from_string(cls, data_str):
        """工厂方法:根据字符串创建实例"""
        name = data_str.split("-")[0]
        return cls(name)

# 使用类方法修改类属性
Person.change_species("Homo sapiens")
print(Person.species)   # Homo sapiens

# 类方法作为工厂
p = Person.from_string("Alice-25")
print(p.name)           # Alice

3.3 静态方法

使用 @staticmethod 装饰器,没有 selfcls 参数。它本质上是一个放在类命名空间里的普通函数,与类和实例的状态无关。适合存放一些工具函数。

class MathUtils:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def is_even(num):
        return num % 2 == 0

# 直接通过类名调用
print(MathUtils.add(3, 5))      # 8
print(MathUtils.is_even(10))    # True

4. 构造与初始化:__init__ 方法

很多教程称 __init__ 为构造函数,但严格来说它不是构造函数。真正的对象创建由 __new__ 方法完成,__init__ 只是在对象创建之后对其进行初始化。

  • __new__:静态方法,负责分配内存并返回一个对象实例。
  • __init__:实例方法,负责设置实例的初始状态(给实例属性赋值)。

我们平时几乎不需要重写 __new__,但需要知道这个区别。

class Example:
    def __new__(cls, *args, **kwargs):
        print("1. __new__ 被调用,创建对象")
        instance = super().__new__(cls)
        return instance

    def __init__(self, value):
        print("2. __init__ 被调用,初始化对象")
        self.value = value

e = Example(10)
# 输出:
# 1. __new__ 被调用,创建对象
# 2. __init__ 被调用,初始化对象

5. 综合对比表格

类型 第一个参数 装饰器 访问实例属性 访问类属性 典型用途
实例方法 self 操作实例数据
类方法 cls @classmethod 操作类属性、工厂方法
静态方法 @staticmethod 工具函数,逻辑上属于类

6. 小结

  • 是蓝图,对象是根据蓝图创建的实体;类本身也是 type 类型的对象。
  • 实例属性属于具体对象,在 __init__ 中通过 self 定义;类属性属于类本身,所有实例共享。
  • 实例方法可以操作实例和类的数据;类方法可以操作类数据,常用于工厂模式;静态方法是独立工具函数。
  • __init__ 是初始化方法而非真正的构造函数,真正的构造由 __new__ 完成。

掌握这些基础概念之后,你就可以用面向对象的方式组织 Python 程序了。下一阶段可以学习继承、多态、以及更高级的魔法方法。希望本文对你的学习有所帮助!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐