簡単に言うと、Pythonは常に値渡しを行いますが、すべてのPython変数は実際にはオブジェクトへのポインターであるため、参照渡しのように見える場合があります。
Pythonでは、すべてのオブジェクトは可変または非可変のいずれかです。たとえば、リスト、辞書、モジュール、パンダのデータフレームは変更可能であり、int、文字列、タプルは変更できません。可変オブジェクトは内部で変更できますが(たとえば、リストに要素を追加する)、非可変オブジェクトは変更できません。
冒頭で述べたように、すべてのPython変数はオブジェクトへのポインターと考えることができます。変数を関数に渡す場合、関数内の変数(ポインター)は常に渡された変数(ポインター)のコピーです。したがって、内部変数に新しいものを割り当てる場合は、変更するだけです。別のオブジェクトを指すローカル変数。これは、変数が指している元のオブジェクトを変更(変更)したり、外部変数が新しいオブジェクトを指したりすることはありません。この時点で、外部変数は元のオブジェクトを指していますが、内部変数は新しいオブジェクトを指しています。
元のオブジェクトを変更する場合(可変データ型でのみ可能)、ローカル変数に完全に新しい値を割り当てずに、オブジェクトを変更する何かを行う必要があります。これが理由letgo()
でletgo3()
、外部アイテムは変更されないままですが、letgo2()
変更されます。
@ursanが指摘したletgo()
ように、代わりにこのようなものを使用df
すると、それが指す元のオブジェクトが変更(変更)され、グローバルa
変数を介して表示される値が変更されます。
def letgo(df):
df.drop('b', axis=1, inplace=True)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo(a)
場合によっては、実際に直接割り当てを行わなくても、元の変数を完全にくり抜いて新しいデータを再入力できます。たとえばv
、これにより、ポイントする元のオブジェクトが変更され、v
後で使用するときに表示されるデータが変更されます。
def letgo3(x):
x[:] = np.array([[3,3],[3,3]])
v = np.empty((2, 2))
letgo3(v)
x
;に直接何かを割り当てていないことに注意してください。の内部範囲全体に何かを割り当てていx
ます。
どうしても完全に新しいオブジェクトを作成して外部に表示する必要がある場合(パンダの場合もあります)、2つのオプションがあります。'clean'オプションは、新しいオブジェクトを返すだけです。
def letgo(df):
df = df.drop('b',axis=1)
return df
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
a = letgo(a)
もう1つのオプションは、関数の外部に到達して、グローバル変数を直接変更することです。これa
は新しいオブジェクトを指すように変更され、a
後で参照する関数はその新しいオブジェクトを参照します。
def letgo():
global a
a = a.drop('b',axis=1)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo()
コードを読む人は誰でもどのようa
に変更されたかを理解するのに苦労するので、グローバル変数を直接変更することは通常悪い考えです。(私は通常、スクリプト内の多くの関数で使用される共有パラメーターにグローバル変数を使用しますが、それらにそれらのグローバル変数を変更させません。)