python中的@classmethod、@staticmethod

python中的@classmethod、@staticmethod

【python】staticmethod与classmethod深度机制解析——要知其所以然

@classmethod、@staticmethod 的使用与实现

普通类函数

写一个类的方法,一般是这样写的:

1
2
3
4
5
6
7
8
9
10
11
# 举例

class A:
def f(self,x):
print(x)

# 调用时
A().f(1)

# 输出
1

方法(函数)的第一个参数是self,self表示把调用这个函数的对象传进去的机制

staticmethod 的使用

而用 staticmethod 的写法是:

1
2
3
4
5
6
7
8
9
10
11
12
class A:
@staticmethod
def f(x):
print(x)

# 调用时
A.f(1)

# 输出
1

#也可以写A().f(1),也是可以使用的

可以看出,和一般的写法很不一样,这种写法更像是通常写函数的样子,只不过把函数放在了class里面而已。

一个定义在class里面的staticmethod,就是一个很普通的函数,使用它的时候,就像使用其它定义在外面的函数一样。

staticmethod decorator,把函数放到了class的命名空间下,让这个函数从属于这个类class了。

调用时,A.f(1),这里的A是class,而不是class的对象object(如果是类的对象,应该写成 A())。这种调用的用法很像在全局定义一个f(x),然后再去调用f(1)

如果想用类的对象来调用函数,依然也是可以用的(不会报错)。就是@staticmethod修饰过的函数,用 A()f(1),也就是用类的对象来调用函数,依然也是可以用的。

staticmethod的意义:

  1. 提供了一个更好的封装,这个函数从属于一个类了;
  2. 不用建立这个类的对象,直接用类就可以调用这个函数;适用于想把功能绑定在类、而不是类的对象上的场景。

classmethod的使用

1
2
3
4
5
6
7
8
9
10
11
12
class A:
@classmethod
def f(cls, x):
print(cls, x)

A.f(1)
# 输出
<class '__main__.A'> 1

A().f(1)
# 输出
<class '__main__.A'> 1

和staticmethod很像,也可以直接在class上调用,或者在class的对象上调用。

classmethod装饰的函数传入的第一个参数是一个类class,但是调用时,不需要传入这个参数(class),和self参数很像。

无论是class或class的object,调用函数时,第一个参数都是class类型。(对于object,会把object的type传进去(对象的类型是class))

staticmethod 的实现

这段没有看懂。

chatgpt解释

chatgpt的回答

classmethod是一种特殊类型的方法,它是针对类对象而不是实例对象进行操作的方法。它的第一个参数永远是类本身,而不是实例,因此可以通过类本身来访问类的属性和方法。下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

@classmethod
def square(cls, side_length):
return cls(side_length, side_length)

square = Rectangle.square(5)
print(square.area()) # 25

在上面的例子中,我们通过使用@classmethod装饰器声明了一个类方法square,它接受一个参数side_length,并返回一个具有相同长和宽的矩形。在这个例子中,我们可以通过调用Rectangle.square(5)来获得一个5x5的正方形。

staticmethod是另一种特殊类型的方法,它不需要任何类或实例对象作为参数,它与类和实例对象没有任何关系。它是类内部的独立函数,可以通过类名直接访问。下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

@staticmethod
def is_valid_dimension(dimension):
if isinstance(dimension, int) and dimension > 0:
return True
return False

print(Rectangle.is_valid_dimension(5)) # True
print(Rectangle.is_valid_dimension(-5)) # False

在上面的例子中,我们通过使用@staticmethod装饰器声明了一个静态方法is_valid_dimension,它接受一个参数dimension,并判断它是否是一个有效的整数。我们可以通过调用Rectangle.is_valid_dimension(5)来获得该方法的结果。