Youtubeでも活動中

チャンネル登録してくれたら喜びます。
リンクはフリーです。共有・拡散は大歓迎!

このボタンで簡単にチャンネル登録!
PR

PythonのListの中身が勝手に変わる??【対策方法もご紹介】

python-List-change

pythonをやっていて、Listを扱うときに注意しないといけないことがあります。

それが、意図しないListの要素の変更です。

Listに要素が入っていて、それをみなさん使うわけですが、

たまに意図せず値を変えてしまうことがあります。

また、この内容は意外と変わっていても見過ごされてしまうパターンがあります。

Listを使っていて、勝手に変更されてしまうこともある。

ということを知識として持っておくだけでも意味があります。

というわけで実例と対策方法をまとめてご紹介していきます。

この記事を読むことでわかること

自己紹介

東証一部上場企業でサラリーマンしてます。

主に工場(生産現場)で使用する検査装置のアプリケーション開発してます。

ヒトの作業を自動化して簡略化するアプリケーションを日々開発中。

2022年5月に転職。現役バリバリの技術者です。
現在は超大手企業の新規事業分野で装置の研究・開発をしています。

Youtubeチャンネルにさまざまな動画を上げています

↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓

今回は実例と対策方法について章を分けてご紹介していきます。

↓↓↓↓これまでのPythonの記事についてはこちら↓↓↓↓

pythonのListの要素が意図せず変わる現象

基本的に気をつけないといけないのは、Listをコピーするときです。

Listをコピーしたときは要注意!!

では実際に要素が勝手に変わってしまう実例をご紹介します。

# 試験的に用意した配列。意味はない。
testPoint=[55,52,23]
# いったんListの内容を新しいListにコピーする。
testPointCopy=testPoint
# Listの要素を変更しているのはコピーのほう。
testPointCopy[2]=0
print(testPointCopy)
print(testPoint)

さて、このソースを実行してみるとどうなるでしょうか?

予想してみてください。

何も知らない人だと、

testPointCopyに一回コピー、その後コピーしたListの要素を変更しているように見えますね。

それでは正解発表です。

[55, 52, 0]
[55, 52, 0]

どうでしょう?違和感を感じますかね。

変更しているListはtestPointCopyなのに、

testPointのほうまで変更されてしまっています。

これが要素が意図せず変わる現象です。

いったん新しいListに格納しなおすなんてのは、

別におかしなことでもないですし、文法的にやってはいけないことでもありません。

当然エラーも出ませんし。

一部Listをコピーするだけなら問題ない。

Listのコピーで意図せずに要素が変わる現象ですが、

それでは一部分のみコピーした場合はどうでしょうか?

ためしにこんな感じで一部分をコピーしてみます。

# 試験的に用意した配列。意味はない。
testPoint=[55,52,23]
# いったんListの内容を新しいListにコピーする。
testPointCopy2=testPoint[0:2]
# Listの要素を変更しているのはコピーのほう。
testPointCopy2[1]=0
print(testPointCopy2)
print(testPoint)

List丸ごとコピーしていた時と異なるのは、

testPointCopy2=testPoint[0:2]

この行ですね。

この行の右辺では、[0:2]と指定することで、

testPointのList内の0番以上2番未満の要素を指定しています。

つまり今回の例で行くと、[55,52]をコピーしていることになります。

それでは気になる出力結果ですが、

[55, 0]
[55, 52, 23]

このようになります。

そう。部分的なコピーをする場合は、コピー後のListの要素を変更しても、

コピー元のListの要素は変更されません。

ちょっと安心しますよね。実はこの部分コピーは対策に使えます。

具体的な対策方法については後述します。

Listの要素が意図せず変わるのを防ぐ方法【3つ】

今回は3つ対策方法についてご紹介します。

そもそもListの全コピーをしない。

え。そんなことか。

と思いがちですが、結構効果があります。

そもそもListを全部コピーする必要があるのは、

Listの名前変更をしたいくらいだと思います。

不用意にListを全部コピーをしないように気を付けるだけで、

防ぐことが可能です。一部、クラスに格納し直したり、ちょっと複雑なことをし始めると

名前変更だけの用途ではないですが、

とりあえずは不必要なところでListを全部コピーしないように気をつけましょう。

部分コピーをすべての要素に適用させる。

部分コピーなのに、すべての要素ってなんだよ。

って話ですよね。

実は、Listの要素の指定方法に:(コロン)を使用するのは説明しましたが、

要素すべてを指定するのに、:(コロン)単体を使用することで

すべての要素を指定することができます。

なので、このようにするとコピー元のListの要素は変更されません。

# 試験的に用意した配列。意味はない。
testPoint=[55,52,23]
# いったんListの内容を新しいListにコピーする。
testPointCopy3=testPoint[:]
# Listの要素を変更しているのはコピーのほう。
testPointCopy3[1]=0
print(testPointCopy3)
print(testPoint)

出力結果としては以下のようになります。

[55, 0, 23]
[55, 52, 23]

意図通りの変更になっていますね。

コピー元のListの要素は変わっていません。

コピーではなく新しくつくる。

Listの全コピーは1行で済むのでラクチンなのですが、

こんな方法もあります。

それが新しくListを生成してしまう方法です。

具体的にはこんな感じです。

# 試験的に用意した配列。意味はない。
testPoint=[55,52,23]
testPoint4=[]
# Listの内容を新しいListに格納する。
for points in testPoint:
    testPoint4.append(points)
# Listの要素を変更しているのはコピーのほう。
testPoint4[1]=0
print(testPoint4)
print(testPoint)

出力結果はこうなります。

[55, 0, 23]
[55, 52, 23]

記述する行数が増えるのであまりオススメではないですが、

こういうことで回避することも可能だよ。というお話です。

今回のまとめ

今回はListの要素が意図せず変わってしまうお話です。

知らないうちに要素が変わってしまっているとなかなか怖いですよね。

実際全コピーを頻繁にするわけではないですが、

この話を知っているのと、知らないのとでは結構差があります。

しかもたちが悪いのが、知らないうちに変化しているところですよね…

エラーなんかになってくれればむしろわかりやすいんですが…

この現象を利用して何か有用なものが作れるんでしょうかね。

ちょっと謎です。

コメント

タイトルとURLをコピーしました