表示在init中显示的顺序的类,没有硬编码

时间:2014-03-11 19:33:55

标签: python python-2.7 csv

在一种方法中,我解析了一个CSV文件。在每次迭代中,我从该条目中创建一个对象。鉴于该对象代表该CSV文件中的一行,如果它是有序的,那么它将更容易阅读,而不仅仅是return self.__dict__

class Student:
  def __init__(self, name, grade, classes):
    self.name = name
    self.grade = grade
    self.classes = classes
  def __repr__(self):
    return #ordered version of self

CSV功能:

with open(arguments.csv, 'rb') as csv_file:
  csv_data = csv.reader(csv_file)
  data = [Student(*row) for row in csv_data]

预期输出(包括“漂亮打印”,与原始init匹配):

Student:
  name: 'Crow',
  grade: 1,
  classes: ['pecking', 'cawing', 'scavenging', 'advanced film theory']
Student:
  name: 'Odin',
  grade: 9999,
  classes: ['Norse Mythology', 'Orithonology']

如何在没有硬编码的情况下以有序的方式表示它?

2 个答案:

答案 0 :(得分:4)

您的__init__方法已订购名称;它们恰好与您的__dict__键匹配,因此您可以使用它们:

import inspect

class Student(object):
    def __init__(self, name, grade, classes):
        self.name = name
        self.grade = grade
        self.classes = classes
    def __repr__(self):
        return '{}\n{}'.format(type(self).__name__,
            '\n'.join(['  {}: {!r}'.format(name, getattr(self, name))
                       for name in inspect.getargspec(self.__init__).args[1:]]))

此处,inspect.getargspec()返回self.__init__方法的签名信息; .args是位置参数。将其切成[1:]会跳过第一个参数self

演示:

>>> Student('Crow', 1, ['pecking', 'cawing', 'scavenging', 'advanced film theory'])
Student
  name: 'Crow'
  grade: 1
  classes: ['pecking', 'cawing', 'scavenging', 'advanced film theory']

答案 1 :(得分:1)

我通常更喜欢对内省的宣言:

import itertools
class Student(object):

    columns = ('name', 'grade', 'classes')

    def __init__(self, *row):
        self.row = _,_,_ = row # Aaaaah, dragons !

    def __getattr__(self, key):
        if key in self.columns:
            return self.row[self.columns.index(key)]

    def __repr__(self):
        return '{}\n{}'.format(
                type(self).__name__,
                '\n'.join(('  {}: {!r}'.format(*item)
                    for item in itertools.izip(self.columns, self.row) ))
                )

您甚至可以添加通用触摸:

import itertools
class Row(object):
    columns = ()
    def __init__(self, *row):
        if len(row) != len(self.columns):
            raise TypeError('{}() takes {} argument'.format(
                    type(self).__name__, len(self.columns)))
        self.row = row
    def __getattr__(self, key):
        if key in self.columns:
            return self.row[self.columns.index(key)]
    def __repr__(self):
        return '{}\n{}'.format(
                type(self).__name__,
                '\n'.join(('  {}: {!r}'.format(*item)
                    for item in itertools.izip(self.columns, self.row) ))
                )
class Student(Row):
    columns = ('name','grade','classes')
相关问题