web-dev-qa-db-fra.com

Comment expliquer la fonction str.maketrans dans Python 3.6?

Je participe actuellement à un cours Udacity qui enseigne aux étudiants la programmation en Python. L'un des projets demande aux étudiants de renommer des fichiers photo (supprimer les numéros du nom) dans un répertoire afin de les classer par ordre alphabétique, après quoi un message secret sera épelé. Par exemple, si un nom de fichier est "48athens", Le programme cherche à supprimer les numéros, en ne laissant que "athens" Comme nom de fichier.

J'utilise Python 3.6, alors que l'instructeur utilise Python 2.7. Je devrais probablement utiliser Python 2.7 donc pour simplifier le processus d’apprentissage, mais pour l’instant je continuerai à utiliser Python 3.6.

Les fichiers ont été renommés par l'instructeur à l'aide de la fonction .translate, Qui prend deux arguments dans Python 2.x, alors que Python = 3.x ne prend qu'un seul argument, il supprime tous les nombres (0 à 9) des noms de fichiers.

import os

def rename_files(): #Obtain the file names from a folder.
    file_list = os.listdir(r"C:\Users\Dennis\Desktop\OOP\prank\prank")
    print (file_list)
    saved_path = os.getcwd()
    os.chdir(r"C:\Users\Dennis\Desktop\OOP\prank\prank")
    for file_name in file_list: #Rename the files inside of the folder.
        os.rename(file_name, file_name.translate(None, "0123456789"))
    os.chdir(saved_path)

rename_files()

Cependant, cela ne fonctionne pas dans Python 3.x, car il est écrit que:

TypeError: translate() takes exactly one argument (2 given)

Heureusement, j'ai trouvé un autre moyen d'utiliser l'aide de quelqu'un. Cependant, je ne sais pas trop comment ça marche. Quelqu'un peut-il m'expliquer la fonction str.maketrans Et à quoi servent les deux premiers arguments vierges entre guillemets? Je pense que cela signifie: pour les deux premiers caractères du nom du fichier, supprimez tous les chiffres (0 à 9). Est-ce exact? Par exemple, dans "48athens", Supprimez les deux premiers caractères (4 et 8) s’il s’agit de nombres compris entre 0 et 9.

import os

def rename_files(): #Obtain the file names from a folder.
    file_list = os.listdir(r"C:\Users\Dennis\Desktop\OOP\prank\prank")
    print (file_list)
    saved_path = os.getcwd()
    os.chdir(r"C:\Users\Dennis\Desktop\OOP\prank\prank")
    for file_name in file_list: #Rename the files inside of the folder.
        os.rename(file_name, file_name.translate(str.maketrans('','','0123456789')))
    os.chdir(saved_path)

rename_files()

Ma compréhension de la documentation:

static str.maketrans(x[, y[, z]]) Cette méthode statique renvoie une table de traduction utilisable pour str.translate().

Cela signifie que les arguments passés à str.maketrans, Ainsi que la fonction réelle str.maketrans, Formeront un tableau qui dit: "Si ce caractère apparaît, remplacez-le par ce caractère." Cependant, je ne suis pas sûr de savoir à quoi servent les crochets.

S'il n'y a qu'un seul argument, il doit s'agir d'un dictionnaire mappant des ordinaux Unicode (entiers) ou des caractères (chaînes de longueur 1) sur des ordinaux Unicode, des chaînes (de longueur arbitraire) ou Aucun. Les clés de personnage seront ensuite converties en ordinaux.

