Перевод: "Практическое программирование на Python" 07_01_Variable_arguments

Python
Перевод: "Практическое программирование на Python" 07_01_Variable_arguments

содержание | Предыдущий раздел (6.4 Выражения генератора) | Следующий раздел (7.2 Анонимные функции)

7.1 Переменные параметры

В этом разделе описываются переменные параметры. Иногда используются переменные параметры*argsи**kwargsвыражать.

Переменные позиционные параметры (*args)

Если функция принимает произвольное количество (позиционных) аргументов, то мы говорим, что функция использует переменные аргументы. Пример:

def f(x, *args):
    ...

вызов функции:

f(1,2,3,4,5)

Дополнительные аргументы передаются в виде кортежей:

def f(x, *args):
    # x -> 1
    # args -> (2,3,4,5)

Переменные аргументы ключевого слова (**kwargs)

Функция также может принимать любое количество аргументов ключевого слова. Пример:

def f(x, y, **kwargs):
    ...

вызов функции:

f(2, 3, flag=True, mode='fast', header='debug')

Дополнительные аргументы передаются как словари:

def f(x, y, **kwargs):
    # x -> 2
    # y -> 3
    # kwargs -> { 'flag': True, 'mode': 'fast', 'header': 'debug' }

Переменные позиционные аргументы в сочетании с переменными ключевыми словами

Функция может принимать как переменные аргументы, не являющиеся ключевыми словами, так и переменные аргументы, являющиеся ключевыми словами.

def f(*args, **kwargs):
    ...

вызов функции:

f(2, 3, flag=True, mode='fast', header='debug')

Эти параметры делятся на позиционные параметры и параметры ключевых слов.

def f(*args, **kwargs):
    # args = (2, 3)
    # kwargs -> { 'flag': True, 'mode': 'fast', 'header': 'debug' }
    ...

Вышеуказанные функции принимают любое количество позиционных и ключевых аргументов. Используйте при написании оболочек или когда вы хотите передать аргументы другой функции.

Передать кортежи и словари

Кортежи могут быть расширены до аргументов с переменным числом аргументов:

numbers = (2,3,4)
f(1, *numbers)      # Same as f(1,2,3,4)

Словари также могут быть расширены до аргументов ключевых слов:

options = {
    'color' : 'red',
    'delimiter' : ',',
    'width' : 400
}
f(data, **options)
# Same as f(data, color='red', delimiter=',', width=400)

Упражнение

Упражнение 7.1. Простой пример вариативных аргументов

Попробуйте определить следующие функции:

>>> def avg(x,*more):
        return float(x+sum(more))/(1+len(more))

>>> avg(10,11)
10.5
>>> avg(3,4,5)
4.0
>>> avg(1,2,3,4,5,6)
3.5
>>>

Пожалуйста, обрати внимание*moreКак собираются все остальные параметры.​

Упражнение 7.2. Передача кортежей и словарей в качестве аргументов

Предположим, вы читаете данные из файла и получаете кортеж. Например:

>>> data = ('GOOG', 100, 490.1)
>>>

Теперь предположим, что вы хотите создатьStockобъект. Если вы пройдете прямоdata, то это не сработает:

>>> from stock import Stock
>>> s = Stock(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 4 arguments (2 given)
>>>

Эту проблему легко решить, просто используйте*dataВот и все. Попробуйте:

>>> s = Stock(*data)
>>> s
Stock('GOOG', 100, 490.1)
>>>

Если у вас есть словарь, вы можете использовать вместо него**. Пример:

>>> data = { 'name': 'GOOG', 'shares': 100, 'price': 490.1 }
>>> s = Stock(**data)
Stock('GOOG', 100, 490.1)
>>>

Упражнение 7.3. Создание списка экземпляров

существуетreport.pyВ программе мы используем следующий код для создания списка экземпляров:

def read_portfolio(filename):
    '''
    Read a stock portfolio file into a list of dictionaries with keys
    name, shares, and price.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                               select=['name','shares','price'],
                               types=[str,int,float])

    portfolio = [ Stock(d['name'], d['shares'], d['price'])
                  for d in portdicts ]
    return Portfolio(portfolio)

Вместо этого мы можем использоватьStock(**d)для упрощения кода. Пожалуйста, завершите модификацию.

Упражнение 7.4. Передача параметров

fileparse.parse_csv()Функция имеет опции для изменения разделителя файлов и сообщения об ошибках. Может быть, вы захотите предоставить эти параметры вышеread_portfolio()функция. Пожалуйста, завершите модификацию:

def read_portfolio(filename, **opts):
    '''
    Read a stock portfolio file into a list of dictionaries with keys
    name, shares, and price.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                                        select=['name','shares','price'],
                                        types=[str,int,float],
                                        **opts)

    portfolio = [ Stock(**d) for d in portdicts ]
    return Portfolio(portfolio)

После модификации попробуйте прочитать некоторые файлы с ошибками:

>>> import report
>>> port = report.read_portfolio('Data/missing.csv')
Row 4: Couldn't convert ['MSFT', '', '51.23']
Row 4: Reason invalid literal for int() with base 10: ''
Row 7: Couldn't convert ['IBM', '', '70.44']
Row 7: Reason invalid literal for int() with base 10: ''
>>>

Теперь попробуйте скрыть ошибку:

>>> import report
>>> port = report.read_portfolio('Data/missing.csv', silence_errors=True)
>>>

содержание | Предыдущий раздел (6.4 Выражения генератора) | Следующий раздел (7.2 Анонимные функции)

Примечание. Полный перевод см.GitHub.com/co Статья 3 — /PRA…