1

意見が必要です。

いくつかのデータを定義する関数があります。私の考えは、ユーザーがファイルからデータを読み取るように指示できるということです。

acquire_data('read_from_file',filename)

または、ユーザーはデータを直接提供できます。

acquire_data('use_this_list',datalist)

したがって、関数は次のような形式になります

def acquire_data(mode,arg2):
    if mode == 'read_from_file':
        inputs=open(arg2)
        data = #etc.
    else:
        data = arg2  #or deepcopy(arg2) or whatever

まあ、これはうまくいきますが、それは一種のハックニーのようです。特に、「arg2」は「mode」の値によって機能が大きく異なります。だから:これは良いコードですか?これは「pythonic」ですか?誰かがこれをコーディングするためのより良い方法を見ますか?ありがとう。

4

6 に答える 6

5
def acquire_data(list_or_filename):
    # assuming py3 here, for py2 use 'isinstance(list_or_filename, basestring)
    if isinstance(list_or_filename, str):
        with open(list_or_filename,"r") as f:
            return acquire_data_from_file(f)
    else:
        return acquire_data_from_list(list_or_filename)
于 2013-02-27T18:52:01.857 に答える
4

ファイルのコンテンツ全体を開いて読み取る代わりに、acquire_dataにを渡す方がよりPython的fileObjですacquire_data

これがより良いデザインである理由

  1. シーケンス、ジェネレーター、ファイルの統一されたインターフェース
  2. 関数内のデータ全体を読み取る必要はありません
  3. 例外が発生した場合でも、ファイルの存続期間を制御できます

スケルトンコードは

def acquire_data(iterable):
    for line in iterable:
        # Do what ever you want

with open("whatever") as fin:
    acquire_data(fin)

acquire_data(some_seq)

acquire_data(some_gen)
于 2013-02-27T18:56:04.853 に答える
2

acquire_data_from_file、、など、さまざまなタスクにさまざまな関数を使用するのはどうacquire_data_from_listですか?はるかに明確でシンプルです。

于 2013-02-27T18:56:20.620 に答える
1

この種の作業はさらに分割して、dictをswitchcaseとして使用します。

def read_file(arg):
 # code

def read_data(arg):
 # code

def default_f(arg):
 # code

def acquire_data(mode, arg2):

    fun = {
    'read_from_file': read_file, 
    'use_this_list': read_data
    }.get(mode, default_f)

    fun(arg2)

編集
2番目のアプローチ:myと@möterを組み合わせました。

def acquire_data(arg):
   fun = {
     True: read_file,
     False: read_data
     }.get(
         isinstance(arg, str),
         default_f
         )
   return fun(arg);

これを呼んでください:

acquire_data('read_from_file',filename)
acquire_data('use_this_list',datalist)
于 2013-02-27T18:55:06.977 に答える
1

Pythonのダックタイピングにより、変数または引数のデータ型に応じて関数が異なる動作を実行するため、このタイプの方法は比較的一般的です。

関数をそのままにしておくこともできますが、実行することを検討します

if mode == 'read_from_file':
        inputs=open(arg2)
        data = #etc.
elif mode == 'use_this_list':
        data = arg2  #or deepcopy(arg2) or whatever
else:
        raise InputError # or something like this

関数が拡張可能であり、関数の2番目の部分に不適切な引数が渡されていないことを確認してください。

別の方法は、データ自体に加えて、開いているファイルやファイル名を受け入れることです。

def acquire_data(arg):
    if isinstance(arg, file):
        data = arg.read() # make sure to parse the data
    elif isinstance(arg, basestring):
        data = open(arg, 'r').read() # make sure to parse
    else:
        data = arg
于 2013-02-27T19:00:33.363 に答える
1

ファイル名またはデータのリストのいずれかを取得できる単一の関数が本当に必要な場合(おそらくそうではありませんが、oseiskarとAbhijitが提案したよりPythonの代替案には抵抗があるようです)、絶対にこれを実行したくないでしょう。仕方。

一般に、タイプの切り替えを行っていることに気付いた場合は、何か問題があります。しかし、文字列に基づいて偽の型の切り替えを行い、文字列を型に一致させるためにユーザーに依存することは、さらに間違っています。

1つの代替方法は、ファイル名を開こうとすることです。それが失敗した場合は、ファイル名ではなくシーケンスであると想定します。(許可よりも許しを求める方が簡単です。)例:

def acquire_data(filename_or_list):
    try:
        with open(filename_or_list) as f:
            data = list(f)
    except TypeError:
        data = list(filename_or_list)
    # ... now the rest of your code uses data

これは、ユーザーが、の代わりに、またはの代わりにunicodeファイル名を渡した場合でも、または聞いたことのないクラスでさえ、または関数で機能する場合でも機能します。それがダックタイピングの本質です。strtuplelistopenlist

もちろん、これはダックタイピングの悪用ですが、それはあなたの問題に固有のものです。2つの異なるタイプのいずれかのパラメーターを取得しようとしています。その機能を実現するソリューションは、一部の機能を悪用します。

唯一の心配は、誰かがとの両方で機能する何かを渡すかもしれないということopenですlist。実際、それは普通の古いものにも当てはまりますstr。したがって、そのような場合をどうするかについての一般的な決定が必要です。最初にパス名として、次にシーケンスとしてそれを試す方が、他の方法よりも優れているようです。それは確かにあなたが望んでいることですがstr、それが両方の方法で機能するすべての可能なタイプに当てはまるかどうかを考えなければなりません。

于 2013-02-27T19:10:43.290 に答える