python classmethod用处_Python 中的 classmethod 和 staticmethod 有什么具体用途?

看了这么多,没看到关于这两个@classmethod 和 @staticmethod 实现原理的,找了一些资料,写一下我现在的理解。

第一部分:classmethod前面的@符号的含义,装饰器

首先这个@符号表示的是语法糖(装饰器),解释可以看看这个Python中语法糖及带参语法糖 - PersistencePythoner - 博客园​www.cnblogs.com

简单来讲就是:

def my_decorator(func):

def wrapper():

func()

pass

return wrapper

# 写法一

@my_decorator

def foo():

pass

# 写法二

foo = my_decorator(foo)

上面的代码,@my_decorator等价于foo = my_decorator(foo),foo是函数句柄

第二部分:什么是描述符

简单来说,如果一个类实现了__ get __ , __ set__, __delete __ 方法的一个或多个,就称这个为描述符。用VS Code打开@staticmethod和@classmethod的代码,可以发现两个类都实现了get方法。而一般情况下,实例化一个对象会触发_init_方法,参数f为Callable类型的对象

取值操作会触发 __get_ 方法

第三部分:@classmethod和@staticmethod的原理

@classmethod和@staticmethod实际上就是描述符和装饰器的组合,为了更好的说明他们的原理,我们可以自己实现一下,以@classmethod为例

class myclassmethod(object):

def __init__(self, method=None):

self.method = method

def __get__(self, instance, cls):

return lambda *args,**ks:self.method(cls,*args,**ks)

# 断点一

class MyClass(object):

@myclassmethod

def func_1(cls,*args,**ks):

print(cls)

print(args)

print(ks)

# 断点二

MyClass.func_1(123,age=199)

用VS Code调试,第一个断点的时候,执行的操作就是装饰器的工作,等价于

MyClass.func_1 = myclasmethod(func_1)

第二个断点,修饰符发挥作用,调用函数,__get__被触发,cls被赋值为拥有者类,也就是其他答案里常常说到的cls默认参数。

最后的输出结果实际上如下:

# print(cls)

(123,) # print(args)

{'age': 199} # print(ks)

参考:location-of-classmethod​stackoverflow.com

class myclassmethod(object):

def __init__(self, method=None):

self.method = method

def __get__(self, instance, cls):

return lambda *args,**ks:self.method(cls,*args,**ks)

class mystaticmethod(object):

def __init__(self,method):

self.method = method

def __get__(self,instance,cls):

return lambda *args,**ks:self.method(*args,**ks)

class MyClass(object):

@myclassmethod

def func_1(cls,*args,**ks):

print(cls)

print(args)

print(ks)

@mystaticmethod

def func_2(age):

print(age)

def func_3(self):

MyClass.func_2(6)

MyClass.func_1(123,age=199)

MyClass.func_2(121213)

obj = MyClass()

obj.func_3()


版权声明:本文为weixin_39768247原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。