python - variable - ¿Cuál es el propósito del asterisco desnudo en los argumentos de función?
the meaning of the keyword parameter is determined by python (2)
Para los que vienen o usan ruby
Por debajo de la expresión en Python
def f(a, b, *, c=1, d=2, e=3):
es parecido a
def f(a,b, options={})
c = options[:c] || 1
d = options[:d] || 2
e = options[:e] || 3
end
en rubí.
Como Python es explícito, es mejor que el lenguaje implícito , requiere un operador *
(splat) en los parámetros.
PD: Nunca usé python, si me equivoco por favor corríjame.
He visto esta pregunta SO (esto no es un duplicado): Python bare asterisk en el argumento de la función
En python-3.x puede agregar un *
simple a los argumentos de la función, esto significa que (cita de los docs ):
Los parámetros después de "*" o "* identificador" son parámetros de palabra clave y solo se pueden pasar los argumentos de palabra clave usados.
Ok, entonces, he definido una función:
>>> def f(a, b, *, c=1, d=2, e=3):
... print(''Hello, world!'')
...
Puedo pasar los valores de las variables c
, d
y e
solo especificando palabras clave:
>>> f(1, 2, 10, 20, 30)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 5 were given
>>> f(1, 2, c=10, d=20, e=30)
Hello, world!
Las preguntas son:
- ¿Cuál es la motivación para este tipo de restricción / sintaxis de azúcar?
- ¿Qué casos de uso cubre?
- ¿Se usa realmente en bibliotecas de terceros que cambiaron a python3?
Algunos ejemplos del "mundo real" ayudarían mucho. Gracias por adelantado.
El PEP 3102 explica el razonamiento con bastante claridad: el punto es permitir que las funciones acepten varias "opciones" que son esencialmente de naturaleza ortogonal. Especificarlos de manera posicional es incómodo, tanto en el lado de definición como en el de llamada, ya que no tienen ninguna "prioridad" obvia que se traduciría en un orden de posición.
Hay muchos ejemplos de funciones que se beneficiarían de esto en varias bibliotecas. Por ejemplo, la firma de llamada de pandas.read_csv
es:
def parser_f(filepath_or_buffer,
sep=sep,
dialect=None,
compression=None,
doublequote=True,
escapechar=None,
quotechar=''"'',
quoting=csv.QUOTE_MINIMAL,
skipinitialspace=False,
lineterminator=None,
header=''infer'',
index_col=None,
names=None,
prefix=None,
skiprows=None,
skipfooter=None,
skip_footer=0,
na_values=None,
na_fvalues=None,
true_values=None,
false_values=None,
delimiter=None,
converters=None,
dtype=None,
usecols=None,
engine=''c'',
delim_whitespace=False,
as_recarray=False,
na_filter=True,
compact_ints=False,
use_unsigned=False,
low_memory=_c_parser_defaults[''low_memory''],
buffer_lines=None,
warn_bad_lines=True,
error_bad_lines=True,
keep_default_na=True,
thousands=None,
comment=None,
decimal=b''.'',
parse_dates=False,
keep_date_col=False,
dayfirst=False,
date_parser=None,
memory_map=False,
nrows=None,
iterator=False,
chunksize=None,
verbose=False,
encoding=None,
squeeze=False,
mangle_dupe_cols=True,
tupleize_cols=False,
infer_datetime_format=False):
A excepción de la ruta de archivo, la mayoría de estas son opciones ortogonales que especifican diferentes aspectos de cómo se analizará un archivo CSV. No hay ninguna razón particular por la que se aprobarían en un orden particular. Te volverías loco haciendo un seguimiento de cualquier orden posicional para estos. Tiene más sentido pasarlos como palabras clave.
Ahora, puedes ver que los pandas no los definen realmente como argumentos de palabra clave, probablemente para mantener la compatibilidad con Python 2. Me imagino que muchas bibliotecas se han abstenido de usar la sintaxis por la misma razón. No sé de antemano qué bibliotecas (si las hay) han comenzado a usarlo.