首页 新闻 会员 周边 捐助

types.MethodType(func, cls)行为感觉和装饰器@classmethod很像啊

0
[已解决问题] 解决于 2025-08-14 11:24

# 注意外部函数上加了self参数

def func(self, age): #这里需要加参数吗
    print(age)

class cls:
    pass

>>> c = cls
>>> import types
>>> c.printage = types.MethodType(func, c)
>>> c.printage(22)
22
_java_python的主页 _java_python | 小虾三级 | 园豆:1050
提问于:2025-08-14 11:18
< >
分享
最佳答案
0

要的
是因为你给 类对象本身 绑了一个方法,而 MethodType 的第二个参数就是“把这个函数绑定到谁身上”。
因此 外层函数必须多一个 self 形参,否则运行时会少一个位置参数而报错。
关键点:
types.MethodType(func, obj)
把 func 变成 obj 的 bound-method。
obj 会作为 第一个实参 自动传给 func,所以 func 的签名必须留第一个形参(习惯叫 self 或 cls)。

def func(self, age):  # ← 必须多一个 self
    print(age)

c.printage = types.MethodType(func, c)
c.printage(22)        # self=c 已经自动传入,只剩 age=22
若把 func 写成 def func(age):,调用时会报
TypeError: func() takes 1 positional argument but 2 were given。
所以:
给 实例 绑定 → 用 self
给 类 绑定 → 用 cls 或仍叫 self 均可,但必须多一个形参

确实很像
types.MethodType(func, cls) 绑定目标 某个现有函数对象,需要 手动 cls.method(),返回类型 普通函数 → bound-method
@classmethod 类体里定义的方法 直接 cls.method() ,method_descriptor → bound-method,@classmethod 会把函数包装成 classmethod 对象

结论:
MethodType 是 运行时手动绑定;@classmethod 是 声明期语法糖,二者效果类似,但来源和用途不同。

绑定到类

Foo.cls_method = types.MethodType(func, Foo)
Foo.cls_method(10) # <class 'main.Foo'> 10

绑定到实例

f = Foo()
f.inst_method = types.MethodType(func, f)
f.inst_method(20) # <main.Foo object at 0x...> 20
Foo.cls_method(30) # 仍可用

Foo.inst_method(40) # 报错,类上没有这个绑定

_java_python | 小虾三级 |园豆:1050 | 2025-08-14 11:23
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册