Ответ 1
Вот довольно хакерское решение:
def f(a, c=None, b=None):
if (b == None):
print("do not do that")
else:
print("good")
где intput: f(1, b=2)
печатает good
а f(1, 2)
печатает do not do that
Рассмотрим функцию с сигнатурой f(a, b)
. В будущем я хотел бы изменить сигнатуру на f(a, *, b)
, запретив передачу b в качестве позиционного аргумента. Чтобы уменьшить влияние изменений, я хочу сначала отказаться от позиционирования b, предупреждая пользователей, которые это делают.
Для этого я хотел бы написать что-то вроде:
def f(a, b):
frame = inspect.currentframe()
if b in frame.specified_as_positional:
print('Do not do that')
else:
print('Good')
Результатом будет то, что
>>> f(1, 2)
'Do not do that'
>>> f(1, b=2)
'Good'
inspect.getargvalues(frame)
не представляется достаточным. Объект ArgInfo просто обеспечивает
>>> f(1,b=2)
ArgInfo(args=['a', 'b'], varargs=None, keywords=None, locals={'a': 1, 'b': 2})
Возможна ли такая проверка даже в Python? Концептуально интерпретатору не требуется запоминать, был ли аргумент задан позиционно или как ключевое слово.
Было бы неплохо иметь поддержку Python 2, но это не обязательно.
Вот довольно хакерское решение:
def f(a, c=None, b=None):
if (b == None):
print("do not do that")
else:
print("good")
где intput: f(1, b=2)
печатает good
а f(1, 2)
печатает do not do that
Вы можете использовать оболочку, чтобы добавить дополнительный шаг между пользователем и функцией. На этом этапе вы можете проверить аргументы, прежде чем имена имеют значение. Обратите внимание, что это зависит от того факта, что b
не имеет значения по умолчанию и всегда должно быть задано как arg.
functools.wraps
используется для того, чтобы оформленная функция во многом напоминала оригинал.
import functools
import warnings
def deprecate_positional(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
if 'b' not in kwargs:
warnings.warn(
'b will soon be keyword-only',
DeprecationWarning,
stacklevel=2
)
return fun(*args, **kwargs)
return wrapper
@deprecate_positional
def f(a, b):
return a + b
>>> f(1, b=2)
3
>>> f(1, 2)
Warning (from warnings module):
File "C:/Users/nwerth/Desktop/deprecate_positional.py", line 36
print(f(1, 2))
DeprecationWarning: b will soon be keyword-only
3