リストがあります:
list1 = [1,2,3]
関数を使用して、元のリストで置き換えたいデータを取得する場合
new_data = [2,3,4]
しない理由
list1 = new_data
元のリストを変更しますか? 新しい参照を作成するのはなぜですか?
list1[:] = new_data
は機能しますが、他の式が機能しないのはなぜですか?
それはPythonの仕組みではないからです。(このように機能する言語は何ですか?)
Python の変数名は、名前そのものです。割り当ては、 によって名付けられたオブジェクトの新しい名前を作成するfoo = whatever
だけです。単純な代入では、既存のオブジェクトが変更されることはありません。foo
whatever
Python の名前はオブジェクトのラベルであり、メモリの場所ではありません。これは C++ とは大きく異なります。1 つのオブジェクトに多くの名前がある場合もあれば、別のオブジェクト (リストなど) に含まれている場合は名前がまったくない場合もあります。
単純な代入はオブジェクトを変更せず、名前を再バインドするだけです。以前にバインドされていたオブジェクトはlist1
変更されませんが、その名前がプログラムで参照された唯一の方法である場合はガベージ コレクションされる可能性があります。
Web ページCode like a Pythonistaは、これをうまく説明しています。Python変数をよりよく理解したい場合は、チェックしてください。
それがPythonでの割り当ての仕組みだからです。すべての割り当ては、指定された名前を、それらが既に参照しているオブジェクト以外のオブジェクトを参照するように変更します。
C プログラマーの場合: C 変数はポインターであり、Python 変数はハンドルです。あなたは本当にこのようなことをしたいと思いますが、Pythonでは:
// C code
std::vector<int> myvector;
myfunction(std::vector<int> &testvector) {
if (somearg) {
testvector.append(4)
} else {
int[] myints = {4,15,16};
testvector = std::vector<int>(myints)
}
}
testvector はオブジェクトへのポインターであり、それが指すオブジェクトを変更したため、どのパスをたどっても、親は変更を確認します。
Python では、これは次のようになります。
list1 = [1,2,3]
def modfunc(mylist):
if (somearg):
mylist.append(4)
else:
mylist = [1,2,3]
最初のものは機能しますが、2 つ目は機能しません。この場合、mylist はメモリへの直接ポインタではありません。オブジェクト ルックアップ テーブルのエントリを指し、それが実際のオブジェクトを指します。失敗した場合、名前 mylist を別のオブジェクトを指すように変更しますが、親は元のオブジェクトを指す名前のままです。
それが機能する最初のケースでは、名前とオブジェクト リストの両方を実際に参照して、実際のオブジェクトを取得し、それを直接操作します。親と子の両方の名前がこのオブジェクトを指しているため、機能します。
それで、あなたは何をしますか?要するに、これを行う必要はありません。C では、戻り値が 1 つに制限されていたため、参照が必要になることがよくありました。確かに、構造体を使用することはできますが、C で行うのはあまり便利ではありませんでした。Python では、タプルは言語の自然な部分です。では、C で次のようなことをしたいとしましょう。
int sumdefault(std::vector<int> &avector):
if len(avector) == 0:
int[] someints = {1,2,3,4,5}
avector = std::vector<int>(someints);
return sum(avector)
したがって、合計を返すには int 戻り値が必要です。また、ベクトルを変更する可能性があるため、参照を返す必要があります。また、ローカル スタック上に変数を作成しているため、(ペアで) ベクトルを返すことは危険な場合があります。したがって、それへの参照を返すことは実際には有効ではありませんが、値で返すことはコストがかかる可能性があります (そして不必要です)。 avector が大きければヤダヤダ。Python では、両方の値を返すだけです。
def sumdefault(mylist=[]):
if len(mylist) == 0:
mylist = [1,2,3,4,5]
return mylist, sum(mylist)
alist = [2,3,4,5]
alist, sumalist = sumdefault(alist)
これは(私の知る限り)このパターンを処理するための適切な Pythonic の方法です。不必要にリストをコピーして時間を無駄にすることはありません。Python は常に参照を渡します。Python には、C と同じように「ローカル」変数のようなものは実際にはありません。サブ関数で作成された変数にはローカル名がありますが、グローバル ヒープにあるため[1,2,3,4,5]
、サブ関数で構築したとしても、そのメモリは関数を返すときに が消えることはありません。そのローカル名は消えますが、親関数にはそれを指す名前が付けられ、一部の名前がそれを参照している限り存続します。
Python の名前は、メモリ内の位置への単なる参照です。そう:
list1 = new_data
両方の変数がメモリ内の同じ位置を参照するようにするだけです。
一方、list1[:]
list1のコピーを作成します