Python:类方法、实例方法与静态方法深度解析(补)

目录

一.实例变量

二.类变量

三.实例方法

四.类方法

五.静态方法

六.小结

总结

今天看程序时,发现自己好像忘了这三者的区别,所以重新写了一篇深度解析,希望之前看博客没看懂的小伙伴可以通过这个博客分清楚这三个方法。跟的是麦叔的课,不是自己的代码!

在 Python的面向对象编程世界里,类方法、实例方法和静态方法犹如三把独特的钥匙,各自开启着不同功能与逻辑的大门。深入理解它们之间的区别与联系,对于构建高效、可读且易于维护的代码体系有着举足轻重的意义。

一.实例变量

实例变量是隶属于类的每个实例对象的独特属性。它们在实例化过程中被初始化,并且每个实例都拥有自己独立的一份副本。这意味着不同实例的同名实例变量可以存储不同的值,彼此之间互不干扰。

以Dog类为例,name,color和weight就是典型的实例变量:

ruby 复制代码
class Dog:
    # name,color......->实例变量,每一条具体的狗都有
    def __init__(self, name, color, weight):
        self.name = name
        self.color = color
        self.weight = weight

当我们创建d1 = Dog('大黄','黄色',10)和d2 = Dog('旺财','黑色',8)两个实例时,d1的name为大黄,color为黄色,weight为10;而d2的name是旺财,color是黑色,weight为8。这些实例变量存储了每个Dog实例特有的信息,使得每个实例都能够在程序中被清晰地识别和区分开来,并且可以根据自身的实例变量值来展现出不同的行为或特性。例如,d1可能因为其较重的体重而在某些行为表现上与体重较轻的d2有所不同,如奔跑速度、耐力等方面的模拟。

二.类变量

类变量则是与整个类相关联的变量,它被类的所有实例所共享。无论创建了多少个类的实例,类变量在内存中只有一份副本,并且对类变量的修改会影响到类的所有实例。

在Dog类中,dogbook就是一个类变量:

ini 复制代码
class Dog:
    dogbook = {'黄色':30,'黑色':20,'白色':0}  # 类变量:一个类里只有这
    # name,color......->实例变量,每一条具体的狗都有
    def __init__(self, name, color, weight):
        self.name = name
        self.color = color
        self.weight = weight

这个dogbook可以用于记录不同颜色狗的数量信息。所有的Dog实例都可以访问这个类变量,并且如果通过某个实例或者类本身对dogbook进行修改,例如增加某种颜色狗的数量,那么这个修改将会在整个类的范围内生效,其他实例看到的dogbook也会是更新后的状态。类变量通常用于存储与类整体相关的信息,如全局配置信息、共享数据等,这些信息不需要在每个实例中单独存储,从而节省内存空间并方便统一管理和维护。

三.实例方法

实例方法是面向对象编程中最为常见且基础的方法类型。它的标志性特征是第一个参数必须为self,这个self并非关键字,只是一种约定俗成的命名方式,其代表的是类的实例对象自身。通过self,实例方法能够深入到实例对象的内部,自由地访问和灵活地操作实例对象所特有的属性。

以一个简单的Dog类为例,我们可以清晰地看到实例方法的运作机制:

ruby 复制代码
class Dog:
    dogbook = {'黄色':30,'黑色':20,'白色':0}  # 类变量:一个类里只有这
    # name,color......->实例变量,每一条具体的狗都有
    def __init__(self, name, color, weight):
        self.name = name
        self.color = color
        self.weight = weight
 
    # 实例方法:传入self作为第一个参数,其他什么都不加,只能用实例调用
    def bark(self):
        print(f'{self.name}叫了起来')
d1 = Dog('大黄', "黄色", 10)
d1.bark()

在上述代码中,__init__方法是一种特殊的实例方法,它在创建类的实例时被自动调用,承担着初始化实例对象属性的重要使命。而 b``ark 方法则是典型的实例方法,当我们创建一个Dog实例,例如d1 = Dog('大黄','黄色',10),并随后调用d1.bark()时,self参数会在后台默默地被 Python 解释器绑定到当前的实例对象d1上。正因为如此,bark方法内部才能精准地获取到d1的name属性,并将这一信息打印输出。

实例方法的核心价值在于,它能够针对每个实例对象的独特性进行定制化的行为和操作。不同的Dog实例,它们各自拥有独立的属性值,而实例方法则可以根据这些不同的属性,展现出各异的行为表现,从而使每个实例都仿佛拥有了属于自己的个性与生命。

四.类方法

类方法在 Python 中是通过@classmethod装饰器来进行定义的,其第一个参数按照惯例被命名为cls,这里的cls代表的是类本身,而非类的某个具体实例。

让我们再次回到Dog类的示例中:

python 复制代码
class Dog:    
    # 类方法:属于狗类,不属于一条具体的狗
    @classmethod
    def dog_num(cls):
        num = 0
        for v in cls.dogbook.values():
            num += v
        return num
d1 = Dog('大黄', "黄色", 10)
d1.bark()
print(f'共有{Dog.dog_num()}条狗')
print(f"共有{d1.dog_num()}条狗")    # 也可以用实例来调用,python会自动帮你把Dog传入代码

