Python: как передать аргументы функции __code__ функции?

Следующие работы:

def spam(): print "spam" exec(spam.__code__) 

спам

  • Принудительное именование параметров в Python
  • Передача аргументов C # vs Python
  • Что означает только звезда * в объявлении функции?
  • Оцениваются ли функции при передаче в качестве параметров?
  • Должен ли я добавить конечную запятую после последнего аргумента в вызове функции?
  • В Python, что определяет порядок при итерации через kwargs?
  • Но что, если spam принимает аргументы?

     def spam(eggs): print "spam and", eggs exec(spam.__code__) 

    TypeError: spam () принимает ровно 1 аргумент (задано 0)

    Учитывая, что у меня нет доступа к самой функции, но только к объекту кода, как я могу передать аргументы объекту кода при его выполнении? Возможно ли это с помощью eval?

    Изменить: поскольку большинство читателей склонны не верить в полезность этого, см. Следующий прецедент:

    Я хочу сохранить небольшие функции Python в файл, чтобы их можно было называть, например, с другого компьютера. (Излишне говорить здесь, что этот usecase строго ограничивает возможные функции.) Расселение самого объекта функции не может работать, потому что это только сохраняет имя и модуль, где определена функция. Вместо этого я мог бы __code__ функции. Когда я снова распечатаю его, конечно, ссылка на функцию исчезла, поэтому я не могу назвать функцию. У меня просто нет во время выполнения.

    Еще одна утилита:

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

    У меня есть версия этого запуска для целого модуля вместо функции. Он работает, просматривая время модификации файла, в котором реализован модуль. Но это не вариант, если у меня есть много функций, которые я не хочу разделять в отдельных файлах.

  • В Python, что определяет порядок при итерации через kwargs?
  • Должен ли я добавить конечную запятую после последнего аргумента в вызове функции?
  • Принудительное именование параметров в Python
  • Оцениваются ли функции при передаче в качестве параметров?
  • Что означает только звезда * в объявлении функции?
  • Передача аргументов C # vs Python
  • 6 Solutions collect form web for “Python: как передать аргументы функции __code__ функции?”

    Можете ли вы изменить функцию, чтобы не принимать какие-либо аргументы? Затем переменные просматриваются с локалей / глобальных переменных, где вы можете поставить в exec :

     >>> def spam(): ... print "spam and", eggs ... >>> exec(spam.__code__, {'eggs':'pasta'}) spam and pasta 

    (Почему бы просто не отправить всю функцию в виде строки? Pickle "def spam(eggs): print 'spam and', eggs" и exec строку (после проверки) с другой стороны.)

    Я полностью против этого использования __code__.

    Хотя я любопытный человек, и это то, что кто-то теоретически мог бы сделать:

     code # This is your code object that you want to execute def new_func(eggs): pass new_func.__code__ = code new_func('eggs') 

    Опять же, я никогда не хочу видеть, что это используется, когда-либо. Возможно, вы захотите изучить __import__ если хотите загрузить код во время выполнения.

    Я думаю, что в вашем более крупном приложении, вероятно, есть некоторые соображения по дизайну, которые могут заставить вас не заботиться об этой проблеме, например, возможно, иметь некоторую коллекцию «известных хороших и действительных» функций, распространяемых как модуль, о которых знают исполнители или что-то в этом роде.

    Тем не менее, одно хакерское решение будет:

     >>> def spam(eggs): ... print "spam and %s" % eggs ... ... >>> spam('bacon') spam and bacon >>> def util(): ... pass ... ... >>> util.__code__ = spam.__code__ >>> util('bacon') spam and bacon >>> 

    Объект кода является частью функции, поэтому несколько ответов выше предлагают создать фиктивную функцию и заменить ее __code__ на ваш codeObject . Вот еще один способ, который позволяет избежать и отбрасывать новый __code__ :

     import new newFunction = new.function(codeObject, globals()) 

    (Протестировано в Python 2.7, где spam.__code__ называется spam.func_code .)

    Я не думаю, что вы можете передавать аргументы либо exec либо eval , чтобы они передавались объекту кода.

    Вы можете обратиться к строковой версии exec / eval, например exec("spam(3)") .

    Вы можете создать другой объект кода, который связывает этот аргумент, а затем выполните следующее:

     def spam_with_eggs(): return spam(3) exec(spam_with_eggs.__code__) 

    (Я думал, что вы также можете добиться этого с помощью functools.partial , но не получили его на работу).

    РЕДАКТИРОВАТЬ:

    Прочитав ваши дополнительные объяснения, я подумал о способах восстановить правильную функцию из объекта кода. Этот простой подход работал для меня (в python2.5):

     def bar():pass bar.func_code = spam.func_code bar(3) # yields "spam and 3" 

    Мой метод, я делаю это красивее

     def f(x): print(x, x+1) g = type(f)(f.__code__, globals(), "optional_name") g(3) 
    Python - лучший язык программирования в мире.