7

データ分析と数値シミュレーションのために、MatlabからPython/numpyに移行することを検討しています。私はMatlab(およびSML-NJ)を何年も使用しており、副作用のない(I / Oを除く)機能環境で非常に快適ですが、Pythonの副作用については少し気が進まないです。人々は副作用に関して彼らの好きな落とし穴を共有することができますか、そして可能であれば、彼らはそれらをどのように回避したのですか?例として、Pythonで次のコードを試したとき、私は少し驚いた。

lofls = [[]] * 4    #an accident waiting to happen!
lofls[0].append(7)  #not what I was expecting...
print lofls         #gives [[7], [7], [7], [7]]
#instead, I should have done this (I think)
lofls = [[] for x in range(4)]
lofls[0].append(7)  #only appends to the first list
print lofls         #gives [[7], [], [], []]

前もって感謝します

4

2 に答える 2

9

同じ (変更可能な) オブジェクトへの参照と別のオブジェクトへの参照を混同することは、実際には "落とし穴" です (変更可能なオブジェクトと、もちろん参照を持つすべての非関数型言語が苦しんでいます)。初心者の Python コードでよく見られるバグは、変更可能なデフォルト値の誤用です。

def addone(item, alist=[]):
  alist.append(item)
  return alist

このコードは、データが C で機能するのとaddone同じように、独自の状態を保持する (そして 1 つの増加するリストを連続する呼び出し元に返す) ことが目的である場合に正しい可能性があります。static呼び出しごとに新しい空のリストが作成されるとコーダーが誤って想定している場合、それは正しくありません。

関数型言語に慣れた生の初心者は、Python の組み込みコンテナのコマンドとクエリの分離設計の決定によって混乱する可能性もあります。具体的に返すものがない変更メソッド (つまり、変更メソッドの大部分) は何も返さない (具体的には、彼らは戻ってきNoneます)-彼らはすべての作業を「その場で」行っています。これを誤解して発生したバグは、簡単に見つけることができます。

alist = alist.append(item)

バグであることがほぼ保証されています. namealistで参照されるリストにアイテムを追加しますが、 namealistNone(呼び出しの戻り値append) に再バインドします。

私が言及した最初の問題は、バインディングが遅いバインディングであると考える人々を誤解させる可能性のある早期バインディングに関するものですが、逆に問題が発生する可能性があります。 、代わりに、遅い。例(架空のGUIフレームワークを使用...):

for i in range(10):
    Button(text="Button #%s" % i,
           click=lambda: say("I'm #%s!" % i))

これは、「ボタン #0」、「ボタン #1」などの 10 個のボタンを表示しますが、クリックすると、すべてのボタンが表示sayます。修正は、引数のデフォルト値が事前にバインドされているという事実を利用して(最初の問題について指摘したように!-)、最後の行を次のように変更することです。#9i lambda

           click=lambda i=i: say("I'm #%s!" % i))

現在、 はデフォルト値をlambda持つi引数であり、もはや自由変数 (レキシカル クロージャによって検索される) ではないため、コードは意図したとおりに機能します (もちろん、他の方法もあります)。

于 2010-03-09T18:53:22.380 に答える
0

numpyへの小さな依存関係を取り除こうとしているときに、(何年にもわたるPythonの後)最近、これに再び遭遇しました。

matlab から来た場合はnumpy、mono-type 配列の処理に関数を使用して信頼する必要があります。matplotlib とともに、これらはスムーズな移行のための非常に便利なパッケージです。

import numpy as np
np.zeros((4,)) # to make an array full of zeros [0,0,0,0]
np.zeros((4,1)) # another one full of zeros but 2 dimensions [[0],[0],[0],[0]]
np.zeros((4,0)) # an empty array like [[],[],[],[]]
np.zeros((0,4)) # another empty array, which can not be represented with python lists o_O

于 2013-03-19T16:48:35.997 に答える