python classmethod 继承_@classmethod的使用

本文探讨了Python中的@classmethod装饰器,对比了它与@staticmethod的区别。通过fruit和apple类的例子,阐述了@classmethod如何允许类函数访问类变量并在继承时自动指向子类,从而简化代码并实现更优雅的设计。文章强调了在需要对对象创建进行特殊处理或在有继承关系时,使用@classmethod的优势。

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

在有了@staticmethod的使用理解后,再看@classmethod的使用,就更加清晰了。@classmethod一样,也是应用于类中的函数,将这些函数转换为类函数。

需要清楚:装饰器也是一个函数!内置的装饰器,当然也是内置函数了。

我们定义的python类,内部可以有三种成员函数,一般的都是对象函数,没有任何装饰器修饰的都是这类。用@staticmethod装饰的,是静态函数,静态类的成员函数,只能通过明确的类名来访问类中的变量,使用方面受到限制。用@classmethod装饰的,类函数,使用比静态函数要广一些,因为类函数的第1个参数默认为当前类名。

由于类函数可以访问类变量(class variable),使得类函数常常用来提供创建对象不同的接口。

class fruit():

num = 0

def __init__(self, price):

self.price = price

self.count()

@classmethod

def count(cls):

cls.num += 1

@classmethod

def float_price(cls, price):

if not isinstance(price, float):

try:

price = float(price)

except: raise

return cls(price)

f1 = fruit(1.234)

print(fruit.num)

f2 = fruit.float_price(1.2345)

print(fruit.num)

f3 = fruit.float_price('1.234')

print(fruit.num)

f4 = fruit.float_price('abcde')

一个很简单的fruit类,只是包含了两个classmethod函数。

一般情况下,我们实用f1 = fruit(1.234)的方式创建对象。如果我们需要对入参进行一些限制和判断,甚至转换,就可以考虑实用float_price这个类函数。请看f2和f3的创建,确定参数没有问题之后,再调用cls(price)创建对象。

cls是classmethod类函数的第1个默认参数,cls这个名字,与self一样,只是一个约定俗称的写法,这样写,大家都能看明白。而cls(price),就跟fruit(price)一样,内部调用__init__创建对象。

count函数也是类函数,用于累加类变量num,用来技术fruit对象的个数。上面代码执行效果如下:

$ python3 classmethod.py

1

2

3

Traceback (most recent call last):

File "classmethod.py", line 30, in

f4 = fruit.float_price('abcde')

File "classmethod.py", line 19, in float_price

price = float(price)

ValueError: could not convert string to float: 'abcde'

继续聊count类函数,为什么这个简单的记录对象个数的函数,要用@classmethod来修饰呢?因为,在有继承关系的时候,可以让你少些很多代码,整体结构也更优雅。

class fruit():

num = 0

def __init__(self, price):

self.price = price

self.count()

@classmethod

def count(cls):

cls.num += 1

@classmethod

def float_price(cls, price):

if not isinstance(price, float):

try:

price = float(price)

except: raise

return cls(price)

class apple(fruit):

@classmethod

def int_price(cls, price):

if not isinstance(price, int):

try:

price = int(price)

except: raise

return cls(price)

f1 = apple(12)

print(apple.num)

f2 = apple.float_price(1.2345)

print(apple.num)

f3 = apple.int_price('12')

print(apple.num)

f4 = apple.int_price('abcde')

现在我们来创建apple对象,apple类继承fruit,只是增加了一个int_price类函数。同样,我们尝试创建4个apple对象,预期输入'abcde'的时候,创建会失败,以上代码执行结果如下:

t$ python3 classmethod.py

1

2

3

Traceback (most recent call last):

File "classmethod.py", line 41, in

f4 = apple.int_price('abcde')

File "classmethod.py", line 30, in int_price

price = int(price)

ValueError: invalid literal for int() with base 10: 'abcde'

结果符合我们的预期,apple对象的计数也在正常进行,这就要归功于fruit类中定义的那个count class method。因为classmethod函数可以使用第1个参数,cls,来访问类变量,因此继承之后,cls自动就指向了继承后的类。注意,这是@classmethod与@staticmethod不一样的地方。也因为这个特性,决定了classmethod的应用会比staticmethod要广。

从@classmethod这个装饰器的名字上,我们也能感觉到,这类函数是服务于类的,它可以访问类变量,因此在继承之后,依然可以保持对继承后的类的支持。

-- EOF --

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值