面向对象编程之类方法@classmethod
首先还是我们熟悉的八股文:
-
类方法 就是针对 类对象 定义的方法
- 在 类方法 内部可以直接访问 类属性 或者调用其他的 类方法
语法如下
@classmethod
def 类方法名(cls):
pass
-
类方法需要用 修饰器
@classmethod
来标识,告诉解释器这是一个类方法 -
类方法的 第一个参数 应该是
cls
-
由 哪一个类 调用的方法,方法内的
cls
就是 哪一个类的引用 -
这个参数和 实例方法 的第一个参数是
self
类似 -
提示 使用其他名称也可以,不过习惯使用
cls
-
-
通过 类名. 调用 类方法,调用方法时,不需要传递
cls
参数
在方法内部
-
可以通过
cls.
访问类的属性扫描二维码关注公众号,回复: 14525918 查看本文章 -
也可以通过
cls.
调用其他的类方法
示例需求
-
定义一个 工具类
-
每件工具都有自己的
name
需求 —— 在 类 封装一个 show_tool_count
的类方法,输出使用当前这个类,创建的对象个数
@classmethod
def show_tool_count(cls):
"""显示工具对象的总数"""
print("工具对象的总数 %d" % cls.count)
在类方法内部,可以直接使用
cls
访问 类属性 或者 调用类方法
类方法:通过@classmethod装饰器实现
类方法和普通方法的区别:
类方法只能访问类变量,不能访问实例变量
直接看代码:
'''
类方法:通过@classmethod装饰器实现
类方法和普通方法的区别:
类方法只能访问类变量,不能访问实例变量
(刨根问底)问题1:为什么类方法中不能够访问实例变量?
答:因为类方法中的self并不是和创建的对象所绑定--简单点来说,因为self这个参数接收的不是实例本身,而是指向类本身
注:当你先写装饰器,在定义方法,会发现方法后的()内是cls 而不是self,这就印证了上面的说明!!
问题2:类方法到底有啥用?
'''
class Student:
def __init__(self,name):
self.name=name
@classmethod
def show(cls):
print('学生的名字为:%s'%cls.name)
s1=Student('小明')
s1.show()
(刨根问底)问题1:为什么类方法中不能够访问实例变量?
答:因为类方法中的self并不是和创建的对象所绑定--简单点来说,因为self这个参数接收的不是实例本身,而是指向类本身
class Student:
name='dog1'
def __init__(self,name):
self.name=name
@classmethod
def show(self):
print(self)
print('学生的名字为:%s'%self.name)
s1=Student('小明')
s1.show()
你会发现类方法中的self指向的是类本身,而不是实例对象
class Student:
name='dog1'
def __init__(self,name):
self.name=name
@classmethod
def show(self):
print(self)
print('学生的名字为:%s'%self.name)
s1=Student('小明')
s1.show()
print(Student)
注:当你先写装饰器,在定义方法,会发现方法后的()内是cls 而不是self,这就印证了上面的说明!!
class Student2:
num=0
def __init__(self,name):
self.name=name
self.num+=1
print(self.name,self.num)
s2=Student2('小李')
s3=Student2('小红')
问题3:为什么num一直是1?
答:因为这里对num+1是针对的每个新创建的实例对象,而不是针对于整个大类而言
问题4:如何解决这个问题?
答:将Self换成类本身即可!!
class Student2:
num=0
def __init__(self,name):
self.name=name
Student2.num+=1
print(self.name,self.num)
s2=Student2('小李')
s3=Student2('小红')
但是这个代码有个bug!当你不创建对象,直接对在外部调用num时也可以使数量+1
class Student2:
num=0
def __init__(self,name):
self.name=name
Student2.num+=1
print(self.name,self.num)
s2=Student2('小李')
s3=Student2('小红')
Student2.num+=1
print(Student2.num)
问题5:如何解决这个问题?
答:可以使用类方法避免这个问题!
class Student2:
#将num变成一个私有变量
__num=0
def __init__(self,name):
self.name=name
#Student2.num+=1
Student2.gain_num()
print(self.name,self.__num)
@classmethod
def gain_num(cls):
cls.__num+=1
s2=Student2('小李')
s3=Student2('小红')
#Student2.num+=1
print(Student2.num)
最终的代码如下:有小伙伴们找到bug可以和我交流一下!!
class Student2:
#将num变成一个私有变量
__num=0
def __init__(self,name):
self.name=name
#Student2.num+=1
Student2.__gain_num()
print(self.name,self.__num)
@classmethod
def __gain_num(cls):
cls.__num+=1
s2=Student2('小李')
s3=Student2('小红')