Python中的static method、class method和instance method

本文介绍了Python中的类属性和实例属性,详细讲解了Instance Method、@classmethod和@staticmethod的区别与使用场景。Instance Method通过self访问实例属性,@classmethod使用cls调用类属性,@staticmethod则与类无直接关联。这三个方法装饰器在代码可维护性方面起到关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类属性和实例属性

在开始整理这两个Decorator之前,先来理一理类和实例之间的关系,那就从属性开始吧,其实属性和方法,大家可以把他们看作是一样的,在python中,一切都是对象,在逻辑上,属性和方法,是一样的。

class Pcl(object):
    class_data = 2

    def __init__(self, data):
        self.data = data

p1 = Pcl(10)
p2 = Pcl(20)
print('--------------------------------')
print('p1.data:', p1.data)
print('p2.data:', p2.data)
# print('Pcl.data: ', Pcl.data)
print('p1.class_data:', p1.class_data)
print('p2.class_data:', p2.class_data)
print('Pcl.class_data:', Pcl.class_data)
p1.class_data = 100
print('--------------------------------')
print('p1.class_data:', p1.class_data)
print('p2.class_data:', p2.class_data)
print('Pcl.class_data:', Pcl.class_data)
Pcl.class_data = 50
print('--------------------------------')
print('p1.class_data:', p1.class_data)
print('p2.class_data:', p2.class_data)
print('Pcl.class_data:', Pcl.class_data)

打印的结果会是

>>>--------------------------------
>>>p1.data: 10
>>>p2.data: 20
>>>p1.class_data: 2
>>>p2.class_data: 2
>>>Pcl.class_data: 2
>>>--------------------------------
>>>p1.class_data: 100
>>>p2.class_data: 2
>>>Pcl.class_data: 2
>>>--------------------------------
>>>p1.class_data: 100
>>>p2.class_data: 50
>>>Pcl.class_data: 50
  • 创建了两个对象,他们的data属性是互不相干的,这个很好理解
  • 类属性class_data对象之间共享同一个
  • 当修改类属性的时候,发生了一些神奇的事情
    • p1.class_data = 100 这一步其实并没有修改那个类属性class_data,而是给p1这个对象创建了一个新的属性,恰好命名也是class_data,所以打印结果就如上所示了
    • 而当我们执行Pcl.class_data = 50 这一句的时候,才真正修改了那个类属性,所以接下来的打印结果,p1因为有了和类属性相同命名的一个属性,所以还是100,p2和Pcl调用的结果,都变成了50

Instance Method

大多数时候,类中的方法都是这种实例方法,随意举个栗子:

class Pcl(object):
    def __init__(self, data):
        self.data = data
    def foo(self):
        print(self.data)

Pcl(10).foo()

打印的结果是

>>>10

简单解释一下,Instance Method的参数第一个必须是self,代表自身对象的引用,实例的任何属性和任何方法,都通过self来调用。

@classmethod

基于Instance Method,当一个方法中,没有通过self来做任何调用,但是调用了类属性(方法),Python建议把这个方法前加上@classmethod,再来举个栗子:

class Pcl(object):
    class_data = 0

    def __init__(self):
        Pcl.class_data += 1

    @classmethod
    def bar(cls):
        print(cls.class_data)

a = Pcl()
b = Pcl()
a.bar()
Pcl.bar()

可以看到,构造了两个对象,class_data 的值向上叠加了2,所以打印结果是:

>>>2
>>>2

对象和类都可以直接调用bar方法,这点和InstanceMethod不同。classmethod的第一个参数,也是Python规定的,必须是cls,代表类本身,cls.class_data相当于Pcl.class_data
为什么说这种情况加上@classmethod是Python建议呢,Python的灵活之处就在这里,不加@classmethod,对程序运行毫无影响,至于调用类属性(方法)有其它办法,如下再来个栗子:

class Pcl(object):
    class_data = 0

    def __init__(self):
        Pcl.class_data += 1

    def bar(self):
        print(self.__class__.class_data)
        print(Pcl.class_data)

a = Pcl()
b = Pcl()
a.bar()

运行结果如下

>>>2
>>>2

看到这里相信大家都明白是怎么回事了。

@staticmethod

至于@staticmethod,一般情况下,如果该方法中,没有引用到这个类的任何其它方法和属性,保持相对独立,Python就建议将该方法设为staticmethod。栗子来了:

switch = True

class Pcl(object):

    @staticmethod
    def check_switch():
        return switch

    def foo(self):
        if self.check_switch():
            print('switch is True')
        else:
            print('switch is False')

Pcl().foo()

可以看到,staticmethod没有任何必须要加上的参数,打印结果自然如下:

>>>switch is True

总结

在我理解,@staticmethod和@classmethod的出现,完全是为了代码的可维护性的,没有他们不会使代码不可运行,但是可以使得代码结构更加科学。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值