que propias procedimientos opcionales metodos lista funciones argumentos python python-3.x identifier python-2.x keyword-argument

propias - python class kwargs



¿Es seguro usar una función que acepta argumentos de palabra clave kwargs que no son identificadores? (1)

En primer lugar: la convención de llamadas **{...} con nombres no identificadores solo funciona si la función llamada tiene un argumento **kw para recibirlos, ya que tampoco puede definir argumentos explícitos de palabras clave que no sean identificadores válidos.

Yo diría que la gramática keyword_arguments solo se aplica al analizador sintáctico del código fuente , y nunca puede verse como una restricción funcional sobre el contenido del **expression resultado de la **expression . La siguiente descripción funcional no restringe explícitamente las claves del diccionario, ni tampoco la documentación de definición de funciones .

En cambio, dado que la gramática permite una expression , y la especificación funcional establece que eso debería resolverse en una asignación cuyos contenidos se tratan como argumentos adicionales de palabra clave , está claro (para mí) que no hay restricciones para las claves en absoluto , más allá de los normales aplicables a los diccionarios de Python (las claves deben ser inmutables). Puede pasar claves tuplas o numéricas para todos los cuidados de Python. La especificación funcional establece cómo se tratan los contenidos, no que los contenidos deben ajustarse a un formato determinado.

Por lo tanto, en mi opinión, la especificación funcional tendría que restringir explícitamente las claves en el diccionario **expression para no permitir lo que está haciendo, porque la gramática ciertamente no lo hace. Cambiar eso sería un gran cambio incompatible con versiones anteriores, y es probable que nunca se agregue.

Tenga en cuenta que aunque la especificación no menciona ninguna restricción en las teclas del diccionario, CPython lo hace:

>>> def f(*args, **kw): print args, kw ... >>> f(**{1: 2}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() keywords must be strings

Esta es una restricción hecha por el intérprete de python al invocar objetos de código (funciones definidas por el usuario). La razón por la cual se explica en el código fuente justo después de la parte que plantea la excepción anterior:

/* Speed hack: do raw pointer compares. As names are normally interned this should almost always hit. */

Al restringir las palabras clave a cadenas, es posible una optimización de la velocidad.

En Python, ¿es seguro dar argumentos de palabras clave que no sean identificadores de Python a una función? Aquí hay un ejemplo:

>>> ''{x-y}''.format(**{''x-y'': 3}) # The keyword argument is *not* a valid Python identifier ''3'' >>> ''{x-y}''.format(x-y=3) File "<ipython-input-12-722afdf7cfa3>", line 1 SyntaxError: keyword can''t be an expression

Lo estoy preguntando porque me resulta más conveniente formatear con nombres que contienen un guion (porque los valores corresponden al argumento de la línea de comandos con guiones en su nombre). Pero, ¿es confiable este comportamiento (es decir, puede variar según la versión de Python)?

No estoy seguro de que el uso de no identificadores como argumentos de palabras clave sea oficialmente compatible: de hecho, la documentación dice:

Si la expresión de sintaxis ** aparece en la llamada de función, la expresión debe evaluarse como una asignación, cuyo contenido se trata como argumentos adicionales de palabras clave.

... donde "argumentos de palabra clave" se definen como tener un nombre que es un identificador :

keyword_arguments :: = keyword_item ("," keyword_item) *

keyword_item :: = identificador "=" expresión

donde los identificadores están restringidos en qué caracteres pueden usar (está prohibido, por ejemplo):

identificador :: = (carta | "_") (letra | dígito | "_") *

Entonces, la documentación indica que la asignación asignada a ** en una llamada a función solo debe contener identificadores válidos como claves, pero CPython 2.7 acepta claves más generales (para format() y funciones con un argumento ** , que no ponen valores en variables). ¿Es esta una característica confiable?