Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将函数动态插入Python类_Python_Python 3.x_Class_Methods_Monkeypatching - Fatal编程技术网

将函数动态插入Python类

将函数动态插入Python类,python,python-3.x,class,methods,monkeypatching,Python,Python 3.x,Class,Methods,Monkeypatching,我正在编写一个元类,其中之一就是希望向它创建的类添加一个方法。让我们暂时忘掉元类,只看简单的方法添加 为了动态添加实例方法,我可以执行以下操作: 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

我正在编写一个元类,其中之一就是希望向它创建的类添加一个方法。让我们暂时忘掉元类,只看简单的方法添加

为了动态添加实例方法,我可以执行以下操作:

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>
之后我可以做:

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>
f.func.\uuuuu模块\uuuuu
也可能与
f.bar.\uuuuu模块\uuuuu
不同,具体取决于所有内容的定义位置

为了使两个构造的行为完全相同(使用
Foo
类的任何代码都不能根据所使用的构造更改其行为),我必须在构造2中(以下)更改什么

我已经创建了一个装饰器,希望它能够实现一个合理的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

它似乎涵盖了一切!虽然我会选择一个函数装饰器,比如:

from pathlib import Path

def patch(f):
    cls = next(iter(f.__annotations__.values()))
    name = f.__defaults__[0]
    f.__qualname__ = f"{cls.__name__}.{f.__name__}"
    f.__module__ = cls.__module__
    if name is None:
        setattr(cls,f.__name__,f)
    else:
        f.__qualname__ = f"{cls.__name__}.{name}"
        setattr(cls,name,f)
    return f

@patch
def new(self:Path, name:str=None):
    "new"
    return list(self.iterdir())

path = Path()
path.new()
大部分改编自fastai版本