杰瑞科技汇

Python类定义的变量如何初始化与访问?

在 Python 类中,变量主要分为两大类:类变量实例变量,理解它们的区别是掌握 Python 面向对象编程的关键。

Python类定义的变量如何初始化与访问?-图1
(图片来源网络,侵删)

类变量

类变量是属于类本身的变量,而不是属于类的某个特定实例,这意味着所有该类的实例都共享同一个类变量,当你修改类变量时,这个修改会影响到所有实例。

如何定义

类变量通常在类定义的顶部,但在任何方法(__init__ 或其他)之外定义。

特点

  • 共享性:所有实例共享同一个值。
  • 定义位置:在类内部,方法之外。
  • 访问方式:可以通过 类名.变量名实例名.变量名 访问。

示例

class Dog:
    # 这是一个类变量
    species = "Canis familiaris"  # 所有狗都属于这个物种
    def __init__(self, name, age):
        # name 和 age 是实例变量,每个实例都有自己独立的副本
        self.name = name
        self.age = age
# --- 使用 ---
# 创建两个 Dog 实例
dog1 = Dog("Buddy", 5)
dog2 = Dog("Milo", 3)
# 访问类变量
print(f"{dog1.name} is a {dog1.species}.")  # 输出: Buddy is a Canis familiaris.
print(f"{dog2.name} is a {dog2.species}.")  # 输出: Milo is a Canis familiaris.
# 通过类名访问类变量
print(f"The species of all dogs is: {Dog.species}") # 输出: The species of all dogs is: Canis familiaris
# 修改类变量
# 注意:这会影响到所有实例
Dog.species = "Canis lupus" # 假设我们改成了狼
print(f"{dog1.name} is now a {dog1.species}.") # 输出: Buddy is now a Canis lupus.
print(f"{dog2.name} is now a {dog2.species}.") # 输出: Milo is now a Canis lupus.

⚠️ 潜在的陷阱

当你通过实例去修改一个类变量时,Python 的行为可能会让你感到意外,它不会修改类本身,而是在该实例上创建一个新的实例变量,屏蔽了类变量。

class Cat:
    species = "Felis catus"
kitty = Cat()
print(f"Initial species via class: {Cat.species}") # 输出: Felis catus
print(f"Initial species via instance: {kitty.species}") # 输出: Felis catus
# 通过实例修改 species
kitty.species = "Panthera pardus" # 假设我们改成了豹猫
# 现在看看发生了什么
print(f"Species via instance after change: {kitty.species}") # 输出: Panthera pardus (这是实例变量)
print(f"Species via class after change: {Cat.species}") # 输出: Felis catus (类变量没有被修改)
# 创建另一个实例
another_cat = Cat()
print(f"Species of another cat: {another_cat.species}") # 输出: Felis catus (它仍然是原来的类变量)

实例变量

实例变量是属于类的实例的变量,每个实例都拥有自己的一套实例变量,它们之间互不影响。

Python类定义的变量如何初始化与访问?-图2
(图片来源网络,侵删)

如何定义

实例变量通常在 __init__ 构造方法中,通过 self 关键字来定义。self 代表类的实例本身。

特点

  • 独立性:每个实例都有自己独立的副本。
  • 定义位置:通常在 __init__ 方法中,通过 self.变量名 定义。
  • 访问方式:只能通过 实例名.变量名 访问。

示例

class Car:
    # 类变量,用于所有汽车
    wheels = 4
    def __init__(self, brand, model, color):
        # 实例变量,每个汽车实例都有自己独立的 brand, model, color
        self.brand = brand
        self.model = model
        self.color = color
        # 每个实例也可以有自己的独立计数器
        self.mileage = 0
# --- 使用 ---
car1 = Car("Toyota", "Camry", "Blue")
car2 = Car("Honda", "Civic", "Red")
# 访问实例变量
print(f"Car 1: {car1.brand} {car1.model}, Color: {car1.color}")
# 输出: Car 1: Toyota Camry, Color: Blue
print(f"Car 2: {car2.brand} {car2.model}, Color: {car2.color}")
# 输出: Car 2: Honda Civic, Color: Red
# 修改 car1 的实例变量,不会影响 car2
car1.color = "Black"
print(f"Car 1's new color: {car1.color}") # 输出: Car 1's new color: Black
print(f"Car 2's color is still: {car2.color}") # 输出: Car 2's color is still: Red
# 修改 car1 的里程数
car1.mileage += 100
print(f"Car 1's mileage: {car1.mileage}") # 输出: Car 1's mileage: 100
print(f"Car 2's mileage: {car2.mileage}") # 输出: Car 2's mileage: 0

其他类型的变量(了解即可)

除了类变量和实例变量,你还会在 Python 中遇到以下两种特殊的“变量”形式,它们在概念上与变量相关,但实现方式不同。

1 实例方法中的局部变量

这些变量定义在方法内部,只在该方法执行期间存在,方法执行完毕后就会被销毁,它们与类和实例无关。

class Calculator:
    def add(self, a, b):
        # result 是一个局部变量
        result = a + b
        return result
calc = Calculator()
total = calc.add(10, 5)
print(total) # 输出: 15
# 在这里无法访问 result,因为它只在 add 方法内有效
# print(result)  # NameError: name 'result' is not defined

2 @property - 将方法伪装成属性

这是一种高级用法,当你不希望直接暴露实例变量,而是想通过一个“受控”的方式来访问或修改它时使用,它定义的方法看起来像一个属性,但可以在访问时执行额外的逻辑。

Python类定义的变量如何初始化与访问?-图3
(图片来源网络,侵删)
class BankAccount:
    def __init__(self, balance):
        # 使用一个下划线开头的变量名来暗示这是一个“受保护的”内部变量
        self._balance = balance
    @property
    def balance(self):
        """这是一个属性访问器,用于获取余额"""
        print("Getting balance...")
        return self._balance
    @balance.setter
    def balance(self, new_balance):
        """这是一个属性设置器,用于设置余额"""
        print("Setting balance...")
        if new_balance < 0:
            print("Error: Balance cannot be negative.")
        else:
            self._balance = new_balance
# --- 使用 ---
account = BankAccount(1000)
# 像访问属性一样调用方法,而不是用括号
print(f"Your balance is: {account.balance}")
# 输出:
# Getting balance...
# Your balance is: 1000
# 像修改属性一样调用方法
account.balance = 1500
print(f"Your new balance is: {account.balance}")
# 输出:
# Setting balance...
# Getting balance...
# Your new balance is: 1500
# 尝试设置负值
account.balance = -500
# 输出:
# Setting balance...
# Error: Balance cannot be negative.
print(f"Your balance is still: {account.balance}")
# 输出:
# Getting balance...
# Your balance is still: 1500

总结与最佳实践

特性 类变量 实例变量
归属 属于本身 属于类的实例
共享性 所有实例共享 每个实例独立拥有
定义位置 类内,方法外 通常在 __init__ 方法中,用 self 定义
内存占用 只有一份 每个实例都有一份
修改影响 修改会影响所有实例 修改只影响当前实例
用途 存储所有实例共享的数据,如物种、分类名等 存储每个实例特有的数据,如姓名、年龄、颜色等

何时使用哪种变量?

  • 使用类变量

分享:
扫描分享到社交APP
上一篇
下一篇