Por posição ou por nome
Os argumentos podem ser passados por posição (casados com os parâmetros em ordem) ou por nome (quantity=200). Os nomes deixam uma chamada legível quando a função tem várias entradas do mesmo tipo e permitem passar os argumentos em qualquer ordem. Os posicionais vêm primeiro; depois que você usa um nome, os demais também precisam ter nome.
def pnl(entry, exit_price, quantity):
return (exit_price - entry) * quantity
print(pnl(184.0, 185.5, 200)) # 300.0
print(pnl(quantity=200, entry=184.0, exit_price=185.5)) # 300.0Valores padrão tornam os parâmetros opcionais
Escreva name=value na linha def e quem chama pode omitir esse argumento; o valor padrão é usado. Os parâmetros com valor padrão vêm depois dos que não têm. Valores padrão servem para configurações quase sempre iguais, como uma taxa ou um mínimo, e qualquer um deles ainda pode ser substituído pelo nome.
# Parameters with a default are optional
def fee(notional, rate=0.001, minimum=1.0):
return max(minimum, notional * rate)
print(fee(36850.0)) # 36.85
print(fee(36850.0, rate=0.0005)) # 18.425
print(fee(100.0, minimum=0.5)) # 0.5Qualquer número de argumentos: *args
Um parâmetro escrito *prices reúne todos os argumentos posicionais extras em uma tupla, então average(1, 2, 3) e average(1, 2, 3, 4, 5) funcionam. O inverso acontece na chamada: average(*quotes) desempacota uma lista em argumentos separados.
# *prices collects the extra arguments into a tuple
def average(*prices):
return sum(prices) / len(prices)
print(average(184.0, 185.0, 186.0)) # 185.0
quotes = [184.0, 185.0]
print(average(*quotes)) # 184.5Quaisquer opções nomeadas: **options
Da mesma forma, **options reúne os argumentos nomeados extras em um dicionário de nomes e valores (os dicionários terão em breve seu próprio tópico). Serve para funções que aceitam extras opcionais, como as configurações de uma ordem. sorted(options) dá os nomes em ordem alfabética, então a saída é previsível.
# **options collects extra named arguments into a dictionary
def describe(symbol, **options):
text = symbol
for name in sorted(options):
text += f" {name}={options[name]}"
return text
print(describe("AAPL", tif="day", limit=184.5)) # AAPL limit=184.5 tif=dayA armadilha do valor padrão mutável
Um valor padrão é criado uma só vez, quando a função é definida, e não a cada chamada. Com um número ou texto isso é inofensivo. Com uma lista, toda chamada que usa o padrão compartilha e altera a mesma lista. A correção usual é usar None como padrão e criar uma lista nova dentro da função.
# A default list is created once and shared by every call
def add_fill(fill, fills=[]):
fills.append(fill)
return fills
print(add_fill(100)) # [100]
print(add_fill(200)) # [100, 200] <- surprise: the same list
# The fix: default to None and build a new list inside
def add_fill_fixed(fill, fills=None):
if fills is None:
fills = []
fills.append(fill)
return fills
print(add_fill_fixed(100)) # [100]
print(add_fill_fixed(200)) # [200]- Use nomes nas chamadas com várias entradas do mesmo tipo.
- Valores padrão para configurações quase sempre iguais; nunca uma lista ou dicionário.
*argspara qualquer número de valores,**optionspara extras nomeados.
A seguir: escopo e closures, para ver quais nomes uma função enxerga e como ela pode lembrar valores.
Lab: o que é avaliado
- Tornar a quantidade e o lado opcionais com
position_pnl25 pts - Aceitar qualquer número de preços com
average25 pts - Receber opções de ordem nomeadas com
describe_order25 pts - Evitar a armadilha da lista compartilhada com
add_fill25 pts