在这个例子里,dog.num类方法被设计用于计算狗的总数。它通过直接访问类变量dogbook,遍历其中的值并进行累加,从而得出所有狗的数量统计结果。类方法的一大优势在于,它可以在无需创建类的实例的情况下被直接调用,调用方式为Dog.dog_num。当然,Python 也允许使用实例来调用类方法,例如d1.dog_num,在这种情况下,Python 解释器会自动将类对象Dog隐式地传入方法中,使得操作依然能够顺利地在类层面进行。

类方法的主要应用场景通常集中在与类整体相关的操作上。比如,对类变量的修改、查询或统计等操作,这些操作往往不依赖于某个特定的实例对象,而是与整个类的概念和状态紧密相连。此外,类方法还常常在创建工厂方法时发挥重要作用,工厂方法能够根据特定的规则或输入参数,返回类的实例,从而为对象的创建提供了一种更加灵活和可控的方式。

五.静态方法

静态方法是使用@staticmethod装饰器定义的一类特殊方法。与实例方法和类方法不同,静态方法不需要强制传入代表实例对象的self或者代表类对象的cls参数。从本质上讲,静态方法更像是一个普通的函数,只不过它被定义在了类的命名空间内,从而在逻辑上与类产生了一定的关联。

以Dog类中的total_weight方法为例:

python 复制代码
class Dog:
    @staticmethod
    def total_weight(dogs):
        total = 0
        for dog in dogs:
            total += dog.weight
        return total
 
print(f'狗共重{Dog.total_weight([d1,d2])}公斤')

total_weight静态方法的功能是计算一组狗的总重量。它接收一个由狗的实例组成的列表作为参数,然后通过遍历这个列表,累加每个实例的weight属性值,最终得到所有狗的总重量并返回。需要注意的是,静态方法无法访问类的实例属性或类变量,它的独立性使得它主要适用于那些与类有一定逻辑关联,但又不依赖于类或实例的特定状态的操作。这类操作往往具有工具性的特点,例如数据的转换、验证或者一些简单的计算逻辑,它们虽然与类相关,但并不需要深入到类或实例的内部状态中去获取信息。

六.小结

实例变量存储着每个实例对象的独特数据,使得实例之间相互独立且具有个性化特征。

类变量则为整个类提供共享的数据资源,便于统一管理和维护与类相关的全局信息。

实例方法专注于处理实例对象的个体行为,通过 self 访问实例变量来实现个性化的操作和表现。

类方法着眼于类的整体层面,借助 cls 操作类变量,处理与类整体相关的事务,如统计、配置等。

静态方法作为类中的独立工具函数,与类和实例的状态相对分离,执行一些通用的、与类有逻辑关联但不依赖内部状态的操作。

总代码如下:

python 复制代码
class Dog:
    dogbook = {'黄色':30,'黑色':20,'白色':0}  # 类变量:一个类里只有这
    # name,color......->实例变量,每一条具体的狗都有
    def __init__(self,name,color,weight):
        self.name = name
        self.color = color
        self.weight = weight
        # 此处省略若干行,应该更新dogbook的数量
 
    # 实例方法:传入self作为第一个参数,其他什么都不加,只能用实例调用
    def bark(self):
        print(f'{self.name}叫了起来')
# d1 = Dog('大黄', "黄色", 10)
# d1.bark()
 
# 类方法:属于狗类,不属于一条具体的狗
    @classmethod
    def dog_num(cls):
        num = 0
        for v in cls.dogbook.values():
            num += v
        return num
# d1 = Dog('大黄', "黄色", 10)
# d1.bark()
# print(f'共有{Dog.dog_num()}条狗')
# print(f"共有{d1.dog_num()}条狗")    # 也可以用实例来调用,python会自动帮你把Dog传入代码
 
# 静态方法:不强制传入self,cls,与类无关
    @staticmethod
    def total_weight(dogs):
        total = 0
        for dog in dogs:
            total += dog.weight
        return total
 
print(f'共有{Dog.dog_num()}条狗')
d1 = Dog('大黄', "黄色", 10)
d1.bark()
print(f"共有{d1.dog_num()}条狗")
 
d2 = Dog('旺财','黑色',8)
d2.bark()
 
print(f'狗共重{Dog.total_weight([d1,d2])}公斤')

运行结果如下:

总结

在实际的Python编程实践中,合理且巧妙地选择使用实例方法、类方法和静态方法,就如同在建筑一座大厦时精心挑选合适的建筑材料和结构设计方案。正确的选择能够使代码结构更加清晰明了,各个模块的逻辑更加严谨合理,进而极大地提高代码的可读性和可维护性。例如,当我们需要描述一个对象的个体行为时,实例方法无疑是最佳选择;当涉及到对类整体信息的统计、管理或创建类的实例的统一入口时,类方法能够发挥其独特的优势;而对于那些与类相关但又相对独立的工具性操作,静态方法则能够提供简洁高效的解决方案。

通过对这三种方法的深入剖析和熟练掌握,我们能够在Python的面向对象编程领域中更加游刃有余地构建复杂而强大的程序体系,不断提升代码的质量和开发效率,为打造出优秀的软件产品奠定坚实的基础。

相关推荐
郭庆汝5 小时前
pytorch、torchvision与python版本对应关系
人工智能·pytorch·python
思则变8 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络9 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find10 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取11 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector13 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习13 小时前
Python入门Day2
开发语言·python
Vertira13 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉13 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗13 小时前
黑马python(二十四)
开发语言·python