Ничего необычного способа (из методов, которые я публикую здесь, это, вероятно, лучший способ сделать это):
module.py:
def initialize():
print('initialize')
def do_the_thing(args):
print('doing things',args)
def function(args):
_function(args)
def firsttime(args):
global _function
initialize()
do_the_thing(args)
_function=do_the_thing
_function=firsttime
Идея проста: вы просто добавляете слой косвенности.function
всегда вызывает _function
, но _function
указывает сначала на firsttime
, а затем навсегда на do_the_thing
.
test.py:
from module import function
function(1)
function([2,3])
Запуск test.py приводит к
initialize
('doing things', 1)
('doing things', [2, 3])
Моей первой мыслью было использование генератора, но, как указывает Триптих, невозможно передать аргументы функции, если вы используете генератор.Итак ...
вот способ использования сопрограммы (который, в отличие от генератора, позволяет отправлять аргументы - и получать значения от - сопрограммы):
module.py:
def coroutine(func):
# http://www.dabeaz.com/coroutines/index.html
def start(*args,**kwargs):
cr = func(*args,**kwargs)
cr.next()
return cr
return start
def initialize():
print('initialize')
def do_the_thing(*args, **kwargs):
print('doing things', args, kwargs)
return ('result', args)
@coroutine
def _function():
args, kwargs = (yield)
initialize()
while True:
args, kwargs = (yield do_the_thing(*args, **kwargs))
_function = _function().send
def function(*args, **kwargs):
# This is purely to overcome the limitation that send can only accept 1 argument
return _function((args,kwargs))
Запуск
print(function(1, x = 2))
print(function([2, 3]))
Выход
initialize
('doing things', (1,), {'x': 2})
('result', (1,))
('doing things', ([2, 3],), {})
('result', ([2, 3],))