Python 类属性和实例属性

目录:

  1. 类属性与实例属性概述

  2. 类属性示例

  3. 实例属性示例

  4. 实例属性与类属性的对比与应用

  5. 动态设置类属性

类属性与实例属性概述

类属性:类属性是属于类本身而不是类的某个具体实例的变量。这意味着,无论你创建了多少个该类的实例,它们都会共享同一个类属性。修改类属性会影响所有实例。

实例属性:与类属性相对,实例属性是每个实例独立拥有的变量。不同实例可以拥有不同值的实例属性,互不影响。

类属性示例

首先,我们定义一个简单的类Fisherman,并给它添加一个类属性ocean来表示所有渔民共有的捕鱼场所。

class Fisherman:
    # 类属性,所有Fisherman实例共享的捕鱼地点
    ocean = "山海"

    def __init__(self, name):
        # 实例属性,每个渔民的名字
        self.name = name

# 创建两个渔民实例
fisherman1 = Fisherman("摸鱼人甲")
fisherman2 = Fisherman("摸鱼人乙")

print(f"{fisherman1.name} 在 {fisherman1.ocean} 摸鱼。")  # 输出: 摸鱼人甲 在 山海 摸鱼。
print(f"{fisherman2.name} 也在 {fisherman2.ocean} 摸鱼。")  # 输出: 摸鱼人乙 也在 山海 摸鱼。

# 改变类属性,观察影响
Fisherman.ocean = "云梦泽"
print(f"{fisherman1.name} 现在在 {fisherman1.ocean} 摸鱼了。")  # 输出: 摸鱼人甲 现在在 云梦泽 摸鱼了。
print(f"{fisherman2.name} 也在 {fisherman2.ocean}。")  # 输出: 摸鱼人乙 也在 云梦泽。

实例属性示例

接下来,让我们为每位渔民添加一个独特的catch_count实例属性,记录他们的捕鱼数量。

class Fisherman:
    ocean = "山海"  # 类属性

    def __init__(self, name, catch_count=0):
        self.name = name  # 实例属性
        self.catch_count = catch_count  # 实例属性,初始捕鱼数量为0

    def catch_fish(self, number):
        """模拟捕鱼过程,增加捕鱼数量"""
        self.catch_count += number
        print(f"{self.name} 捕获了 {number} 条鱼。")

# 创建渔民实例并捕鱼
fisherman1 = Fisherman("摸鱼人甲")
fisherman2 = Fisherman("摸鱼人乙", 5)  # 摸鱼人乙 初始有5条鱼

fisherman1.catch_fish(3) # 输出: 摸鱼人甲 捕获了 3 条鱼。
fisherman2.catch_fish(2) # 输出: 摸鱼人乙 捕获了 2 条鱼。

print(f"{fisherman1.name} 的捕鱼总数是 {fisherman1.catch_count} 条。")  # 输出: 摸鱼人甲 的捕鱼总数是 3 条。
print(f"{fisherman2.name} 的捕鱼总数是 {fisherman2.catch_count} 条。")  # 输出: 摸鱼人乙 的捕鱼总数是 7 条。

实例属性与类属性的对比与应用

  • 灵活性:实例属性提供了更多的灵活性,因为每个对象可以有不同的状态。这对于模拟真实世界的复杂性和多样性非常有用。

  • 资源效率:类属性在内存中只占用一份空间,所有实例共享,这在处理大量对象且某些信息固定不变时能节省内存。

  • 应用场景:在设计游戏、模拟系统或任何需要大量相似但又不完全相同的对象时,类属性和实例属性的组合使用能够大大提高代码的组织性和效率。

动态设置类属性

动态设置类属性:在开发过程中,有时可能需要根据配置文件或用户输入动态地设置类属性,这可以通过类方法实现。

class Fisherman:
    ocean = "山海"  # 类属性
    
    def __init__(self, name):
        self.name = name

    @classmethod
    def set_common_ocean(cls, new_ocean):
        cls.ocean = new_ocean

# 动态改变捕鱼地点
fisherman3 = Fisherman("摸鱼人丙")
print(f"{fisherman3.name} 在 {fisherman3.ocean}。")  # 输出: 摸鱼人丙 在 山海。
Fisherman.set_common_ocean("桃花源")
print(f"{fisherman3.name} 在 {fisherman3.ocean} 开始了他的捕鱼生涯。")  # 输出: 摸鱼人丙 在 桃花源 开始了他的捕鱼生涯。
fisherman3 = Fisherman("摸鱼人丁")
print(f"{fisherman3.name} 在 {fisherman3.ocean}。")  # 输出: 摸鱼人丙 在 桃花源。

使用类属性进行默认值管理:在【实例属性示例】的Fisherman类中,我们可以看到catch_count使用了默认参数0。实际上,对于复杂的默认值需求,类属性可以作为更灵活的默认值管理方式,避免了每次实例化时重复计算默认值的问题。

在该例中,使用了@classmethodcls

@classmethod 装饰器

作用@classmethod装饰器使得一个方法与类关联,而不是与类的实例关联。这意味着你可以直接通过类名来调用这个方法,而不需要创建类的实例。类方法可以访问类属性,也可以修改它们,因为它接收到的是类本身作为参数。

使用场景

  • 当你需要一个方法来创建类的实例,并且这个方法需要根据类的属性来定制实例时,类方法非常有用。

  • 当一个方法逻辑上属于类,而不是某个具体的实例,比如工厂方法、辅助方法来操作类属性等。

  • 用于实现多态,即子类可以覆盖父类的类方法,提供不同的实现。

cls 参数

含义:在类方法中,cls是一个约定俗成的名称,代表调用该方法的类。你也可以选择其他名称,但cls是最常见的命名方式,因为它清晰地表明了这个参数的意图。通过cls,你可以访问或修改类的属性,调用类的其他类方法,甚至实例化新的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值