Как создать копию функции python - программирование
Подтвердить что ты не робот

Как создать копию функции python

Есть ли возможность создавать реальные копии функций python? Наиболее очевидным выбором был http://docs.python.org/2/library/copy.html, но там я читал:

Он выполняет "копирование" функций и классов (неглубоко и глубоко), посредством возвращение исходного объекта без изменений;

Мне нужна реальная копия, потому что я могу изменить некоторые атрибуты функции.

Update:

Я знаю все возможности, упомянутые в комментариях. Мой вариант использования основан на метапрограмме, где я строю классы из некоторых декларативных спецификаций. Полная информация будет слишком длинной для SO, но в основном у меня есть функция типа

def do_something_usefull(self,arg):
    self.do_work()

Я добавлю этот метод в различные классы. Тестовые классы могут быть полностью не связаны. Использование классов mixin не является вариантом: у меня будет много таких функций и в итоге будет добавлен базовый класс для каждой функции. Моим текущим "обходным решением" было бы обернуть эту функцию в "factory" следующим образом:

def create_do_something():
    def do_something_usefull(self,arg):
        self.do_work()

Таким образом, я всегда получаю новую функцию do_something_useful, но мне нужно обернуть все мои функции следующим образом.

Вы можете доверять мне, что я знаю, что это не "нормальное" программирование OO. Я знаю, как решить что-то подобное "нормально". Но это динамический генератор кода, и я бы хотел, чтобы все было максимально легким и простым. И поскольку функции python - вполне нормальные объекты, я не думаю, что это слишком странно, чтобы спросить, как их скопировать!

4b9b3361

Ответ 1

В Python2:

import types
import functools
def copy_func(f):
    """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
    g = types.FunctionType(f.func_code, f.func_globals, name=f.func_name,
                           argdefs=f.func_defaults,
                           closure=f.func_closure)
    g = functools.update_wrapper(g, f)
    return g

def f(x, y=2):
    return x,y
f.cache = [1,2,3]
g = copy_func(f)

print(f(1))
print(g(1))
print(g.cache)
assert f is not g

дает

(1, 2)
(1, 2)
[1, 2, 3]

В Python3:

import types
import functools

def copy_func(f):
    """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
    g = types.FunctionType(f.__code__, f.__globals__, name=f.__name__,
                           argdefs=f.__defaults__,
                           closure=f.__closure__)
    g = functools.update_wrapper(g, f)
    g.__kwdefaults__ = f.__kwdefaults__
    return g

def f(arg1, arg2, arg3, kwarg1="FOO", *args, kwarg2="BAR", kwarg3="BAZ"):
    return (arg1, arg2, arg3, args, kwarg1, kwarg2, kwarg3)
f.cache = [1,2,3]
g = copy_func(f)

print(f(1,2,3,4,5))
print(g(1,2,3,4,5))
print(g.cache)
assert f is not g

дает

(1, 2, 3, (5,), 4, 'BAR', 'BAZ')
(1, 2, 3, (5,), 4, 'BAR', 'BAZ')
[1, 2, 3]