4

Mathematicaユーザーとして、私は自動的に「リストをスレッド化」する関数が好きです(Mathematicaの人々がそれを呼んでいるように、http://reference.wolfram.com/mathematica/ref/Listable.htmlを参照してください)。つまり、関数に単一の値ではなくリストが指定された場合、関数は自動的に各リストエントリを引数として使用し、結果のリストを返します。

myfunc([1,2,3,4]) -> [myfunc(1),myfunc(2),myfunc(3),myfunc(4)]

私はこの原則を次のようにPythonで実装しました。

def myfunc(x):    
    if isinstance(x,list):
        return [myfunc(thisx) for thisx in x]
    #rest of the function

これはそれを行うための良い方法ですか?この実装または戦略全体の欠点について考えてみてください。

4

2 に答える 2

7

これを多くの関数で行う場合は、Python デコレーターを使用できます。これはシンプルですが便利なものです。

def threads_over_lists(fn):
    def wrapped(x, *args, **kwargs):
        if isinstance(x, list):
            return [fn(e, *args, **kwargs) for e in x]
        return fn(x, *args, **kwargs)
    return wrapped

@threads_over_listsこのように、関数の前に行を追加するだけで、このように動作します。例えば:

@threads_over_lists
def add_1(val):
    return val + 1

print add_1(10)
print add_1([10, 15, 20])

# if there are multiple arguments, threads only over the first element,
# keeping others the same

@threads_over_lists
def add_2_numbers(x, y):
    return x + y

print add_2_numbers(1, 10)
print add_2_numbers([1, 2, 3], 10)

また、これをリストに対してのみベクトル化するか、タプルやジェネレーターなどの他の反復可能なオブジェクトに対してもベクトル化するかを検討する必要があります。これは、それを判断するための便利な StackOverflow の質問です。ただし、文字列は反復可能ですが、文字列内の各文字に対して関数を動作させたくないでしょう。

于 2012-08-29T09:57:48.210 に答える
3

それはそれを行う良い方法です。ただし、作成する関数ごとにこれを行う必要があります。それを避けるには、次のようなデコレータを使用できます。

def threads(fun):
  def wrapper(element_or_list):
    if isinstance(element_or_list, list):
      return [fun(element) for element in element_or_list]
    else:
      return fun(element_or_list)

  return wrapper

@threads
def plusone(e):
  return e + 1

print(plusone(1))
print(plusone([1, 2, 3]))
于 2012-08-29T09:58:41.643 に答える