#python
Вопрос:
Предположим , я пишу модуль , который содержит вызываемую функцию normalize()
и другую функцию double()
, у которой также есть параметр с именем normalize
. Изнутри double()
я хочу , чтобы он вызывался normalize()
, но это проблема, потому что параметр имеет то же имя, что и функция.
def normalize(x):
return x * 100
def double(n, normalize = True):
n = n * 2
if (normalize):
n = normalize(n)
return n
Это не работает, потому что вызов normalize(n)
пытается использовать локальную переменную normalize
вместо внешней функции с тем же именем.
Я не хочу переименовывать normalize
функцию или normalize
параметр, потому что оба этих имени имеют смысл. Как я могу заставить это работать?
Одна из возможностей, которую я рассмотрел, состоит в том, чтобы сделать копию normalize
функции, а также использовать __all__
ее так, чтобы копия не экспортировалась.
__all__ = ['normalize', 'double']
def normalize(x):
return x * 100
normalize_copy = normalize
def double(n, normalize = True):
n = n * 2
if (normalize):
n = normalize_copy(n)
return n
Есть ли более простой способ сделать это?
Комментарии:
1. Может
normalize_function = globals()['normalize']
быть ?2. почему бы не изменить имя переменной на
should_normalize
, поскольку это еще более значимо3. Честно говоря, ты слишком много об этом думаешь. У вас есть конфликт имен, поэтому два очевидных решения: (1) использовать пространства имен (т. Е. Импортировать модуль, содержащий функцию, или поместить его в класс) или (2) переименовать один из них ( 1 по
should_normalize
предложению @JoranBeasley).4. @Selcuk или даже, используя a
types.SimpleNamespace
.5. Смотрите Дзен Python :
Simple is better than complex
,[...] practicality beats purity
, иNamespaces are one honking great idea -- let's do more of those!
Ответ №1:
Вот своего рода глупый обходной путь, но вы могли бы сделать это; он повторно normalize()
связывает функцию с новым именем в списке параметров.
def double(n, norm_func=normalize, normalize=True):
n = n * 2
if normalize:
n = norm_func(n)
return n
Комментарии:
1. Это действительно круто, так как оно полностью инкапсулировано.
Ответ №2:
Я настоятельно рекомендую вам изменить имя аргумента на should_normalize
, так как это еще более значимо, чем normalize
в данном контексте.
Если по какой-либо причине это не является для вас хорошим решением, я поддержу предложение из комментариев использовать инкапсуляцию пространства имен:
import types
def normalize(x):
return x * 100
NS = types.SimpleNamespace(normalize=normalize)
def double(n,normalize):
n = n * 2
if normalize:
n = NS.normalize(n)
return n
Ответ №3:
Вы можете достичь этого, если захотите немного изменить API, как показано ниже. Аргумент normalize
теперь содержит значение функции, а не логическое значение.
def normalize(x):
return x * 100
def double(n, normalize = None):
n = n * 2
if (normalize):
n = normalize(n)
return n
print(double(10, normalize))
@tdelaney, мы можем инвертировать normalize
аргумент, как показано ниже, если действие по умолчанию должно быть всегда normalizing
.
def normalize(x):
return x * 100
def double(n, normalize = normalize):
n = n * 2
if (normalize):
n = normalize(n)
return n
print(double(10))
Комментарии:
1. Недостатком является то, что пользователи API должны будут знать, как вызывать функцию normalize.
Ответ №4:
Для меня ваше второе решение является самым простым, но на самом деле вам не нужно использовать __all__
, просто подчеркивание.
_normalize = normalize # For use in "double()", which has a param "normalize"
def double(n, normalize=True):
n = n * 2
if normalize:
n = _normalize(n)
return n
Я бы также добавил комментарий, чтобы указать, почему там есть эта строка.
Комментарии:
1. Мне это нравится-это просто и делает свою работу.
Ответ №5:
Ответ заключается в изменении имени параметра. Вы можете напрямую запросить глобальную область для объекта
def normalize(x):
return x * 100
def double(n, normalize = True):
n = n * 2
if (normalize):
n = globals()["normalize"](n)
return n
Но тогда люди будут удивляться, почему вы просто не изменили название параметра.