python3.7.9
vscode + Pylance
实例变量就是__init__函数初始化中的变量
而类变量类似于C++中的静态成员变量。
class Dog:
dogbook = {
'黄色':0,'白色':0,'黑色':0}
def __init__(self,name,color,weight) -> None:
self.name = name
self.color = color
self.weight = weight
dogbook是类变量
name、color、weight是实例变量
最常使用的就是实例方法
class Dog:
def __init__(self,name,color,weight) -> None:
self.name = name
self.color = color
self.weight = weight
Dog.dogbook[color]+=1
def bark(self):
print("{}叫了起来".format(self.name))
dog1 = Dog("大黄","黄色","10kg")
dog1.bark()
特点:
以@staticmethod标识
class Dog:
dogbook = {
'黄色':0,'白色':0,'黑色':0}
def __init__(self,name,color,weight) -> None:
self.name = name
self.color = color
self.weight = weight
@staticmethod
def emotion():
print("小狗们很开心")
dog1 = Dog("大黄","黄色","10kg")
dog1.emotion()
Dog.emotion()
需要用@classmethod标识
class Dog:
dogbook = {
'黄色':0,'白色':0,'黑色':0}
def __init__(self,name,color,weight) -> None:
self.name = name
self.color = color
self.weight = weight
def bark(self):
print("{}叫了起来".format(self.name))
@classmethod
def total_number(cls):
total = sum(cls.dogbook.values())
print("共有{}条狗狗".format(total))
dog1 = Dog("大黄","黄色","10kg")
dog1.bark()
Dog.total_number()
dog1.total_number()
总结:
其实classmethod的功能很多都可以由其它方法实现。
比如前面的,cls.func()可以用Dog.func()代替
但classmethod中引入的cls参数具有类似多态的作用:
它会自动判断是调用的哪一个子类(基类)的函数
class Dog:
color = "黄色、白色和黑色"
dogbook = {
'黄色':0,'白色':0,'黑色':0}
def __init__(self,name,color,weight) -> None:
self.name = name
self.color = color
self.weight = weight
Dog.dogbook[color]+=1
@classmethod
def showColor(cls):
print("这是{}的狗狗".format(cls.color))
class YellowDog(Dog):
color = '黄色'
def __init__(self, name, weight) -> None:
super().__init__(name, "黄色", weight)
class BlackDog(Dog):
color = '黑色'
def __init__(self, name, weight) -> None:
super().__init__(name, "黑色", weight)
class WhiteDog(Dog):
color = '白色'
def __init__(self, name, weight) -> None:
super().__init__(name, "白色", weight)
dogs = [YellowDog("大黄",12),BlackDog("二黑",23),WhiteDog("小白",12)]
for dog in dogs:
dog.showColor()
这样就不需要在子类中重写showColor方法,利用多态&继承实现了代码复用。
以上的@classmethod等修饰符,在我的测试中不加也是可以的。
其实很明显:这几种方法是靠self和cls来实现的。只需要把self和cls看作是类的成员变量(并且是保留字,不会和用户的自定义变量产生冲突),这几种方法没有本质区别。并且完全不需要用修饰符来区分。
但我翻阅的博客均加上了修饰符,兼容起见,还是加上这个修饰符比较好。