東京大学のPythonプログラミング入門「2-2. リスト (list)」備忘録

Python勉強中で備忘録です。今回はかなり難しかったです。メソッドも色々出てきており、全然全部は覚えられていません。たぶん今後も読み返す気がします。


⇒「偶数番目のインデックスの値」というのが紛らわしい。リストの2番目、4番目、6番目を削除するのかと思ったが、インデックスの値は0から始まるので、リストで言うところの1番目、3番目、5番目。スライスは「[1::2]」のようにも記載できる。*インデックスの値0から最後まで、数字は2つ置き。

以下の通り、3案考えたがB案は正解となった。ChatGPTに解説させたら以下の通り。

<A案>
def change_domain(email, domain):
email.split(“@”)
email.replace(email[1], domain)
問題点

⇒email.split(“@”) の結果を受け取っていない(ただ呼んでいるだけ)。
email.replace(email[1], domain) は文字列の2文字目 (email[1]) を探して domain に置き換えようとするので、ドメイン部分を置き換える処理になっていない。
return がないので結果も返さない。模範解答はBをまとめた感じ。appendも不要(joinの中に組み込める)。

<B案>
def change_domain(email, domain):
email1 = email.split(“@”)
del email1[1]
email1.append(domain)
return “@”.join(email1)

<C案>
def change_domain(email, domain):
del email.split(“@”)[1]
email1.append(domain)
return “@”.join(email1)
⇒問題点
email.split(“@”) の結果を直接 del しても、そのリストは捨てられてしまうので無意味。
email1 という変数が出てくるが、定義されていないのでエラーになる。

<模範解答>
def change_domain(email, domain):
return ‘@’.join([email.split(‘@’)[0], domain])

⇒ 以下で良くない?
def sum_list(ln):
return sum(ln)

<模範解答>
def sum_list(ln):
int_sum = 0
for value in ln:
int_sum += value
return int_sum
#sum_list([10, 20, 30])

⇒これも難しい。B案は正解となったが強引。forを使っていない。模範解答難しい。具体的には、引数に対して繰り返す式を使うのではなく、文字列’ATGC’を仮に置いて、それに対して繰り返す式を使う点が難しい。ヒントはあるがこのような使い方は思いつかない。

<A案>
def atgc_countlist(str_atgc):
countlist=[]
for x in str_atgc:
countlist.append([str_atgc.count(‘x’),’x’])
return countlist

⇒ChatGPTによる解説は以下の通り。

問題点

  1. 'x' を文字列として書いてしまっている
    • str_atgc.count('x') とすると「文字 'x' の出現回数」を数えます。
    • でも本当は 変数 x(ループで回している実際の文字)を使わないといけません。
    • 正しくは str_atgc.count(x)
  2. ループ対象が間違っている
    • あなたの for x in str_atgc: は「DNA文字列そのものを1文字ずつ回す」ループです。
    • すると A, T, G, C が順番に出てくるのではなく、入力文字列の中身が順に x に入ります。
    • そのため「A, T, G, C の順番で数える」という要件を満たしていません。
    • 正しくは for bp in "ATGC": とする必要があります。
  3. 重複してカウントされてしまう
    • 例えば str_atgc = "ATGCA" の場合、あなたの方法だと
      文字列の長さ分(5回)ループするので、同じカウントを何度も追加してしまいます。

<B案>
def atgc_countlist(str_atgc):
  return [[str_atgc.count(“A”),”A”],[str_atgc.count(“T”),”T”],[str_atgc.count(“G”),”G”],[str_atgc.count(“C”),”C”]]

<模範解答>
def atgc_countlist(str_atgc): list_count = [] for value in ‘ATGC’: int_bpcnt = str_atgc.count(value) list_count.append([int_bpcnt, value]) return list_count


⇒何を言っているかよくわからない。ChatGPTにいろいろ質問したところ以下の回答。
 要は「 a=[] 」という式が一つの評価に相当し、この際に一つのリストが作られる。「 b=[] 」も一つの評価に相当し、この際に上記とは異なるリスト(アドレスが異なる)が作られる。だから、リスト(オブジェクト)としてはaとbは同一ではないということ。
 「is」はいつ使うんだろう(Trueになるのだろう)?


🔹「評価(evaluation)」の定義

「評価」とは、式(expression)を実行して、その結果(値や副作用)を得ることを指します。

  • 例:
    • 2 + 3 を評価すると 5 が得られる。
    • len([1, 2, 3]) を評価すると 3 が得られる。
  • プログラム中で式が書かれると、処理系はそれを 「評価」して値に変換します。

👉 「評価」=「式 → 値(+必要なら副作用)への変換」と覚えるとよいです。


🔹「リストオブジェクト」の定義

「リストオブジェクト」とは、複数の値(要素)を順序付きで保持するためのオブジェクトです。
(Pythonを例に説明しますが、多くの言語でも似ています)

  • Python でのリストの特徴:
    • 順序がある(インデックスでアクセスできる)
    • 可変(要素の追加・削除・変更ができる)
    • 異なる型を混在できる

例:

a = [1, "apple", 3.14]

ここで a はリストオブジェクト。

  • a[0]1
  • a[1]"apple"

🔹「新しいリストオブジェクトが作られる」とは?

これは 評価の過程で、処理系がメモリ上に新しいリストを確保する という意味です。

たとえば:

x = [1, 2, 3]
y = x + [4]   # 新しいリストオブジェクトが作られる
  • x + [4] を評価すると、[1, 2, 3, 4] という 新しいリストオブジェクト が生成される。
  • その結果を変数 y に代入。
  • x は元の [1, 2, 3] のまま。

👉 「リストを変更する」場合と「新しいリストを作る」場合は区別されます。

例:

x.append(4)   # 既存のリスト x を変更
y = x + [4]   # 新しいリストを生成して代入

✅ まとめると:

  • 評価:式を実行して値を得ること。
  • リストオブジェクト:順序付きで要素を保持できるデータ構造。
  • 新しいリストオブジェクトが作られる:式を評価した結果として、既存のリストとは別に新しいリストがメモリに確保されること。

✅ 新しいリストが作られるケース

a = [1, 2, 3]
b = a + [4]        # 新しいリストが作られる
c = a[1:3]         # スライスも新しいリストを返す
d = list(a)        # 明示的にコピー、新しいオブジェクト
id(a) != id(b)
id(a) != id(c)
id(a) != id(d)

→ これらはすべて 別オブジェクト


❌ 元のリストを直接変更するケース

a = [1, 2, 3]
a.append(4)        # a 自身が変更される、返り値は None
a.extend([5, 6])   # a 自身が変更される、返り値は None
a.sort()           # a 自身が変更される、返り値は None

→ これらは 新しいリストは作られない

a = []
b = []

print(a == b)   # True (内容は等しい)
print(a is b)   # False(同一オブジェクトではない)

print(id(a))    # 例: 140356894135232
print(id(b))    # 例: 140356894135168 (違うアドレス)

<今回の理解内容>
・タプルは変更できないデータの要素。1つしかない場合は、以下のように記載。
 onlyone = (1,)
・x, y = y, xで2つの変数に格納された値の入れ替えを行える。

コメント

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