TypeError: no todos los argumentos se convierten durante el formateo de cadenas en Python

192

Se supone que el programa toma dos nombres, y si tienen la misma longitud, debe verificar si son la misma palabra. Si es la misma palabra, imprimirá "Los nombres son iguales" . Si tienen la misma longitud pero con letras diferentes, imprimirá "Los nombres son diferentes pero tienen la misma longitud" . La parte con la que tengo un problema está en las 4 líneas inferiores.

#!/usr/bin/env python
# Enter your code for "What's In (The Length Of) A Name?" here.
name1 = input("Enter name 1: ")
name2 = input("Enter name 2: ")
len(name1)
len(name2)
if len(name1) == len(name2):
    if name1 == name2:
        print ("The names are the same")
    else:
        print ("The names are different, but are the same length")
    if len(name1) > len(name2):
        print ("'{0}' is longer than '{1}'"% name1, name2)
    elif len(name1) < len(name2):
        print ("'{0}'is longer than '{1}'"% name2, name1)

Cuando ejecuto este código, muestra:

Traceback (most recent call last):
  File "program.py", line 13, in <module>
    print ("'{0}' is longer than '{1}'"% name1, name2)
TypeError: not all arguments converted during string formatting

Cualquier sugerencia es altamente apreciada.

usuario2652300
fuente

Respuestas:

210

Estás mezclando diferentes funciones de formato.

El %formato antiguo usa %códigos para formatear:

'It will cost $%d dollars.' % 95

El {}formato de nuevo estilo usa {}códigos y el .formatmétodo

'It will cost ${0} dollars.'.format(95)

Tenga en cuenta que con el formato de estilo antiguo, debe especificar varios argumentos utilizando una tupla:

'%d days and %d nights' % (40, 40)

En su caso, dado que está utilizando {}especificadores de formato, use .format:

"'{0}' is longer than '{1}'".format(name1, name2)
nneonneo
fuente
17
en python 3.6:f"'It will cost ${your_variable} dollars."
JinSnow
51

El error está en el formato de su cadena.

