python笔记 类方法

31 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

0 环境

  • 编辑器:pycharm或者vscode
  • 系统版本:windows10
  • python版本:3.9.6

1 参考文档

参考文档

2 回顾类方法的使用

如下代码: 关注点:绑定@classmethod,并且入参加上个cls,不管类还是实例调用都一样。

class I:
    @classmethod
    def class_print(cls):
        print("id -->", id(cls))
        print("class method")
       
i = I()
i.class_print()
I.class_print()

image.png

3 自实现@classmethod

这里用到了,MethodType,先了解下它,如下代码: MethodType就像是一个红娘,把单独分开的类和单独的方法,连接在一块,首先我们先定义show,带有self和val,在定义了一个类,这两个现在是相互独立的,现在就要把两个毫不相干的类和方法,把它们连接在一起,类名.方法名 = MethodType(方法, 类),连接的规则就是这样的。当我们两个类实例分别调用这个方法时,最后分别输出age的属性,但是结果为啥是一样的,明明连个入参是1、2,这里注意,后面的实例调用会覆盖之前的实例调用的值的。

from types import MethodType
#创建一个方法
def show(self, val):
    self.age = val
#创建一个类 
class A:
    pass

A.show = MethodType(show, A)
a = A()
a1 = A()
a.show(1)
a1.show(2)
print(a.age, a1.age)

image.png

现在再看如下的代码: 是不是和之前的自定义的静态方法类似呢,也要是初始话f的,这里无非是在__get__先做了判断,当然我们也可以不用这个判断,只是为了测试MethodType,可以先忽略了,MethodType相当于将f连接到了F类里,然后在返回,这样我的类或它的实例直接调用直接就可以得到我们想要的结果了。

from types import MethodType
class Classmethod:

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

    def __get__(self, obj, cls=None):
        if cls is None:
            cls = type(obj)
        if hasattr(type(self.f), '__get__'):
            return self.f.__get__(cls, cls)
        return MethodType(self.f, cls)

class F:
    @Classmethod
    def f(cls, x):
        return cls.__name__, x

print(F.f(10))
print(F().f(10))

image.png

4 总结

想实现类方法的功能,和实现自定义的静态方法类似,无非是在它的基础上,多了个绑定和cls,关键点:f(方法)、cls、前面这两个通过MethodType来链接,然后__get__返回,这里的MethodType还可以使用partial来替代。