質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

959閲覧

NumPyでない配列(リスト)とNumPyの配列のコピー方法

SomeoneHello

総合スコア5

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/11/03 12:45

編集2021/11/03 12:48

質問1
NumPyでない配列(リスト)を複製する場合に単純な代入では

python

1list1 = ['A', 'B', 'C'] 2 3list2 = list1 4list2[0] = '1' 5 6print(list1) 7# ['1', 'B', 'C'] 8 9print(list2) 10# ['1', 'B', 'C']

このように、コピー先を書き換えるとコピー元にも影響してしまいます。これは、NumPyの配列でも同じでしょうか?

質問2
この対策として、NumPyでない配列(リスト)の場合は

python

1a = [1] 2b = a.copy() 3

このような方法があるのですが、この対策はNumPyの配列でも通用しますか?

質問3

python

1   spectrogram = np.zeros((num_frames, int(fft_size/2)+1)) 2 3 for frame_idx in range(num_frames): 4 # 分析の開始位置は,フレーム番号(0始まり)*フレームシフト 5 start_index = frame_idx * frame_shift 6 7 # 1フレーム分の波形を抽出 8 frame = waveform[start_index : \ 9 start_index + frame_size].copy()#------------------------1 10 11 # ハミング窓を掛ける 12 frame = frame * np.hamming(frame_size) 13 14 # 高速フーリエ変換(FFT)を実行 15 spectrum = np.fft.fft(frame, n=fft_size) 16 17 # 振幅スペクトルを得る 18 absolute = np.abs(spectrum) 19 20 # 振幅スペクトルは左右対称なので,左半分までのみを用いる 21 absolute = absolute[:int(fft_size/2) + 1] 22 23 # 対数を取り、対数振幅スペクトルを計算 24 log_absolute = np.log(absolute + 1E-7) 25 26 # 計算結果をスペクトログラムに格納 27 # 数字のところをコロンにするとその軸全部とってくる 28 spectrogram[frame_idx, :] = log_absolute#---------------------------------2

1では
frame = waveform[start_index : start_index + frame_size].copy() と書かれており、配列をちゃんとコピーしている。

一方で、2では
spectrogram[frame_idx, :] = log_absolute と書かれており、log_absoluteが配列であるにもかかわらずそのまま代入している。
これでは、for文で繰り返す中で、1つ前の繰り返しによって代入されたspectrogramの行が、今の繰り返しの代入によって同じ値になってしまわないのでしょうか?
繰り返し1回目:
(1,2,3,4) ←代入された

繰り返し2回目:
(5,6,7,8) ←ここも同時に書き換えられないのか?
(5,6,7,8) ←代入された

繰り返し3回目:
(1,3,5,7) ←ここも同時に書き換えられないのか?
(1,3,5,7) ←ここも同時に書き換えられないのか?
(1,3,5,7) ←代入された

.
.
.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

  • 質問1 コピー先を書き換えるとコピー元にも影響してしまいます。

違います。 list1という変数の値であるオブジェクトを変数list2に代入しただけです。
同じことですが、list1が束縛しているオブジェクトにlist2を束縛しただけです。

  • NumPyの配列でも同じでしょうか?

ミュータブルなオブジェクトでは常にそうなります。

  • 質問2 この対策はNumPyの配列でも通用しますか?

はい。

  • 質問3 今の繰り返しの代入によって同じ値になってしまわないのでしょうか?

spectrogram[frame_idx, :] = log_absolute は、変数への代入ではなくndarrayのスライスへの代入ですので、そのようなことは起こりません。

コメントへの追加回答

  • スライスへの代入ではなぜ起こらないのでしょうか?

そういうように、Pythonの文法で決めているからです
詳細を知りたければ、公式ドキュメント 言語リファレンス 7.2. 代入文 (assignment statement)の「ターゲットが変更可能なオブジェクト (属性参照、添字表記、またはスライス) の一部である場合」に続く部分をお読みください。

例で理解したいなら、以下を実行してみて下さい。

Python

1>>> list1 = ['A', 'B', 'C'] 2>>> list2 = ['1', '2'] 3>>> list1[1:] = list2 4>>> print(list1) 5['A', '1', '2'] 6>>> list2[0] = 'abc' 7>>> print(list1) 8['A', '1', '2']

投稿2021/11/03 13:10

編集2021/11/03 14:24
ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SomeoneHello

2021/11/03 13:27

スライスへの代入ではなぜ起こらないのでしょうか?
ppaul

2021/11/03 14:46

回答に追加したのでそちらをお読みください。
lehshell

2021/11/03 15:17

誤解されそうな気がします。 list1 = ['A', 'B', 'C'] list2 = [[1, 2], [3, 4]] list1[1:] = list2 print(list1) # ['A', [1, 2], [3, 4]] list2[0][0] = 'abc' print(list1) # ['A', ['abc', 2], [3, 4]] ということはありますのでお気を付けください。
SomeoneHello

2021/11/03 17:56

これはコピー元であるlist2を変えるとコピー先であるlist1まで変わるという意味ですよね? だとしたら質問3の spectrogram[frame_idx, :] = log_absolute の部分に似た状況だと思うのですが、質問3の状況ではなぜ、コピー元(log_absolute)を変えてもコピー先が変わらないのでしょうか?
ppaul

2021/11/03 20:33

SomeoneHelloさん、 今回の状況は、lehshellさんの書かれた方ではなっく、私が回答に追加した方と同じ状況だからです。 その違いは、 https://docs.python.org/ja/3/reference/simple_stmts.html#assignment-statements の説明にある「代入はターゲット (リスト) の形式に従って再帰的に行われます。」を理解すれば分かります。 これから数日多忙で、次にアクセスできるのは来週になると思います。 そのときでよければもう少し説明します。
bsdfan

2021/11/04 09:05 編集

(削除)
SomeoneHello

2021/11/09 13:58 編集

ppaulさん ppaulさんが回答に追加したものの状況とlehshellさんの状況は、配列の次元以外は同じだと思うのですが、配列の次元によって変わってくるということでしょうか?説明していただけると助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問