|
发表于 2023-1-10 14:00:28
|
显示全部楼层
函数、方法、静态方法、类方法的底层实现原理
- # 函数和方法
- class C:
- def func(self, x):
- return x
- c = C()
- print(c.func)# <bound method C.func of <__main__.C object at 0x000001C5EE4ECFD0>>
- print(C.func)# <function C.func at 0x000001C5EE4D48B0>
- # 函数和方法本质上是一个东西,python在底层分辨函数和方法的原理 -> 描述符
- # 官方文档:
- # class Function:
- # ...
- # def __get__(self, obj, objtype=None):
- # '''Simulate func_descr_get() in Objects/funcobject.c'''
- # if obj is None:
- # return self
- # return MethodType(self, obj)
- # 当定义函数时,其实是实例化了一个叫做Function的类(底层为C语言形式实现),包含一个__get__()方法。
- # 当数定义一个类,再在类里边定义一个函数的时候,就会用到__get__()方法(obj对应instance,objtype对应owner)
- # 先判断第二个参数obj是否为None,是则返回自己,否则返回MethodType
- # 官方代码相当于:
- class D:
- def __get__(self, instance, owner):
- if instance is None:
- print('函数~')
- else:
- print('方法~')
- class C:
- x = D()
- c = C()
- c.x# 方法~
- C.x# 函数~
- # MethodType其实也是一个类,其官方文档:
- # class MethodType:
- # '''Emulate PyMethod_Type in Objects/classobject.c'''
- # def __init__(self, func, obj):
- # self.__func__ = func
- # self.__self__ = obj
- # def __call__(self, *args, **kwargs):
- # func = self.__func__
- # obj = self.__self__
- # return func(obj, *args, **kwargs)
- # 当它的实例化对象被当做函数调用的时候,__call__()魔法方法就会被执行,将传递进去的func和obj两个参数进行整合并且返回,即将传递进来的第一个实参func作为函数名,第二个实参作obj为该函数的第一个参数,整合之后返回
- # 那么上边return MethodType其实就相当于return self(obj)。
- # 静态方法,官方文档:
- # class StaticMethod:
- # '''Emulate PyStaticMethod_Type() in Objects/funcobject.c'''
- # def __init__(self, f):
- # self.f = f
- # def __get__(self, obj, objtype=None):
- # return self.f
- # def __call__(self, *args, **kwargs):
- # return self.f(*args, **kwargs)
- # 只要被StaticMethod装饰器碰过的对象就会变成StaticMethod类的对象,当这个对象被作为函数调用的时候,会直接调用传递进来的函数自身,省去类和对象的中间环节
- # 类方法,官方文档:
- # class ClassMethod:
- # '''Emulate PyClassMethod_Type() in Objects/funcobject.c'''
- # 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)
- # type()如果传入一个对象,那么他会返回该对象所属的类
- class C:
- pass
- c = C()
- print(type(c))# <class '__main__.C'>
- print(type(c) is C)# True
- # 代码hasattr(type(self.f), '__get__')为的是让类方法能够和其他装饰器串联起来使用,如;
- class C:
- @classmethod
- def __doc__(cls):
- return f'i love you -- from class {cls.__name__}'
- c = C()
- print(c.__doc__())# i love you -- from class C
- print(C.__doc__())# i love you -- from class C
- # 调用方法的形式
- class G:
- @classmethod
- @property
- def __doc__(cls):
- return f'A doc for {cls.__name__!r}'
- g = G()
- print(g.__doc__)# A doc for 'G'
- print(G.__doc__)# A doc for 'G'
- # 属性访问的形式
- #将官方文档复制下来,并添加一些print语句
- class MethodType:
- def __init__(self, func, obj):
- self.__func__ = func
- self.__self__ = obj
- def __call__(self, *args, **kwargs):
- func = self.__func__
- obj = self.__self__
- print('小白')
- return func(obj, *args, **kwargs)
- class ClassMethod:
- def __init__(self, f):
- self.f = f
- def __get__(self, obj, cls=None):
- if cls is None:
- print('旺财')
- cls = type(obj)
- if hasattr(type(self.f), '__get__'):
- print(f'来福,type(self.f) -> {type(self.f)}')
- return self.f.__get__(cls, cls)
- return MethodType(self.f, cls)
- class D:
- @ClassMethod# 注意不是classmethod
- @property
- def __doc__(cls):
- return f'i love you. -- from class {cls.__name__}'
- d = D()
- d.__doc__# 来福,type(self.f) -> <class 'property'>
- # 如果多个装饰器串联,那么传入这个参数的类type(self.f)就是property,相当于
- # __doc__是property的实例对象__doc__ = property(__doc__),然后到@ClassMethod,运行到hasattr分支,type(self.f)运行的结果是property类,包含'__get__'方法,然后if里对__get__进行改造
- # self.f.__get__(cls, cls)调用的是propert类里的__get__方法,并将instance对象参数的位置替换成了cls类参数
- class D:
- @ClassMethod# 注意不是classmethod
- def __doc__(cls):
- return f'i love you. -- from class {cls.__name__}'
- d = D()
- d.__doc__# 来福,type(self.f) -> <class 'function'>
- # python万物皆对象,函数也是对象,这里type(self.f)指的是<class 'function'>类
复制代码 |
|