Python 类的属性和方法

对于 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

分析:

虽然实例方法可以操作类属性,但我们并不建议这样做。类方法的出现,其实就是用来操作类属性的。请一定要记住:实例方法关联的是实例属性,类方法关联的是类属性

上一篇: Python 构造函数

下一篇: Python 静态方法

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号