Для анализа реальных данных CSV (значений, разделенных запятыми) вы можете использовать модуль CSV, который включен в последние версии Python.
CSV - это набор соглашений, а не стандарт. Образцы данных, которые вы показываете, простые и регулярные, но в CSV обычно есть некоторые уродливые угловые случаи для цитирования, где содержимое любого поля может иметь встроенные запятые, например.
Вот очень грубая программа, основанная на вашем коде, которая выполняет наивный анализ данных (разделение на строки, затем разделение каждой строки запятыми). Он не будет обрабатывать любые данные, которые не разделяются на точное количество полей, а также те, где числовые поля неправильно анализируются функциями Python int()
и float()
(конструкторами объектов). Другими словами, это не содержит ни проверки ошибок, ни обработки исключений.
Тем не менее, я держал это намеренно простым, чтобы его можно было легко сравнить с вашими грубыми заметками. Также обратите внимание, что я использовал обычные соглашения Python, касающиеся ссылок на себя в определении класса. (Практически единственный раз, когда для них используются имена, отличные от «self», - это при программировании «мета-класса» ... написание классов, которые динамически создают другие классы. Любой другой случай почти наверняка вызовет серьезную озабоченность опытные программисты на Python, смотрящие на ваш код).
#!/usr/bin/env python
class Jewel:
def __init__(self, name, carat, value):
self.name = name
self.carat = int(carat)
self.value = float(value)
assert self.carat != 0 # Division by zero would result from this
def __repr__(self):
return repr((self.name, self.carat, self.value))
if __name__ == '__main__':
sample='''ruby,2,100
diamond,1,400
emerald,3,250
amethyst,2,50
opal,1,300
sapphire,2,500
malachite,1,60'''
these_jewels = list()
for each_line in sample.split('\n'):
gem_type, carat, value = each_line.split(',')
these_jewels.append(Jewel(gem_type, carat, value))
# Equivalently:
# these_jewels.append(Jewel(*each_line.split(',')))
decorated = [(x.value/x.carat, x) for x in these_jewels]
results = [x[1] for x in sorted(decorated)]
print '\n'.join([str(x) for x in results])
Синтаксический анализ здесь выполняется просто с использованием строкового метода .split()
, а данные извлекаются в имена с использованием синтаксиса Python «распаковка кортежей» (это не удастся, если в какой-либо строке ввода будет указано неправильное количество полей).
Альтернативный синтаксис для этих двух строк использует синтаксис Python «применить». Префикс * для аргумента приводит к его распаковке в отдельные аргументы, которые передаются в экземпляр класса Jewel()
.
В этом коде также используется широко распространенный (и широко рекомендуемый) шаблон DSU (декорирование, сортировка, декорирование) для сортировки в некотором поле ваших данных. Я «декорирую» данные, создавая серию кортежей: (вычисленное значение, ссылка на объект), а затем «декорирую» отсортированные данные таким образом, который, я надеюсь, вам понятен. (Это было бы сразу понятно любому опытному программисту на Python).
Да, весь блок DSU может быть сведен к одной строке; Я выделил это здесь для разборчивости и педагогических целей.
Опять же, этот пример кода предназначен исключительно для вашего назидания. Вы должны использовать модуль CSV для любых реальных данных; и вы должны ввести обработку исключений либо в разборе, либо в обработке Jewel.__init__
(для преобразования числовых данных в правильные типы Python.
(Также обратите внимание, что вам следует рассмотреть возможность использования модуля Python Decimal
вместо float()
s для представления денежных значений ... или, по крайней мере, хранения значений в центах или миллах и использования собственных функций для представления их в долларах и центах).