TypeError: tous les arguments ne sont pas convertis lors du formatage de la chaîne python


202

Le programme est censé prendre deux noms, et s'ils ont la même longueur, il devrait vérifier s'ils sont le même mot. Si c'est le même mot, il affichera "Les noms sont les mêmes" . S'ils sont de la même longueur mais avec des lettres différentes, il affichera "Les noms sont différents mais de même longueur" . La partie avec laquelle j'ai un problème se trouve dans les 4 dernières lignes.

#!/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)

Lorsque j'exécute ce code, il affiche:

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

Toutes les suggestions sont très appréciées.

Réponses:


215

Vous mélangez différentes fonctions de format.

La %mise en forme à l' ancienne utilise des %codes pour la mise en forme:

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

La {}mise en forme du nouveau style utilise des {}codes et la .formatméthode

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

Notez qu'avec le formatage à l'ancienne, vous devez spécifier plusieurs arguments à l'aide d'un tuple:

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

Dans votre cas, puisque vous utilisez des {}spécificateurs de format, utilisez .format:

"'{0}' is longer than '{1}'".format(name1, name2)

20
en python 3.6:f"'It will cost ${your_variable} dollars."
JinSnow

2
@JinSnow il n'a pas besoin du signe $.
Mahmoodvcs

51

L'erreur est dans le formatage de votre chaîne.

La bonne façon d'utiliser le formatage de chaîne traditionnel à l'aide de l'opérateur '%' est d'utiliser une chaîne de format de style printf (documentation Python pour cela ici: http://docs.python.org/2/library/string.html#format- syntaxe de chaîne ):

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

Cependant, l'opérateur '%' sera probablement obsolète à l'avenir . La nouvelle façon de faire PEP 3101 est la suivante:

"'{0}' is longer than '{1}'".format(name1, name2)

10
scnr: "sera probablement obsolète à l'avenir" ne s'est pas produit jusqu'à présent (Python 3.5). L'ancienne syntaxe '%' n'était pas obsolète dans la version 3.1 et seulement dans la version 3.2, le module de journalisation a appris à formater avec le nouveau style{} . Et soudainement 3.5 apporte PEP 461: %formatage des octets . Cela me fait penser que les %restes pendant longtemps.
cfi

7
%est plus concis. Heureux que ça reste avec nous.
Lenar Hoyt

3
Je suis d'accord. % est plus concis et la suppression n'ajouterait aucun avantage à la langue.
chevydog

@LenarHoyt Que pensez-vous des f-strings? Je ne peux pas imaginer que ce soit "'%s' is longer than '%s'" % (name1, name2)plus concis quef"'{name1}' is longer than '{name2}'"
Mark Moretto

Je suis tout à fait pour les chaînes de caractères, mais elles sont trop récentes et vous ne pouvez pas les utiliser sur un projet de plus d'un an
Darko Kolev

44

Pour moi, cette erreur a été provoquée lorsque j'essayais de passer un tuple dans la méthode de format de chaîne.

J'ai trouvé la solution à partir de cette question / réponse

Copier et coller la bonne réponse à partir du lien (PAS MON TRAVAIL) :

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

Faire un tuple singleton avec le tuple d'intérêt comme seul élément, c'est-à-dire la partie (thetuple,), est le bit clé ici.


Je préfère convertir le tuple en une chaîne en utilisant l'une des instructions suivantes: print("this is a tuple: %s" % str(thetuple))ouprint("this is a tuple: %s" % repr(thetuple))
AlexG

12

Dans mon cas, c'est parce que je n'ai besoin que d'une seule %sentrée de valeurs manquantes.


@ParisNakitaKejser, alors comment obtenir le paramètre d'entrée pour un seul% s?
Jatin Patel - JP

6

En plus des deux autres réponses, je pense que les indentations sont également incorrectes dans les deux dernières conditions. Les conditions sont qu'un nom est plus long que l'autre et qu'ils doivent commencer par «elif» et sans indentations. Si vous le mettez dans la première condition (en lui donnant quatre indentations à partir de la marge), cela finit par être contradictoire car les longueurs des noms ne peuvent pas être égales et différentes en même temps.

    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))

3

Il y a une combinaison de problèmes comme souligné dans quelques-unes des autres réponses.

  1. Comme indiqué par nneonneo, vous mélangez différentes méthodes de formatage de chaîne.
  2. Comme l'a souligné GuyP, votre indentation est également désactivée.

J'ai fourni à la fois l'exemple de .format et la transmission de tuples au spécificateur d'argument de% s. Dans les deux cas, l'indentation a été corrigée de sorte que les vérifications supérieures / inférieures sont en dehors du moment où la longueur correspond. Également changé les instructions if suivantes en elif afin qu'elles ne s'exécutent que si l'instruction de même niveau précédente était False.

Formatage de chaîne avec .format

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))

Formatage de chaîne avec% s et un tuple

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))

2

En python 3.7 et supérieur, il existe un moyen nouveau et simple. voici la syntaxe:

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

Production:

Hello, Eric. You are 74.

1

Pour moi, comme je stockais de nombreuses valeurs dans un seul appel d'impression, la solution était de créer une variable distincte pour stocker les données sous forme de tuple, puis d'appeler la fonction d'impression.

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

1

Le moyen le plus simple de convertir le nombre de chaînes en nombre entier

number=89
number=int(89)

0

Je rencontre également l'erreur,

_mysql_exceptions.ProgrammingError: not all arguments converted during string formatting 

Mais les arguments de liste fonctionnent bien.

J'utilise mysqlclient python lib. La bibliothèque semble ne pas accepter les arguments de tuple. Passer des arguments de liste comme ['arg1', 'arg2'] cela fonctionnera.


0

Requête SQL brute django en vue

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

models.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")

Remarque: en utilisant python 3.5 et django 1.11

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.