对于 Python 类的属性和方法,我们从以下 2 个角度来介绍,这样可以更好地帮助小伙伴理解。
- 类属性和实例属性。
- 类方法和实例方法。
Python 类属性和实例属性
在介绍 Python 类属性和实例属性之前,我们还是先来看一个简单的例子。
class Hero:
title = 'DOTA hero'
def __init__(self, name, type):
self.name = name
self.type = type
def skill(self):
print('放大招啦!')分析:
在这个例子中,title 是一个类属性,而 name 和 type 是实例属性。一般来说,直接在 class 中定义的属性(变量)就是一个 “类属性”,只有在构造函数 __init__() 中使用 self 关键字定义的才是 “实例属性(又叫 “对象属性”)。小伙伴们一定要清楚:一个实例就是一个对象。
示例 1:Python 类属性
class Hero:
title = 'DOTA hero'
h1 = Hero()
h2 = Hero()
print(h1.title)
print(h2.title)
print(Hero.title)运行结果如下。
DOTA hero
DOTA hero
DOTA hero分析:
上面这个 title 是一个类属性,而不是实例属性,因为它是在 class 中直接定义的。从运行结果可以看出,虽然类属性是归于类所有,但是类的所有实例都可以访问到。
想要访问类属性,不建议使用 “实例名.类属性” 的方式,而应该使用 “类名.类属性” 的方式。比如在上面这个例子中,虽然 h1.title 和 h2.title 都可以访问到类属性,但是在实际开发中并不建议使用这种不规范的方式,而是应该使用 Hero.title 这种方式。
示例 2:类属性和实例属性同名
class Hero:
name = 'DOTA英雄'
def __init__(self, name, type):
self.name = name
self.type = type
def skill(self):
print('放大招啦!')
h1 = Hero('船长', '力量型')
print(h1.name)运行结果如下。
船长分析:
上面示例定义了一个名为 name 的类属性,然后在 __init__() 内又定义了一个同名的实例属性。从结果可以看出来,实例属性会覆盖掉类属性。因此大家要记住一点:在实际开发中,不要对类属性和实例属性使用相同的名字。
示例 3:在实例方法中访问类变量
class Hero:
title = 'DOTA hero'
def skill(self):
print(Hero.title)
print(self.__class__.title)
h1 = Hero()
h1.skill()运行结果如下。
DOTA hero
DOTA hero分析:
在实例方法中访问实例变量很简单,直接使用 self.xxx 就可以访问了。不过想要在实例方法中访问类变量,就不是使用 self.xxx 方式,而是使用 “类名.类属性” 或者 “self.__class__.类属性” 的方式。
你可能会有这么一个疑问:大多数情况下我们只会用到实例属性,那么类属性这东西到底有什么用呢?不要着急嘛,我们先来看一个简单的例子。
示例 4:统计实例的个数
class Hero():
count = 0
def __init__(self, name, type):
self.name = name
self.type = type
self.__class__.count += 1
h1 = Hero('船长', '力量型')
h2 = Hero('先知', '智力型')
print(Hero.count)运行结果如下。
2分析:
上面例子定义了一个类属性 count 用于统计实例的个数。构造函数 __init__() 有一个特点,就是在实例化一个对象的同时,__init__() 函数就会自动执行一次,因此我们可以使用类属性 count 来统计实例的个数。此外,self.__class__.count += 1 等价于 Hero.count += 1。
对于类属性和实例属性,我们可以总结出以下 3 点。
- 实例属性属于各个实例所有,互不干扰。
- 类属性属于类所有,所有实例共享一个属性。
- 不要对实例属性和类属性使用相同的名字,否则实例属性会覆盖类属性。
Python 类方法和实例方法
在 Python 中,我们可以使用 @classmethod 装饰器来定义一个类方法。
语法:
@classmethod
def 方法名 (cls):
……说明:
类方法在定义时,需要在定义的上面加上 @classmethod,而且类方法的第 1 个参数是 cls,它指向的是类本身。cls 只是一个参数名,你也可以使用任意变量名,不过为了规范,这里还是建议使用 cls。
提示: 如果小伙伴们不了解装饰器是什么,可以查看:Python 装饰器。
示例 5:类方法 vs 实例方法
class Hero:
count = 0
def __init__(self, name, type):
self.name = name
self.type = type
# 实例化时自动累加
Hero.count += 1
# 定义实例方法
def skill(self):
print(f'{self.name}放大招啦!')
# 定义类方法
@classmethod
def getcount(cls):
print(f'当前英雄总数为:{cls.count}')
h1 = Hero('船长', '力量型')
h1.skill()
Hero.getcount()
h2 = Hero('先知', '智力型')
h2.skill()
Hero.getcount()运行结果如下。
船长放大招啦!
1
先知放大招啦!
2分析:
虽然实例方法可以操作类属性,但我们并不建议这样做。类方法的出现,其实就是用来操作类属性的。请一定要记住:实例方法关联的是实例属性,类方法关联的是类属性。
