Ajouter dynamiquement l'en-tête CSV comme nom d'attribut de la classe Model à l'aide de setattr de python

python a un module pratique qui charge csv, non? J'ai essayé d'insérer un enregistrement de test DB en utilisant cela. À ce moment-là, si chaque valeur de colonne de CVS est affectée au modèle en décrivant le nom d'attribut comme indiqué ci-dessous, le code source sera modifié en raison du changement de valeur de colonne et de classe de modèle. Nous allons refactoriser pour éliminer cela.

Les avantages et l'utilisation de setattr peuvent être compris en réfléchissant, mais je pense que cet exemple est plus facile à comprendre.

L'environnement d'exécution est supposé être Python 3.4.3.

import csv

class Model():
    pass

if __name__ == '__main__':
    models = []
    with open('person.csv', 'r') as f:
        reader =  csv.reader(f)
        #Lire une seule ligne (en-tête)
        Model._columns = next(reader)
        for row in reader:
            model = Model()
            #Définir dynamiquement les attributs dans le modèle
            for i in range(len(row)):
                model.coulmn1 = row[0]
                model.coulmn2 = row[1]
            models.append(model)

Utilisez setattr pour définir les attributs

Je publierai le fichier csv à utiliser cette fois en premier.

id,name,age
1,Taro,19
2,Ziro,18
3,Mikio,40
4,Mineko,38

python a une fonction intégrée appelée setattr. Utilisé comme setattr (objet, nom d'attribut, valeur). Ce qui est bien, c'est que vous pouvez spécifier le nom de l'attribut avec une variable. Si vous définissez ʻobj.var1, il recherchera var1 dans obj. Si vous voulez que var1 se développe en tant que variable, utilisez setattr ()`.

import csv

class Model():
    pass

if __name__ == '__main__':
    models = []
    with open('person.csv', 'r') as f:
        reader =  csv.reader(f)
        #Lire une seule ligne (en-tête)
        columns = next(reader)
        for row in reader:
            model = Model()
            #Définir dynamiquement les attributs dans le modèle
            for i in range(len(row)):
                setattr(model, columns[i], row[i])
            models.append(model)

    for model in models:
        print(model)

# =>
# <__main__.Model object at 0x1053169b0>
# <__main__.Model object at 0x105316a58>
# <__main__.Model object at 0x105316b00>
# <__main__.Model object at 0x105316ba8>

Maintenir l'ordre de la liste d'attributs

S'il est laissé tel quel, les attributs de l'objet ne seront pas affichés, donc même si vous n'utilisez pas dir, il sera affiché par défaut. En python, une méthode spéciale appelée __str__ est exécutée lors de l'impression avec une instruction print. Tout ce que vous avez à faire est de renvoyer la chaîne que vous souhaitez afficher avec cette méthode.

Ceux dont le préfixe n'est pas _ (trait de soulignement) sont exclus de l'affichage. Si vous souhaitez définir une méthode de traitement interne dans Model par ceci, vous pouvez ajouter _ (trait de soulignement).

import csv

class Model():
    #Parce qu'il est inclus dans le nombre d'attributs lors de la comparaison avec la longueur de l'élément
    #Ajouter un underbar
    _columns = []

    def __init__(self):
        if len(self._columns) == 0:
            raise Exeption("Please set the columns of %s" % self)

    def __str__(self):
        attribute_str = ""
        #Le préfixe est_Exclure
        attributes = list(filter(
                            lambda attribute_name: not(attribute_name[0].startswith("_")),
                            dir(self)))

        if len(attributes) == len(self._columns):
            #Se référer à la variable de classe car self n'a pas de colonnes
            for attribute in self._columns:
                attribute_str += "%s = %s \n" % (attribute,
                                                 getattr(self, attribute))
        else:
            raise Exception("Incorrect the number of %s.columns" % self)

        return attribute_str

if __name__ == '__main__':
    models = []
    with open('person.csv', 'r') as f:
        reader =  csv.reader(f)
        #Lire une seule ligne (en-tête)
        Model._columns = next(reader)
        for row in reader:
            model = Model()
            #Définir dynamiquement les attributs dans le modèle
            for i in range(len(row)):
                setattr(model, Model._columns[i], row[i])
            models.append(model)

    for model in models:
        print(model)

# =>
# id = 1 
# name = Taro 
# age = 19 
# 
# id = 2 
# name = Ziro 
# age = 18 
# 
# id = 3 
# name = Mikio 
# age = 40 
# 
# id = 4 
# name = Mineko 
# age = 38

Recommended Posts

Ajouter dynamiquement l'en-tête CSV comme nom d'attribut de la classe Model à l'aide de setattr de python
Encodage de caractères lors de l'utilisation du module csv de python 2.7.3
[Python] Implémentation du clustering à l'aide d'un modèle gaussien mixte
Ajouter des attributs d'objets de classe avec une instruction for
Exemple d'obtention du nom du module et du nom de la classe en Python
Identification de nom à l'aide de python
[Python3] Mettre en forme la chaîne de caractères en utilisant le nom de la variable comme clé