python中@classmethod,@staticmethod和@property方法
在python类当中,经常会遇到@classmethod和@staticmethod这两个装饰器,那么到底它们的区别和作用是啥子呢?具体来看下。
@classmethod :默认有一个cls参数,用类或对象都可以调用。
@staticmethod:静态方法,无默认参数,用类和对象都可以调用。
1.@staticmethod:
我们看下代码:
1 2 3 4 5 | class A: def f1(x): print (x) A.f1( 2 ) # 2 类.函数 |
创建一个类,通过类调用函数。
1 2 3 4 5 6 7 | class A: @staticmethod def f1(x): print (x) A.f1( 2 ) # 2 类.静态方法 A().f1( 2 ) # 2 对象.静态方法 这种情况下是可以执行的,如果上述f1没有被staticmethod装饰那么就会报错!!! |
创建一个类,通过类调用函数。同时,因为该方法被staticmethod装饰器装饰了,那么通过对象.方法 也是可以调用的。
所以在类中,通过@staticmethod装饰的函数,可以直接被类调用,也可以被实例化后的对象调用!!!
同时,发现@staticmethod装饰的函数根本不需要传递self这个参数。因为被@staticmethod装饰的函数是直接绑定在类上而不是对象上。
那么再看个示例:
#静态方法 只是名义上归类管理,实际上在静态方法里访问不了类或实例中 的任何属性 class Dog(object): def __init__(self,name): self.name=name @staticmethod #实际上跟类本身已没什么关系,只是名义上是类的方法(与类无关,不能访问类里的任何属性和方法) def eat(self,name): print("%s is eating %s"%(self.name,name)) d=Dog('sb') # d.eat('baozi')#出错 原因是eat需要一个self参数,但调用时却没有传递,没错,因为当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了 #解决办法 #1.调用时主动传递实例本身给eat方法#在eat中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其他变量了 d.eat(d,'baozi') #执行结果 >>>sb is eating baozi
上述代码中,静态方法访问不了类或者实例中的任何属性。如果想要访问,则调用时主动传递实例本身。
2.@classmethod:
1 2 3 4 5 6 7 | class A: @classmethod def f1( cls ,x): print (x) A.f1( 2 ) # 2 类.方法 A().f1( 2 ) # 2 对象.方法 |
创建一个类,通过类调用函数。同时,因为该方法被classmethod装饰器装饰了,那么通过对象.方法 也是可以调用的。但注意,在被装饰方法中,必须传递cls参数!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class B: name = 'bruce' age = 16 @classmethod def f1( cls ,x): print (x) print ( cls .age) print ( cls .name) B().f1( 1 ) # 1 # 16 # bruce |
上述中,说明被classmethod装饰后的方法,通过cls参数,在该方法中,可以调用该类的变量。
1 2 3 4 5 6 7 8 9 10 11 | class C: @classmethod def f1( cls ,x): print (x) cls ().f2() def f2( self ): print ( 'hello world' ) C.f1( 1 ) 或者 C().f1( 1 ) # 1<br># hello world |
上述中,说明被classmethod装饰后的方法,通过cls参数,在该方法中,可以调用该类的其他方法。
所以在类中,通过@classmethod装饰的函数,首先在方法中必须传递第一个参数cls, 该函数可以被类直接调用,也可以被对象调用!!!
同时,因为传递了一个cls,所以可以调用类中的其他变量和方法。
再看下示例:
class Dog(object): name='SB' #类变量 def __init__(self,name): self.name=name @classmethod #类方法只能访问类变量,不能访问实例变量 def eat(self,name): print('%s is eating %s'%(self.name,name)) def talk(self,something): print("%s is talking %s"%(self.name,something)) d=Dog('Lulu') d.eat('Mantou') #执行结果 SB is eating Mantou
类方法只能访问类变量,不能访问实例变量。
3.@property:
将类中的方法变成属性方法,对象调用时直接.方法,不用再加一个‘()’。
示例:
class Rect: def __init__(self,area): self.__area = area @property def area(self): return self.__area rect = Rect(30) #直接通过方法名来访问 area 方法 print("矩形的面积是:",rect.area) # 30
要想实现对area进行修改,可以通过@setter来实现
@area.setter
def area(self, value):
self.__area = value
再次运行如下代码:
rect.area = 90
print("修改后的面积:",rect.area) # 90
要实现对area进行删除,可以通过@deleter实现
@area.deleter def area(self): self.__area = 0
print(rect.area) # 0
总之,关于@property:
1. @property装饰器:修饰的函数,类内调用时函数不用带小括号——getter方法
2. @setter 装饰器:函数名和变量名相同,可以直接修改属性——seter方法。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言