[解決済み] 変数を参照渡しする方法を教えてください。
質問
Pythonのドキュメントでは、パラメータが参照で渡されるのか値で渡されるのかについて不明確なようで、次のコードは変更されない値「オリジナル」を生成します。
class PassByReference:
def __init__(self):
self.variable = 'Original'
self.change(self.variable)
print(self.variable)
def change(self, var):
var = 'Changed'
実際の参照で変数を渡すために何かできることはないでしょうか?
どのように解決するのですか?
引数は 代入で渡す . その根拠は2つあります。
- 渡されたパラメータは、実際には 参照 オブジェクトへの参照 (ただし、参照は値で渡される)。
- あるデータ型はミュータブルだが、他のデータ型はミュータブルでない
だから
-
を渡すと ミュータブル オブジェクトをメソッドに渡すと、メソッドはその同じオブジェクトへの参照を取得し、思う存分変異させることができます。しかし、メソッド内で参照を再バインドすると、外部スコープはそのことについて何も知らず、終了した後も外部参照は元のオブジェクトを指すことになります。
-
を渡すと 不変 オブジェクトをメソッドに渡したとしても、外部参照を再バインドすることはできませんし、オブジェクトを変異させることさえできません。
さらにわかりやすくするために、いくつかの例を挙げてみましょう。
リスト - ミュータブルな型
あるメソッドに渡されたリストを変更してみましょう。
def try_to_change_list_contents(the_list):
print('got', the_list)
the_list.append('four')
print('changed to', the_list)
outer_list = ['one', 'two', 'three']
print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)
出力します。
before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']
渡されたパラメータは
outer_list
そのため、Mutating List メソッドを使ってそれを変更し、その変更を外部スコープに反映させることができます。
では、パラメータとして渡された参照を変更しようとすると、どうなるか見てみましょう。
def try_to_change_list_reference(the_list):
print('got', the_list)
the_list = ['and', 'we', 'can', 'not', 'lie']
print('set to', the_list)
outer_list = ['we', 'like', 'proper', 'English']
print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)
出力します。
before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']
というのは
the_list
パラメータは値で渡されるため、新しいリストを代入しても、メソッドの外のコードには何の影響もありません。そのため
the_list
はコピーであった。
outer_list
のリファレンスを持っていました。
the_list
は新しいリストを指すようになりましたが
outer_list
を指します。
文字列 - 不変の型
イミュータブルなので、文字列の中身を変更することはできない
では、参照先を変更してみましょう。
def try_to_change_string_reference(the_string):
print('got', the_string)
the_string = 'In a kingdom by the sea'
print('set to', the_string)
outer_string = 'It was many and many a year ago'
print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)
出力します。
before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago
ここでも
the_string
パラメータは値で渡されるため、新しい文字列を代入してもメソッドの外のコードからは何も見えません。また
the_string
はコピーであった。
outer_string
のリファレンスを持っていました。
the_string
が新しい文字列を指していることを確認する必要があります。
outer_string
を指します。
これで少しはスッキリしたかな。
EDITです。 これは、@David が最初に尋ねた質問、"実際の参照で変数を渡すためにできることはあるか、" に対する答えになっていないことが指摘されています。それを解決しましょう。
どうすれば回避できるのか?
Andreaの回答が示すように、新しい値を返すことができます。この方法では、渡されたものを変更することはできませんが、必要な情報を取り出すことができます。
def return_a_whole_new_string(the_string):
new_string = something_to_do_with_the_old_string(the_string)
return new_string
# then you could call it like
my_string = return_a_whole_new_string(my_string)
どうしても戻り値を使いたくない場合は、値を保持するクラスを作成して関数に渡すか、リストのような既存のクラスを使用することができます。
def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
new_string = something_to_do_with_the_old_string(stuff_to_change[0])
stuff_to_change[0] = new_string
# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)
do_something_with(wrapper[0])
少し面倒な気もしますが。
関連
-
pythonを使ったオフィス自動化コード例
-
python implement mysql add delete check change サンプルコード
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】Flaskのテンプレートが見つからない【重複あり
-
[解決済み】ValueError: xとyは同じサイズでなければならない
-
[解決済み] プログラムの実行やシステムコマンドの呼び出しはどのように行うのですか?
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] 環境変数の値にアクセスする方法
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python 人工知能 人間学習 描画 機械学習モデル作成
-
python implement mysql add delete check change サンプルコード
-
パッケージングツールPyinstallerの使用と落とし穴の回避
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】Python regex AttributeError: 'NoneType' オブジェクトに 'group' 属性がない。
-
[解決済み] データ型が理解できない
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】LogisticRegression: Pythonでsklearnを使用して、未知のラベルタイプ: '連続'を使用しています。