設計決定を見直す

Beginner

This tutorial is from open-source community. Access the source code

はじめに

このセクションでは、以前に行った設計決定を再考します。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 初級 レベルの実験の完了率は 83%です。学習者から 100% の好評価を得ています。

ファイル名と反復可能オブジェクト

同じ出力を返すこの 2 つのプログラムを比較しましょう。

## ファイル名を指定する
def read_data(filename):
    records = []
    with open(filename) as f:
        for line in f:
           ...
            records.append(r)
    return records

d = read_data('file.csv')
## 行を指定する
def read_data(lines):
    records = []
    for line in lines:
       ...
        records.append(r)
    return records

with open('file.csv') as f:
    d = read_data(f)
  • これらの関数のどちらが好きですか?なぜですか?
  • これらの関数のどちらがより柔軟ですか?

深い考え方:「ダックタイピング」

ダックタイピング は、オブジェクトが特定の目的に使用できるかどうかを判断するコンピュータプログラミングの概念です。これは、ダックテスト の応用です。

見た目がアヒルで、泳ぎ方がアヒルで、鳴き声がアヒルなら、おそらくそれはアヒルです。

上の read_data() の 2 番目のバージョンでは、関数は任意の反復可能オブジェクトを期待します。ファイルの行だけでなくです。

def read_data(lines):
    records = []
    for line in lines:
     ...
        records.append(r)
    return records

これは、他の と一緒に使用できることを意味します。

## CSV ファイル
lines = open('data.csv')
data = read_data(lines)

## 圧縮ファイル
lines = gzip.open('data.csv.gz','rt')
data = read_data(lines)

## 標準入力
lines = sys.stdin
data = read_data(lines)

## 文字列のリスト
lines = ['ACME,50,91.1','IBM,75,123.45',... ]
data = read_data(lines)

この設計にはかなりの柔軟性があります。

質問:この柔軟性を受け入れるべきか、抵抗するべきか?

ライブラリ設計のベストプラクティス

コードライブラリは、柔軟性を受け入れることで多くの場合、より良い結果が得られます。オプションを制限しないでください。大きな柔軟性には大きな力が伴います。

演習 3.17:ファイル名からファイルライクオブジェクトへ

これまでに、parse_csv() 関数を含む fileparse.py というファイルを作成しました。この関数は次のように機能しました。

>>> import fileparse
>>> portfolio = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>>

今のところ、この関数はファイル名を渡されることを期待しています。ただし、コードをより柔軟にすることができます。関数を修正して、任意のファイルライク/反復可能オブジェクトと動作するようにしましょう。たとえば:

>>> import fileparse
>>> import gzip
>>> with gzip.open('portfolio.csv.gz', 'rt') as file:
...      port = fileparse.parse_csv(file, types=[str,int,float])
...
>>> lines = ['name,shares,price', 'AA,100,34.23', 'IBM,50,91.1', 'HPE,75,45.1']
>>> port = fileparse.parse_csv(lines, types=[str,int,float])
>>>

この新しいコードでは、以前と同じようにファイル名を渡すと何が起こりますか?

>>> port = fileparse.parse_csv('portfolio.csv', types=[str,int,float])
>>> port
... 出力を見る(おそらく狂った出力になるはず)...
>>>

はい、注意が必要です。これを回避するためのセーフティチェックを追加できますか?

演習 3.18:既存の関数の修正

report.py ファイル内の read_portfolio()read_prices() 関数を修正して、修正された parse_csv() のバージョンと動作するようにしましょう。これは僅かな修正にとどまるはずです。その後、あなたの report.pypcost.py プログラムは以前と同じように動作するはずです。

まとめ

おめでとうございます!あなたはデザインディスカッションの実験を完了しました。あなたのスキルを向上させるために、LabEx でさらに多くの実験を行うことができます。