- Оригинальный адрес:Keyword (Named) Arguments in Python: How to Use Them
- Оригинальный автор:Trey Hunner
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:sisibeloved
- Корректор:Starriers,ALVINYEH
Аргументы ключ-значение — это особенность Python, которая может показаться странной любому, кто перешел на Python с другого языка программирования. Когда люди изучают Python, часто требуется много времени, чтобы понять различные особенности параметров «ключ-значение».
При обучении Python мне часто хотелось в нескольких словах объяснить богатство параметров «ключ-значение». Я надеюсь, что эта статья может достичь этого эффекта.
В этой статье я объясню, что такое параметры ключ-значение и почему они используются. Затем я дам еще несколько подробных советов по использованию, которые могут упустить из виду даже опытные программисты на Python, поскольку в последних версиях Python 3 многое изменилось. Если вы уже являетесь опытным программистом на Python, вы можете сразу перейти к концу.
Что такое параметры ключ-значение?
Давайте посмотрим, что такое параметры "ключ-значение" (также называемые именованными параметрами).
Взгляните на следующую функцию Python:
from math import sqrt
def quadratic(a, b, c):
x1 = -b / (2*a)
x2 = sqrt(b**2 - 4*a*c) / (2*a)
return (x1 + x2), (x1 - x2)
Когда мы вызываем эту функцию, у нас есть два разных способа передать эти три параметра.
Мы можем передавать значения в качестве параметров-заполнителей следующим образом:
>>> quadratic(31, 93, 62)
(-1.0, -2.0)
Или как параметр ключ-значение, например:
>>> quadratic(a=31, b=93, c=62)
(-1.0, -2.0)
При передаче значений в качестве заполнителей порядок параметров имеет значение:
>>> quadratic(31, 93, 62)
(-1.0, -2.0)
>>> quadratic(62, 93, 31)
(-0.5, -1.0)
Но добавление имени параметра не имеет значения:
>>> quadratic(a=31, b=93, c=62)
(-1.0, -2.0)
>>> quadratic(c=62, b=93, a=31)
(-1.0, -2.0)
Когда мы используем ключ-значение/именованные параметры, важно имя параметра, а не его позиция:
>>> quadratic(a=31, b=93, c=62)
(-1.0, -2.0)
>>> quadratic(c=31, b=93, a=62)
(-0.5, -1.0)
Таким образом, в отличие от многих других языков программирования, Python знает имена параметров, которые получают функции.
Если мы используем вспомогательную функцию, Python сообщит нам имена трех аргументов:
>>> help(quadratic)
Help on function quadratic in module __main__:
quadratic(a, b, c)
Обратите внимание, что функции можно вызывать, используя сочетание заполнителей и имен:
>>> quadratic(31, 93, c=62)
(-1.0, -2.0)
Это действительно удобно, но было бы понятнее использовать полные параметры-заполнители или полные параметры ключ-значение в функции, подобной той, которую мы написали.
Зачем использовать параметры ключ-значение?
При вызове функций в Python обычно приходится выбирать между аргументами ключ-значение и аргументами-заполнителями. Использование параметров ключ-значение может сделать вызовы функций более явными.
Взгляните на этот код:
def write_gzip_file(output_file, contents):
with GzipFile(None, 'wt', 9, output_file) as gzip_out:
gzip_out.write(contents)
Эта функция получаетoutput_file
файловый объект иcontents
string, затем записывает сжатую gzip-строку в выходной файл.
Следующий код делает то же самое, но заменяет параметры-заполнители параметрами "ключ-значение":
def write_gzip_file(output_file, contents):
with GzipFile(fileobj=output_file, mode='wt', compresslevel=9) as gzip_out:
gzip_out.write(contents)
Вы можете видеть, что вызов этого метода с параметрами ключ-значение может более четко увидеть значение этих трех параметров.
Мы опустили здесь параметр. Первый параметр представляетfilename
, и естьNone
значение по умолчанию для . Здесь нам не нужноfilename
, потому что мы должны передавать только файловый объект или просто имя файла вGzipFile
, не оба.
Есть еще один параметр, который мы можем опустить.
Все еще исходный код, но на этот раз степень сжатия была удалена, а значение по умолчанию9
заменять:
def write_gzip_file(output_file, contents):
with GzipFile(fileobj=output_file, mode='wt') as gzip_out:
gzip_out.write(contents)
Из-за использования именованных параметров мы смогли отбросить два параметра и расположить оставшиеся 2 параметра в разумном порядке (файловый объект более важен, чем режим выборки «wt»).
Когда мы используем параметры ключ-значение:
- Мы можем удалить параметры со значениями по умолчанию
- Мы можем изменить параметры в более читаемом виде
- Легче понять значение параметров, называя их по имени
где посмотреть функции ключ-значение
Вы можете увидеть параметры ключ-значение во многих местах Python.
В Python есть некоторые функции, которые принимают неограниченное количество аргументов-заполнителей. Эти функции иногда могут получать параметры, которые используются для настройки функциональности. Эти параметры должны использовать именованные параметры, чтобы отличать их от бесконечного числа параметров-заполнителей.
Встроенныйprint
необязательные атрибуты функцийsep
,end
,file
иflush
, который может принимать только параметры "ключ-значение":
>>> print('comma', 'separated', 'words', sep=', ')
comma, separated, words
itertools.zip_longest
функциональныйfillvalue
свойство (по умолчаниюNone
), который также принимает только параметры "ключ-значение":
>>> from itertools import zip_longest
>>> list(zip_longest([1, 2], [7, 8, 9], [4, 5], fillvalue=0))
[(1, 7, 4), (2, 8, 5), (0, 9, 0)]
На самом деле, некоторые функции в Python заставляют аргументы быть названными, хотя и в заполнителях.Можетчетко указано.
В Питоне 2,sorted
Функции могут получать параметры в виде заполнителей или ключей-значений:
>>> sorted([4, 1, 8, 2, 7], None, None, True)
[8, 7, 4, 2, 1]
>>> sorted([4, 1, 8, 2, 7], reverse=True)
[8, 7, 4, 2, 1]
Но в Питоне 3sorted
Требовать, чтобы все параметры после итератора были указаны как ключ-значение:
>>> sorted([4, 1, 8, 2, 7], None, True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must use keyword argument for key function
>>> sorted([4, 1, 8, 2, 7], reverse=True)
[8, 7, 4, 2, 1]
В стандартных и сторонних библиотеках распространены не только встроенные функции Python, но и параметры ключ-значение.
сделайте ваши параметры названными
используя*
оператор для сопоставления всех аргументов-заполнителей, а затем в*
Указав необязательные параметры "ключ-значение", вы можете создать функцию, которая принимает любое количество параметров-заполнителей и определенное количество параметров "ключ-значение".
Вот пример:
def product(*numbers, initial=1):
total = initial
for n in numbers:
total *= n
return total
Уведомление: если вы не видели его раньше*
синтаксис,*numbers
войдет во всеproduct
Замещающие параметры функции помещаются вnumbers
Кортеж, на который указывает переменная.
в функции вышеinitial
Параметры должны быть указаны как ключи-значения:
>>> product(4, 4)
16
>>> product(4, 4, initial=1)
16
>>> product(4, 5, 2, initial=3)
120
Уведомлениеinitial
Есть значение по умолчанию. Вы также можете указать с помощью этого синтаксисаобязательныйПараметры "ключ-значение":
def join(*iterables, joiner):
if not iterables:
return
yield from iterables[0]
for iterable in iterables[1:]:
yield joiner
yield from iterable
joiner
Переменная не имеет значения по умолчанию, поэтому ее необходимо указать:
>>> list(join([1, 2, 3], [4, 5], [6, 7], joiner=0))
[1, 2, 3, 0, 4, 5, 0, 6, 7]
>>> list(join([1, 2, 3], [4, 5], [6, 7], joiner='-'))
[1, 2, 3, '-', 4, 5, '-', 6, 7]
>>> list(join([1, 2, 3], [4, 5], [6, 7]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: join() missing 1 required keyword-only argument: 'joiner'
Следует отметить, что этот вид параметра находится в*
Последний синтаксис действителен только в Python 3. В Python 2 нет синтаксиса, требующего именования параметров.
Принимает только параметры "ключ-значение", а не параметры-заполнители.
Что делать, если вы хотите получать только параметры "ключ-значение" без каких-либо параметров-заполнителей?
Если вы хотите получить параметр "ключ-значение" и не планируете получать*
параметры заполнителя, вы можете*
без каких-либо символов после него.
Например, вот модифицированный Djangodjango.shortcuts.render
функция:
def render(request, template_name, context=None, *, content_type=None, status=None, using=None):
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
с Джанго сейчасrender
Реализация функции отличается, эта версия не позволяет вызывать таким образом, чтобы все параметры были указаны как заполнители.render
.context_type
,status
иusing
параметр должен пройти名称
указать.
>>> render(request, '500.html', {'error': error}, status=500)
<HttpResponse status_code=500, "text/html; charset=utf-8">
>>> render(request, '500.html', {'error': error}, 500)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: render() takes from 2 to 3 positional arguments but 4 were given
Как и в случае с неограниченным количеством параметров-заполнителей, эти параметры «ключ-значение» также могут потребоваться. Вот функция с четырьмя обязательными параметрами ключ-значение:
from random import choice, shuffle
UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
LOWERCASE = UPPERCASE.lower()
DIGITS = "0123456789"
ALL = UPPERCASE + LOWERCASE + DIGITS
def random_password(*, upper, lower, digits, length):
chars = [
*(choice(UPPERCASE) for _ in range(upper)),
*(choice(LOWERCASE) for _ in range(lower)),
*(choice(DIGITS) for _ in range(digits)),
*(choice(ALL) for _ in range(length-upper-lower-digits)),
]
shuffle(chars)
return "".join(chars)
Эта функция требует, чтобы все функции были указаны по имени:
>>> random_password(upper=1, lower=1, digits=1, length=8)
'oNA7rYWI'
>>> random_password(upper=1, lower=1, digits=1, length=8)
'bjonpuM6'
>>> random_password(1, 1, 1, 8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: random_password() takes 0 positional arguments but 4 were given
Требование именованных параметров для более явного вызова функций.
Смысл вызова функции такой:
>>> password = random_password(upper=1, lower=1, digits=1, length=8)
Это понятнее, чем называть это так:
>>> password = random_password(1, 1, 1, 8)
Опять же, этот синтаксис работает только в Python 3.
Соответствие параметрам "ключ-значение" с подстановочными знаками
Как написать функцию, которая соответствует любому количеству аргументов ключ-значение?
Например, метод форматирования строки принимает любой аргумент ключ-значение, который вы ему передаете:
>>> "My name is {name} and I like {color}".format(name="Trey", color="purple")
'My name is Trey and I like purple'
Как написать такую функцию?
Python позволяет функциям сопоставлять произвольные входные аргументы ключ-значение, определяя функцию с помощью**
оператор:
def format_attributes(**attributes):
"""Return a string of comma-separated key-value pairs."""
return ", ".join(
f"{param}: {value}"
for param, value in attributes.items()
)
**
оператор позволяетformat_attributes
Функция принимает любое количество аргументов ключ-значение. Входные параметры будут храниться в файле с именемattributes
в словаре.
Вот пример использования нашей функции:
>>> format_attributes(name="Trey", website="http://treyhunner.com", color="purple")
'name: Trey, website: http://treyhunner.com, color: purple'
Вызов функции с подстановочными аргументами ключ-значение
Точно так же, как вы можете определять функции для получения параметров "ключ-значение" с подстановочными знаками, вы также можете передавать параметры "ключ-значение" с подстановочными знаками при вызове функции.
Это означает, что вы можете передавать аргументы ключ-значение функциям на основе элементов словаря.
Здесь мы вручную извлекаем пары ключ/значение из словаря и передаем их в функцию как аргументы ключ-значение:
>>> items = {'name': "Trey", 'website': "http://treyhunner.com", 'color': "purple"}
>>> format_attributes(name=items['name'], website=items['website'], color=items['color'])
'name: Trey, website: http://treyhunner.com, color: purple'
Этот способ жесткого кодирования кода при вызове функции кода требует от нас знания каждого ключа в словаре, который используется при написании кода. Этот подход не работает, когда мы не знаем ключей в словаре.
мы можем пройти**
Оператор разлагает записи в словаре на параметры ключ-значение при вызове функции, чтобы передать подстановочные параметры ключ-значение в функцию:
>>> items = {'name': "Trey", 'website': "http://treyhunner.com", 'color': "purple"}
>>> format_attributes(**items)
'name: Trey, website: http://treyhunner.com, color: purple'
Эта практика передачи подстановочных параметров ключ-значение в функцию и получения подстановочных параметров внутри функции (как мы делали ранее) особенно распространена при использовании наследования классов:
def my_method(self, *args, **kwargs):
print('Do something interesting here')
super().my_method(*args, **kwargs) # 使用传入的参数调用父类的方法
Уведомление: Точно так же мы можем использовать*
оператор для сопоставления и распаковки аргументов-заполнителей.
чувствительность порядка
Начиная с Python 3.6, функции будут поддерживать порядок, в котором передаются аргументы ключ-значение (см.PEP 468). Это означает, что при использовании**
При сопоставлении параметров ключ-значение ключи словаря, используемого для хранения результата, будут в том же порядке, что и переданные параметры.
Итак, после Python 3.6 вы будетебольше никогдаПосмотрите что-то вроде этого:
>>> format_attributes(name="Trey", website="http://treyhunner.com", color="purple")
'website: http://treyhunner.com, color: purple, name: Trey'
Соответственно, в Python 3.6+ аргументы всегда хранятся в том порядке, в котором они были переданы:
>>> format_attributes(name="Trey", website="http://treyhunner.com", color="purple")
'name: Trey, website: http://treyhunner.com, color: purple'
Обобщение аргументов ключ-значение в Python
параметрМесто расположенияПередаваемое сообщение обычно не так хорошо, какназваниеэффективный. Поэтому при вызове функции подумайте о том, чтобы дать своим параметрам имена, если это сделает ее значение более понятным.
При определении новой функции забудьте о том, какой параметр следует указывать в качестве параметра "ключ-значение". использовать*
Оператор указывает эти параметры как параметры ключ-значение.
Помните, что вы можете использовать**
оператор для приема и передачи аргументов ключ-значение с подстановочными знаками.
Важные объекты должны иметь имена, вы можете использовать параметры ключ-значение, чтобы присвоить имена своим объектам!
Нравится мой стиль преподавания?
Хотите узнать больше о Python? Каждую неделю я делюсь своими любимыми ресурсами Python и отвечаю на вопросы, связанные с Python, в чате. Зарегистрируйтесь ниже, и я отвечутвоя проблемаИ научит вас, как сделать ваш код Python более ярким и понятным, более Pythonic.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из ИнтернетаНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллекти другие поля, если вы хотите видеть больше качественных переводов, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.