QQ登录

只需一步,快速开始

开启左侧

Python学习第六十七天—类和对象16-类方法和静态方法

[复制链接]
15271953841 发表于 2024-4-5 08:35:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 15271953841 于 2024-4-6 16:55 编辑

类方法和静态方法
类里面定义的函数叫方法,但类没有办法自己直接调用它,需要通过实例对象操作才行,因为方法需要对象来绑定。
一、        类方法:专门用于绑定类的方法,用@classmethod这个装饰器来实现。
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
class C:
    def funA(self):       (先定义一个普通的方法,用于绑定实例对象的)
        print(self)
    @classmethod        (再定义一个类方法,需要使用一个@classmethod这么一个装饰器,那么funB就是一个类方法。)
    def funB(cls):
        print(cls)

        
c = C()                   (实例化一个对象小c)
c.funA()                   (普通的方法绑定的是一个对象,绑定的是一个object)
<__main__.C object at 0x0000022E84CBBBF0>
c.funB()                      (再看一下类方法)
<class '__main__.C'>              (打印的__main__.C,是一个class,它是一个类)
那么类方法到底有什么用?类方法的特点是绑定类,而非实例对象,这是它的一个特点。
一个人学习编程之后,他就解锁了对象自由,那么有时候对象一多起来,就可能需要程序能够统计一下这个对象的数量,或者说通过创建一个列表来维护一个类对应的所有对象。那么对于这类型的需求,我们就可以通过类方法来实现。
class C:
    count = 0             (给个类属性count)
    def __init__(self):
        C.count += 1        (当这个构造函数被调用的时候,也就是在实例化对象的时候)
    @classmethod
    def get_count(cls):
        print(f"该类一共实例化了{cls.count}个对象")

        
c1 = C()
c2 = C()
c3 = C()                 (实例化了3个对象)
c1.get_count()            (c1是随便调用一个实例对象,看统计的是否准确)
该类一共实例化了3个对象
c3.get_count()
该类一共实例化了3个对象
c3.count = 1               (如果在对象中去创建一个跟类属性同名的实例属性,后者会覆盖类属性,不过这里get_count是类方法,所以就算不小心实例属性覆盖了类属性,但问题也不大。)不受影响。
c3.count
1
c3.get_count()
该类一共实例化了3个对象           (可以看出,不受影响)
这里不使用类方法同样是可以实现的呀?
确实,这里直接使用类名来访问类属性也是ok,但是涉及到继承问题,使用类方法无疑就会有更大的优势,不急,在这节课的最后就有一个升级版的demo(演示、示范),大家看到最后一对比就清晰了。

二、静态方法:放在类里面的函数,跟普通函数的区别是它们可以放到类里面去。我们说在类里面的函数叫方法,是因为方法需要跟对象进行绑定,但是函数却没有绑定的操作,静态方法就是让你做到在类里面定义一个不需要绑定的函数,还是通过一个例子,通过一个演示(demo)来告诉大家怎么玩。
class C:
    @staticmethod                (创建一个静态函数使用的装饰器@staticmethod)
    def funC():                    (它不需要任何参数进行绑定)
        print("I love FishC.")

        
c = C()
c.funC()                        (可以通过对象小c来访问这个静态方法)
I love FishC.
C.funC()                       (也可以通过类名来访问这个静态方法)
I love FishC.
那么使用静态方法也可以效仿类的方法来做一个统计实例化对象数量的demo.
class C:
    count = 0
    def __init__(self):
        C.count += 1
    @staticmethod                (这里做了一个修改,与本课时的开头的一个列子比较)
    def get_count():             (这个地方的参数也去掉了,因为静态方法是不需要绑定的)
        print(f"该类一共实例化了{C.count}个对象。")      (原来是cls的位置,由于没有绑定,我们这里就拿不到这个类,我们可以直接点名C.count)

        
c1 = C()
c2 = C()
c3 = C()
c3.get_count()
该类一共实例化了3个对象。
C.get_count()
该类一共实例化了3个对象。
那么使用静态方法也不用担心对象覆盖这个属性的问题,因为我们点名C.count去获取这个类的一个属性。
到底是类方法好用,还是静态方法好用呢?还是要看应用场景,因地制宜,比如说,当操作不涉及类属性,或者实例属性引用的时候,我们使用静态方法比较合适;但是如果是像统计实例对象数量这种任务交由类方法来实现更好。修改本课时开头的例子。
class C:
    count = 0
    def __init__(self):
        C.count += 1
    @staticmethod
    def get_count():
        print(f"该类一共实例化了{C.count}个对象。")

        
c1 = C()
c2 = C()
c3 = C()
c3.get_count()
该类一共实例化了3个对象。
C.get_count()
该类一共实例化了3个对象。
class C:
    count = 0
    @classmethod             (添加另一个clasmethod)
    def add(cls):             (另外一个类方法,称作add)
        cls.count += 1
    def __init__(self):
        self.add()             (直接调用self.add())
    @classmethod
    def get_count(cls):
        print(f"该类一个实例化了{cls.count}个对象。")
调整后,当实例化对象发生时,构造函数就会去调用它的一个,这个对象的add方法,那么add由于是一个类方法,所以它会自动将对应的类给传递进去,那么这里面的cls.count += 1,就相当于对应的类属性的count += 1,递增1,这样做的好处是什么?现在我们涉及了继承问题。
        
class D(C):
    count = 0              (重写覆盖一个类属性count)

   
class E(C):
    count = 0

   
c1 = C()
d1,d2 = D(),D()
e1,e2,e3 = E(),E(),E()
c1.get_count()
该类一个实例化了1个对象。
d1.get_count()
该类一个实例化了2个对象。
e1.get_count()
该类一个实例化了3个对象。

当代码涉及到继承的时候,实例对象的数量统计就稍微变得复杂了一丢丢。那么类方法的优势也因此就显现出来了,为什么要独立出一个@类方法,这样做的好处显然为了实现自动化,这里我们让构造函数去调用@类方法,那么我们就不用管它是子类,还是父类,反正谁去调,谁就会自动把对应的类传递进去,那么递增的也就是该类对应的count类属性,相当于各回各家,各找各妈,所以我们要做的是继承的时候,覆盖一下对应的count属性就可以了,这样就可轻松地实现各个类统计各个类实例的对象。

客服热线
400-1234-888 周一至周日:09:00 - 21:00
公司地址:襄阳市樊城区长虹路现代城5号楼188

创客帮MAKER.BAND青少年创客创意社区是一个融教育、科技、体育资讯为一体的综合服务平台,专注于教育创新、专注于科技体育、专注于教育资讯。

Powered by Discuz! X3.4 © 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表