La forma correcta de usar el formato de cadena tradicional usando el operador '%' es usar una cadena de formato de estilo printf (documentación de Python para esto aquí: http://docs.python.org/2/library/string.html#format- sintaxis de cadena ):

"'%s' is longer than '%s'" % (name1, name2)

Sin embargo, el operador '%' probablemente quedará obsoleto en el futuro . La nueva forma de hacer las cosas PEP 3101 es así:

"'{0}' is longer than '{1}'".format(name1, name2)
leonh
fuente
9
scnr: "probablemente quedará obsoleto en el futuro" no sucedió hasta ahora (Python 3.5). La antigua sintaxis '%' no estaba en desuso en 3.1 y solo en el módulo de registro{} 3.2 aprendió a formatear con el nuevo estilo . Y de repente 3.5 trae PEP 461: %formateo para bytes . Esto me hace pensar en los %restos durante mucho tiempo por venir.
cfi
77
%Es más conciso. Me alegro de que se quede con nosotros.
Lenar Hoyt
3
Estoy de acuerdo. % es más conciso y eliminar no agregaría ningún beneficio al idioma.
chevydog
@LenarHoyt ¿Cómo te sientes acerca de las cuerdas f? No puedo imaginar que sea "'%s' is longer than '%s'" % (name1, name2)más conciso quef"'{name1}' is longer than '{name2}'"
Mark Moretto
44

Para mí, este error fue causado cuando intentaba pasar una tupla al método de formato de cadena.

Encontré la solución de esta pregunta / respuesta

Copiar y pegar la respuesta correcta desde el enlace (NO ES MI TRABAJO) :

>>> thetuple = (1, 2, 3)
>>> print "this is a tuple: %s" % (thetuple,)
this is a tuple: (1, 2, 3)

Hacer una tupla singleton con la tupla de interés como único elemento, es decir, la parte (thetuple,), es la clave aquí.

Nick Brady
fuente
Prefiero convertir la tupla en una cadena usando una de las siguientes declaraciones: print("this is a tuple: %s" % str(thetuple))oprint("this is a tuple: %s" % repr(thetuple))
AlexG
12

En mi caso, es porque solo necesito una sola entrada %s, me faltan valores de entrada.

ParisNakitaKejser
fuente
@ParisNakitaKejser, entonces, ¿cómo obtener el parámetro de entrada para% s?
Jatin Patel - JP
6

Además de las otras dos respuestas, creo que las muescas también son incorrectas en las últimas dos condiciones. Las condiciones son que un nombre es más largo que el otro y deben comenzar con 'elif' y sin hendiduras. Si lo coloca dentro de la primera condición (dándole cuatro hendiduras desde el margen), termina siendo contradictorio porque las longitudes de los nombres no pueden ser iguales y diferentes al mismo tiempo.

    else:
        print ("The names are different, but are the same length")
elif len(name1) > len(name2):
    print ("{0} is longer than {1}".format(name1, name2))
GuyP
fuente
3

Hay una combinación de problemas como se señala en algunas de las otras respuestas.

  1. Como señaló nneonneo, está mezclando diferentes métodos de formato de cadenas.
  2. Como señaló GuyP, su sangría también está desactivada.

He proporcionado tanto el ejemplo de .format como el paso de tuplas al especificador de argumento de% s. En ambos casos, la sangría se ha corregido de modo que sea mayor / menor que los controles fuera de cuando la longitud coincide. También se cambiaron las declaraciones if posteriores a elif's, por lo que solo se ejecutan si la declaración anterior del mismo nivel era False.

Formateo de cadenas con formato.

name1 = input("Enter name 1: ")
name2 = input("Enter name 2: ")
len(name1)
len(name2)
if len(name1) == len(name2):
    if name1 == name2:
        print ("The names are the same")
    else:
        print ("The names are different, but are the same length")
elif len(name1) > len(name2):
    print ("{0} is longer than {1}".format(name1, name2))
elif len(name1) < len(name2):
    print ("{0} is longer than {1}".format(name2, name1))

Formato de cadena con% sy una tupla

name1 = input("Enter name 1: ")
name2 = input("Enter name 2: ")
len(name1)
len(name2)
if len(name1) == len(name2):
    if name1 == name2:
        print ("The names are the same")
    else:
        print ("The names are different, but are the same length")
elif len(name1) > len(name2):
    print ("%s is longer than %s" % (name1, name2))
elif len(name1) < len(name2):
    print ("%s is longer than %s" % (name2, name1))
Trevor Benson
fuente
2

En Python 3.7 y superior hay una forma nueva y fácil. Aquí está la sintaxis:

name = "Eric"
age = 74
f"Hello, {name}. You are {age}."

Salida:

Hello, Eric. You are 74.
Shani
fuente
1

Para mí, como estaba almacenando muchos valores dentro de una sola llamada de impresión, la solución fue crear una variable separada para almacenar los datos como una tupla y luego llamar a la función de impresión.

x = (f"{id}", f"{name}", f"{age}")
print(x) 
Neel0507
fuente
0

Me encuentro con el error también,

_mysql_exceptions.ProgrammingError: not all arguments converted during string formatting 

Pero los argumentos de lista funcionan bien.

Yo uso mysqlclient python lib. Parece que la biblioteca no acepta argumentos de tupla. Para pasar la lista de argumentos como ['arg1', 'arg2'] funcionará.

Victor Choy
fuente
0

consulta sql sin procesar de django a la vista

"SELECT * FROM VendorReport_vehicledamage WHERE requestdate BETWEEN '{0}' AND '{1}'".format(date_from, date_to)

modelos.py

class VehicleDamage(models.Model):
    requestdate = models.DateTimeField("requestdate")
    vendor_name = models.CharField("vendor_name", max_length=50)
    class Meta:
        managed=False

views.py

def location_damageReports(request):
    #static date for testing
    date_from = '2019-11-01'
    date_to = '2019-21-01'
    vehicle_damage_reports = VehicleDamage.objects.raw("SELECT * FROM VendorReport_vehicledamage WHERE requestdate BETWEEN '{0}' AND '{1}'".format(date_from, date_to))
    damage_report = DashboardDamageReportSerializer(vehicle_damage_reports, many=True)
    data={"data": damage_report.data}
    return HttpResponse(json.dumps(data), content_type="application/json")

Nota: usando python 3.5 y django 1.11

Vinay Kumar
fuente