【发布时间】:2020-05-22 13:53:18
【问题描述】:
我正在编写一个元类,除其他外,它还想为它创建的类添加一个方法。让我们暂时忘掉元类,看看简单的方法添加。
为了动态添加实例方法我可以这样做:
class Foo:
def bar(self, x):
print(f"In bar() with {x} and {self}")
def func(self, x):
print(f"In func() with {x} and {self}")
Foo.func = func
之后我可以做:
>>> f = Foo()
>>> f.bar(7)
In bar() with 7 and <__main__.Foo object at 0x7f912a7e57f0>
>>> f.func(7)
In func() with 7 and <__main__.Foo object at 0x7f912a7e57f0>
所以bar 和func 方法似乎功能相同,但有一些明显的区别,例如:
>>> f.bar.__qualname__
'Foo.bar'
>>> f.func.__qualname__
'func'
f.func.__module__ 也可能与 f.bar.__module__ 不同,具体取决于所有内容的定义位置。
我必须在构造 2(如下)中进行哪些更改才能使两个构造的行为完全相同(没有使用 Foo 类的代码可以根据使用的构造改变其行为)?
# Construction 1
class Foo:
def func(self):
pass
# Construction 2
class Foo:
pass
def func(self):
pass
Foo.func = func
我已经创建了一个装饰器,希望能实现一个合理的Construction 2版本,但是我仍然会因为这样的猴子补丁而丢失/破坏什么?
class instance_method_of:
def __init__(self, cls, name=None):
self.cls = cls
self.name = name
def __call__(self, func):
if self.name is not None:
func.__name__ = self.name
func.__qualname__ = f'{self.cls.__qualname__}.{func.__name__}'
func.__module__ = self.cls.__module__
setattr(self.cls, func.__name__, func)
return func
class Foo:
pass
@instance_method_of(Foo)
def func(self):
pass
【问题讨论】:
标签: python python-3.x class methods monkeypatching