• 面向对象编程之类方法@classmethod


    面向对象编程之类方法@classmethod

    首先还是我们熟悉的八股文

    • 类方法 就是针对 类对象 定义的方法

      • 类方法 内部可以直接访问 类属性 或者调用其他的 类方法

    语法如下

    1. @classmethod
    2. def 类方法名(cls):
    3. pass
    '
    运行
    • 类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法

    • 类方法的 第一个参数 应该是 cls

      • 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用

      • 这个参数和 实例方法 的第一个参数是 self 类似

      • 提示 使用其他名称也可以,不过习惯使用 cls

    • 通过 类名. 调用 类方法调用方法时,不需要传递 cls 参数

    在方法内部

    • 可以通过 cls. 访问类的属性

    • 也可以通过 cls. 调用其他的类方法

    示例需求

    • 定义一个 工具类

    • 每件工具都有自己的 name

    需求 —— 在 封装一个 show_tool_count 的类方法,输出使用当前这个类,创建的对象个数

     

    1. @classmethod
    2. def show_tool_count(cls):
    3. """显示工具对象的总数"""
    4. print("工具对象的总数 %d" % cls.count)
    '
    运行

    在类方法内部,可以直接使用 cls 访问 类属性 或者 调用类方法

    类方法:通过@classmethod装饰器实现
    类方法和普通方法的区别:
        类方法只能访问类变量,不能访问实例变量

    直接看代码:

    1. '''
    2. 类方法:通过@classmethod装饰器实现
    3. 类方法和普通方法的区别:
    4. 类方法只能访问类变量,不能访问实例变量
    5. (刨根问底)问题1:为什么类方法中不能够访问实例变量?
    6. 答:因为类方法中的self并不是和创建的对象所绑定--简单点来说,因为self这个参数接收的不是实例本身,而是指向类本身
    7. 注:当你先写装饰器,在定义方法,会发现方法后的()内是cls 而不是self,这就印证了上面的说明!!
    8. 问题2:类方法到底有啥用?
    9. '''
    10. class Student:
    11. def __init__(self,name):
    12. self.name=name
    13. @classmethod
    14. def show(cls):
    15. print('学生的名字为:%s'%cls.name)
    16. s1=Student('小明')
    17. s1.show()

     

    (刨根问底)问题1:为什么类方法中不能够访问实例变量?
        答:因为类方法中的self并不是和创建的对象所绑定--简单点来说,因为self这个参数接收的不是实例本身,而是指向类本身

    1. class Student:
    2. name='dog1'
    3. def __init__(self,name):
    4. self.name=name
    5. @classmethod
    6. def show(self):
    7. print(self)
    8. print('学生的名字为:%s'%self.name)
    9. s1=Student('小明')
    10. s1.show()
    '
    运行

    你会发现类方法中的self指向的是类本身,而不是实例对象

    1. class Student:
    2. name='dog1'
    3. def __init__(self,name):
    4. self.name=name
    5. @classmethod
    6. def show(self):
    7. print(self)
    8. print('学生的名字为:%s'%self.name)
    9. s1=Student('小明')
    10. s1.show()
    11. print(Student)
    '
    运行

    注:当你先写装饰器,在定义方法,会发现方法后的()内是cls 而不是self,这就印证了上面的说明!!

     

    1. class Student2:
    2. num=0
    3. def __init__(self,name):
    4. self.name=name
    5. self.num+=1
    6. print(self.name,self.num)
    7. s2=Student2('小李')
    8. s3=Student2('小红')
    '
    运行

    问题3:为什么num一直是1?

    答:因为这里对num+1是针对的每个新创建的实例对象,而不是针对于整个大类而言

    问题4:如何解决这个问题?

    答:将Self换成类本身即可!!

    1. class Student2:
    2. num=0
    3. def __init__(self,name):
    4. self.name=name
    5. Student2.num+=1
    6. print(self.name,self.num)
    7. s2=Student2('小李')
    8. s3=Student2('小红')
    '
    运行

     但是这个代码有个bug!当你不创建对象,直接对在外部调用num时也可以使数量+1

    1. class Student2:
    2. num=0
    3. def __init__(self,name):
    4. self.name=name
    5. Student2.num+=1
    6. print(self.name,self.num)
    7. s2=Student2('小李')
    8. s3=Student2('小红')
    9. Student2.num+=1
    10. print(Student2.num)
    '
    运行

     

     问题5:如何解决这个问题?

    答:可以使用类方法避免这个问题!

    1. class Student2:
    2. #将num变成一个私有变量
    3. __num=0
    4. def __init__(self,name):
    5. self.name=name
    6. #Student2.num+=1
    7. Student2.gain_num()
    8. print(self.name,self.__num)
    9. @classmethod
    10. def gain_num(cls):
    11. cls.__num+=1
    12. s2=Student2('小李')
    13. s3=Student2('小红')
    14. #Student2.num+=1
    15. print(Student2.num)

     最终的代码如下:有小伙伴们找到bug可以和我交流一下!!

    1. class Student2:
    2. #将num变成一个私有变量
    3. __num=0
    4. def __init__(self,name):
    5. self.name=name
    6. #Student2.num+=1
    7. Student2.__gain_num()
    8. print(self.name,self.__num)
    9. @classmethod
    10. def __gain_num(cls):
    11. cls.__num+=1
    12. s2=Student2('小李')
    13. s3=Student2('小红')
    '
    运行

  • 相关阅读:
    ElasticSearch--整合SpringBoot
    【UniApp】-uni-app-项目计算功能(苹果计算器)
    Spring Boot项目中使用Logback日志与使用AOP拦截请求日志信息
    JavaScript流程控制-循环(循环(for 循环,双重 for 循环,while 循环,do while 循环,continue break))
    02.webpack中多文件打包
    java计算机毕业设计基于安卓Android微信小程序的共享单车租赁系统uniApp
    面试官:去重和幂等的理解掌握多少?
    【ArcGIS微课1000例】0075:将AutoCAD(Dwg、Dxf)文件转换为shp、KML(kml、kmz)文件
    MySQL主从复制和基于Amoeba的读写分离部署
    FCOS目标检测 paper笔记
  • 原文地址:https://blog.csdn.net/qq_46044325/article/details/127041159