Cela signifie qu'il ne peut changer que des entiers, ou des caractères dans des chaînes de longueur un, en d'autres entiers ou chaînes (de n'importe quelle longueur que vous voulez). Mais je crois avoir trois arguments, pas un.

S'il y a deux arguments, il doit s'agir de chaînes de longueur égale et, dans le dictionnaire résultant, chaque caractère de x sera associé au caractère situé à la même position dans y. S'il existe un troisième argument, il doit s'agir d'une chaîne dont les caractères seront mappés sur Aucun dans le résultat.

J'ai trois arguments ('', '', '0123456789'). Je pense que x est le premier '' Et que y est le deuxième ''. J'ai le troisième argument, qui est une chaîne '0123456789', Mais je ne comprends pas ce que signifie être mappé sur 'None'.

28
Dennis

str.maketrans construit une table de traduction, qui est un mappage d'entiers ou de caractères en entiers, chaînes ou None. Pensez-y comme un dictionnaire. Nous parcourons la chaîne pour traduire et remplacer tout ce qui apparaît comme une clé dans le mappage avec quelle que soit sa valeur dans la carte.

Vous pouvez construire une table de traduction avec un, deux, trois arguments (je pense que c'est peut-être ce qui vous trouble). Avec un argument:

str.maketrans({'a': 'b', 'c': None})

Vous attribuez à la fonction un mappage qui suit les règles pour les tables de traduction et renvoie une table équivalente pour ce mappage. Les éléments mappés sur None sont supprimés

Avec deux arguments:

str.maketrans('abc', 'xyz')

Vous lui donnez deux cordes. Chaque caractère de la première chaîne est remplacé par le caractère correspondant à cet index de la deuxième chaîne. Alors 'a' mappe sur 'x', 'b' à 'y', et 'c' à 'z'.

Celui que vous utilisez, avec trois arguments, fonctionne de la même manière que deux arguments, mais comporte une troisième chaîne.

str.maketrans('abc', 'xyz', 'hij')

Ceci est identique à la version à deux arguments, sauf que les caractères de la troisième chaîne sont supprimés, comme s'ils étaient mappés sur None. Donc, votre table dit "Ne remplacez rien, mais supprimez les caractères qui apparaissent dans cette chaîne".

43
Patrick Haugh

De la documentation sur str.maketrans :

S'il existe un troisième argument, il doit s'agir d'une chaîne dont les caractères seront mappés à None dans le résultat.

C'est quoi str.maketrans fait; il prend chaque élément du troisième argument et crée une mappe (un dictionnaire Python) qui mappe chaque valeur ordinale des caractères de la chaîne à None:

>>> str.maketrans('', '', '0123456789') 
{48: None,
 49: None,
 50: None,
 51: None,
 52: None,
 53: None,
 54: None,
 55: None,
 56: None,
 57: None}

Si des valeurs supplémentaires existent en tant que premier et second arguments, , elles sont ajoutées à ce mappage en tant que caractères supplémentaires à traduire (c'est pourquoi l'auteur a sélectionné '' et ''; il ne veut pas que des caractères supplémentaires soient traduits):

>>> str.maketrans('a', 'A', '0123456789') 
{48: None,
 49: None,
 50: None,
 51: None,
 52: None,
 53: None,
 54: None,
 55: None,
 56: None,
 57: None,
 97: 65}   # map ord('a') to ord('A')

Si vous appliquez cela à votre chaîne maintenant, cela va également capitaliser 'athens' à 'Athens' en raison du supplément 'a', 'A' nous avons fourni à maketrans. Pas la plus belle des traductions mais suffit pour saisir la fonctionnalité.

str_obj.translate effectuera ensuite des recherches dans ce dictionnaire pour chaque caractère de str_obj remplaçant ses valeurs par celles du mappage. S'il ne le trouve pas dans le mappage, il le laisse tel quel, s'il est None, il le supprime. Ceci est indiqué dans le documentation pour str.translate :

Lorsqu'il est indexé par un ordinal Unicode (un entier), l'objet table peut effectuer l'une des opérations suivantes: renvoyer un ordinal Unicode ou une chaîne, pour mapper le caractère à un ou plusieurs autres caractères; return None, pour supprimer le caractère de la chaîne de retour ; ou lever une exception LookupError pour mapper le caractère sur lui-même.

(Mon accentuation)

7
import string
import os
  # Required to call maketrans function.

#trantab = maketrans()
def rename_files():

    x=os.listdir(r'C:\Users\user\Desktop\prank')
    print (x)

    path=os.getcwd()
    print("path is"+path)
    os.chdir(r'C:\Users\user\Desktop\prank')
    for file in x:
        os.rename(file,file.translate(file.maketrans('','','0123456789')))
rename_files()
0
Akash