coLinux日記

coLinuxはフリーソフトを種として、よろずのシステムとぞなれりける。

SimplePrograms で Python を学ぶ その16

2024-06-29 09:43:52 | Python
SimplePrograms - Python Wiki
https://wiki.python.org/moin/SimplePrograms

の 16番目のプログラムは、 csv 、 タプル・アンパック 、 cmp() です。

import csv

# need to define cmp function in Python 3
def cmp(a, b):
    return (a > b) - (a < b)

# write stocks data as comma-separated values
with open('stocks.csv', 'w', newline='') as stocksFileW:
    writer = csv.writer(stocksFileW)
    writer.writerows([
       ['GOOG', 'Google, Inc.', 505.24, 0.47, 0.09],
       ['YHOO', 'Yahoo! Inc.', 27.38, 0.33, 1.22],
       ['CNET', 'CNET Networks, Inc.', 8.62, -0.13, -1.4901]
    ])

# read stocks data, print status messages
with open('stocks.csv', 'r') as stocksFile:
    stocks = csv.reader(stocksFile)

    status_labels = {-1: 'down', 0: 'unchanged', 1: 'up'}
    for ticker, name, price, change, pct in stocks:
       status = status_labels[cmp(float(change), 0.0)]
       print ('%s is %s (%.2f)' % (name, status, float(pct)))

prog-16.py というファイルにして実行してみます。

$ ls
prog-16.py
$ ./prog-16.py
Google, Inc. is up (0.09)
Yahoo! Inc. is up (1.22)
CNET Networks, Inc. is down (-1.49)
$ ls
prog-16.py stocks.csv
$ cat stocks.csv
GOOG,"Google, Inc.",505.24,0.47,0.09
YHOO,Yahoo! Inc.,27.38,0.33,1.22
CNET,"CNET Networks, Inc.",8.62,-0.13,-1.4901
$

実行すると、前半で stocks.csv という CVS 形式のファイルが作成され、後半でそのファイルを読み込んで、
定義した cmp() 関数の結果を含めて表示するプログラムですね。

まず、cmp() 関数の定義ですが、複数引数を持つ場合ですね。 カンマで引数を分けており、
条件式が True なら 1、 False なら 0 になる事を利用して、
cmp(a, b) で、 a>b なら 1、 a=b なら 0、 a<b なら -1 を返す関数です。

じつは、この関数 python2 ではあったのに python3 から無くなったようです。
別の古い Raspberry Pi で試して見ます。
$ python
Python 2.7.13 (default, Feb 6 2022, 20:16:18)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "cmp(80,100) : ", cmp(80,100)
cmp(80,100) : -1
>>> # print は、カッコがなくてもエラーにならない!

$ python3
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print "cmp(80,100) :", cmp(80,100)
File "<stdin>", line 1
print "cmp(80,100) :", cmp(80,100)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
>>> # print は、カッコがないとエラー
>>>
>>> print("cmp(80,100) :", cmp(80,100))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'cmp' is not defined
>>>

これは、古いPythonのプログラムを Python3 で使うときの非互換になるので対処が必要という話なので、サンプルプログラムに取り上げたのが興味深いです。

前半のファイル書き込み用の open() 関数は、次の説明から理解できます。
https://docs.python.org/ja/3/library/functions.html?highlight=open#open

ファイル名の引数の次の引数が、'w' なので、ファイルへの書き出し用 に開くのですね。
newline='' は、
「ユニバーサル改行モードは有効になりますが、行末は変換されずに呼び出し元に返されます。」
ということで、普通はこの指定で良さそうです。

次に CSV ファイルの読み書きです。
https://docs.python.org/ja/3/library/csv.html

CSVファイルはよく使う可能性があるので、とりあえず読み込みと書き込みはこのサンプルを丸ごと使うのが良さそうです。
例えば、
a01,b01,c01
a02,b02,c02
というCSVファイルは、1行づつ配列(正確には「変更可能なシーケンス型であるリスト型」のようです。)配列にして、
それらを個々の要素にして更に配列を作るわけですね。

そのオブジェクトを 'w' でファイルをオープンして、 csv.writer() と writerows() で書き出すと理解すれば良さそうです。

一方 CSVファイルの読み込みは、 'r' でファイルをオープンして csv.reader() で読み込むのですね。

ここで、for 文でファイルから読み込んだオブジェクトを1行づつ読み込むために、

for ticker, name, price, change, pct in stocks:

を使って、CSVファイルの1行を表すタプルをアンパックして各変数に代入し、各行の処理を行うようです。

各変数の値は文字列として受け取るらしいので、 change は float(change)で浮動小数点にするわけです。
もし整数なら、int(change) ですね。

status_labels は、お馴染みの辞書型ですね。最初に定義したcmp()関数を使って、change の値を判定して、
その判定値によって辞書を引いて、'down', 'unchanged', 'up' を出力するプログラムでした。

サンプルプログラムをそのまま利用するのが、とりあえず CSV ファイル操作の Python プログラムを作るときは近道ですね。
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする