There is a convenient module in python that loads csv. I tried inserting a DB test record using that. At that time, if each CVS column value is assigned to Model by describing the attribute name as shown below, the source code will be changed due to the change of column value and Model class. We will refactor to eliminate this.
The advantages and usage of setattr may be understood by reflecting, but I think this sample is easier to understand.
The execution environment is assumed to be Python 3.4.3.
import csv
class Model():
pass
if __name__ == '__main__':
models = []
with open('person.csv', 'r') as f:
reader = csv.reader(f)
#Read only one line (header)
Model._columns = next(reader)
for row in reader:
model = Model()
#Dynamically set attributes to model
for i in range(len(row)):
model.coulmn1 = row[0]
model.coulmn2 = row[1]
models.append(model)
I will post the csv file to be used this time first.
id,name,age
1,Taro,19
2,Ziro,18
3,Mikio,40
4,Mineko,38
Python has a built-in function called setattr. Use as setattr (object, attribute name, value)
. What's good about this is that you can specify the attribute name with a variable. If you set ʻobj.var1, it will search for var1 in obj. If you want var1 to expand as a variable, use
setattr ()`.
import csv
class Model():
pass
if __name__ == '__main__':
models = []
with open('person.csv', 'r') as f:
reader = csv.reader(f)
#Read only one line (header)
columns = next(reader)
for row in reader:
model = Model()
#Dynamically set attributes to model
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>
Since the attribute of the object is not output as it is, it will be output by default even if dir is not used. In python, a special method called __str__
is executed when printing with a print statement. All you have to do is return the string you want to display with this method.
Those whose prefix is not _ (underscore) are excluded from the display. If you want to define a method for internal processing in Model by this, you can add _ (underscore).
import csv
class Model():
#Because it is included in the number of attributes when comparing with the length of the element
#Add underscore
_columns = []
def __init__(self):
if len(self._columns) == 0:
raise Exeption("Please set the columns of %s" % self)
def __str__(self):
attribute_str = ""
#The prefix is_Exclude
attributes = list(filter(
lambda attribute_name: not(attribute_name[0].startswith("_")),
dir(self)))
if len(attributes) == len(self._columns):
#Refer to the class variable because self does not have columns
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)
#Read only one line (header)
Model._columns = next(reader)
for row in reader:
model = Model()
#Dynamically set attributes to model
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