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.

user2652300
la source

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)
nneonneo
la source
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)
Leonh
la source
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.

Nick Brady
la source
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
la source
@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))
GuyP
la source
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))
Trevor Benson
la source
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.
Shani
la source
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) 
Neel0507
la source
1

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

number=89
number=int(89)
sameer_nubia
la source
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.

Victor Choy
la source
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

Vinay Kumar
la source