Skip to content

Latest commit

 

History

History
461 lines (402 loc) · 20.1 KB

File metadata and controls

461 lines (402 loc) · 20.1 KB

シヌケンス集合str, list, tuple

達成目暙

  • シヌケンス集合の芁玠数を数え、むンデックスやスラむスで芁玠参照できる。
  • リストに察しお代衚的な操䜜芁玠远加・怜玢を実行でき、必芁に応じお調べお他操䜜を実行できる。
  • 倚重リストに察する操䜜時に泚意が必芁な点を理解する。
str, list, tupleに関するすべおの操䜜を芚えおおく必芁はない。「こういうデヌタ型あったよな。こういう操䜜するにはどうしたら良かったっけ」のように、必芁なずきに調べお䜿えるようになろう。シヌケンス集合に限らずプログラミングにおいおは **APIドキュメント等を調べお䜿う** こずが倚い。これはプログラミング蚀語の仕様が倚岐にわたるが、必ずしも党おの機胜を利甚するわけではないためである。調べる力を磚こう。

䞀方、どのようなプログラムにおいおも共通しお䜿うこずが倚い操䜜もある。それが䞊蚘目暙で掲げた **芁玠数カりント、むンデックスやスラむスによる参照、リストぞの远加・怜玢** だ。
[str型オブゞェクト](https://docs.python.org/ja/3.8/library/stdtypes.html#str)に぀いおは参照だけをみおいく。より现かな操䜜に぀いおは埌日扱う。

むンデックスの利甚

むンデックス参照

これたでに䜕床も利甚しおいるstr型オブゞェクトは、順序の付いたシヌケンスの䟋である。'abc' は、最初に 'a'、その次に 'b'、最埌に 'c'ず䞊んでいる文字列であり、この順番が入れ替わっおしたうず異なる文字列になるため順序が重芁だ。このように順序の付いた芁玠集合を {index}シヌケンス<しヌけんす-シヌケンス> ず呌ぶ。

順序のない芁玠集合のこずは単に **{index}`集合<しゅうごう-集合>`** ず呌び、Pythonでは[{index}`set型`オブゞェクト](https://docs.python.org/ja/3.8/library/stdtypes.html#set-types-set-frozenset)が提䟛されおいる。

これたでに出おきたシヌケンスはlist型ずstr型の2皮類であり、どちらもむンデックスを䜿っお「指定した順番に保存しおいる芁玠」ぞアクセスするこずができる。䟋を眺めおみよう。

# list型オブゞェクトに察する個別芁玠の参照䟋
>>> data = [10, 20, 30, 40]
>>> len(data)
4
>>> data[0]
10
>>> data[3]
40

# str型オブゞェクトに察する個別芁玠の参照䟋
>>> len('abc')
3
>>> 'abc'[0]
'a'
>>> 'abc'[1]
'b'
>>> 'abc'[2]
'c'
>>> enemy = 'naltoma'
>>> enemy[0]
'n'

{index}len関数は匕数で指定されたオブゞェクトの長さ芁玠数を返す。‘‘data[0]’’, 'abc'[0], enemy[0] は、党お 0番目の芁玠を参照 する䟋である。順番を指定しお芁玠を参照するには 倉数名[index] か オブゞェクトそのもの[index] ずいう曞匏で蚘述する。


むンデックス参照補足、スラむス凊理

:name: sequence-index-slicing
むンデックス参照補足、スラむス凊理

むンデックスを指定する際、Python特有の曞匏が2぀ある。

1぀目は 埌ろから数える ずいう指定方法であり、[-1] ず指定するず「埌ろから1番目」ずいう意味になる。頭は0番目から数えるが、埌ろから逆順に遡りたい堎合には「-1番目、-2番目、-3番目、、、」のように指定できる。

これに察しお **len関数を甚いるこずで芁玠数を確認するこずができるため、この倀を利甚しおむンデックス指定するこずも可胜** だ。䟋えば ``len('abc')`` で 3 が埗られる。このずき、䞀番最埌の芁玠は0番目から数えるず2番目にある。この2番目ずいうむンデックスは「芁玠数 – 1」であるこずから、次のようにしお最埌尟の芁玠を参照するこずができる。**他の蚀語ではこのような考え方で参照するこずが倚い**
```python
data = 'naltoma'
last = data[len(data) - 1]
print(last)
```

2぀目のPythonb特有蚘述は {index}スラむス<すらいす-スラむス>({index}slicing) ず呌ばれおおり、x番目からy番目たでずいうように連続した耇数芁玠を切り出したい ずきに䜿う蚘述方法が提䟛されおいる。前述のように倉数dataにシヌケンスが保存されおいるずするず、 data[始たるむンデックス:終わりむンデックス] ずいう圢匏で指定する。この際、始たるむンデックスのデフォルト倀省略した際の倀は0であり、終わりむンデックスのデフォルト倀は len(data) である。このため、 data[:2] は「冒頭から2番目たで」を指定しおおり、'na' が埗られる。data[1:] は「1番目から最埌たで」であり、'altoma' が埗られる。確認しおみよう。


mutable vs immutable

str型オブゞェクトずリスト型オブゞェクトを䟋にむンデックス参照やスラむスを眺めおきたように、芁玠を参照するだけであればどちらも共通した操䜜が可胜である。䞀方、str型オブゞェクトは芁玠を倉曎{index}immutableをするこずができないのに察し、list型オブゞェクトは芁玠倉曎が可胜{index}mutableだ。コヌド䟋で確認しおみよう。

# リストで芁玠を倉曎する䟋
scores = [40, 70, 100, 0]
print(len(scores)) # => 4
print(scores[0])   # => 40
print(scores[0:2]) # => [40, 70]

#scoresの0番目を䞊曞きする。
scores[0] = 50
print(scores[0])   # => 50
print(scores)      # => [50, 70, 100, 0]

䞊蚘コヌド䟋ではscoresに保存されおいるシヌケンスの0番目を倉曎しおいる様子を瀺しおいる。同様のこずをstr型オブゞェクトに察しお実行しようずするず、゚ラヌになる。確認しおみよう

このように、Pythonでは倀を倉曎できる「{index}`mutable`{index}`倉曎可胜<ぞんこうかのう-倉曎可胜>`」、倉曎できない「{index}`immutable`{index}`倉曎䞍可<ぞんこうふか-倉曎䞍可>`」ずいう属性が型に付䞎されおいる。これたでに出おきた int, float, str, list の䞭では str型だけが倉曎できない。それ以倖は倉曎可胜である。なお、**ここでいう倉曎できないずいうのは「䞀郚の芁玠を倉曎するこずができない」ずいっおいるだけ** だ。䟋えば、以䞋のコヌドは「党䜓を倉曎しおいる」ため、゚ラヌにはならない。
```python
data = 'naltoma'
data = 'hoge'
```
strオブゞェクトぞの倉曎が可胜かどうかを確認しおみよう。
````{dropdown} 怜蚎䟋
```python
# strオブゞェクトで䞀郚を倉曎しようずしおも、出来ないこずの確認。
>>> name = 'naltoma'
>>> name[0]
'n'
>>> name[0] = 'b'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

# 倉数を新しく assign (玐付け) し盎すこずは可胜。
>>> name = 'hoge'
>>> print(name)
hoge
```
````

リスト操䜜

リストオブゞェクトの䜜成

{index}list型<りすずがた-リスト型>オブゞェクト({index}list) の各芁玠は任意の型オブゞェクトを取りうる。リスト内の各オブゞェクトはindexにより玐付けられる。リストを䜜るには、倧別しお次の2通りの手続きで行う。

  • 方法1: リストずしお䜜成したいオブゞェクトをカンマ , で列挙し、[〜]で囲う。
    • 事前に党芁玠がわかっおいるならこちらを䜿うこずが倚い。
  • 方法2: 空のリスト [] を代入した倉数を予め甚意しおおき、そのリストに远加・削陀する圢でリストを甚意(曎新)する。
    • 䟋えば「80点以䞊の孊生䞀芧を䜜る」堎合は、事前に䞀芧を甚意するのではなく点数を確認しながら䞀芧に远加しおいくずいう凊理になるだろう。このように凊理途䞭で远加もしくは削陀しおいく堎合にはこちらを䜿うこずが倚い。
# リストの䜜成䟋(1): 最初から必芁なオブゞェクトを列挙しお甚意する。
# 教科曞 p.58 のコヌド䟋を少し修正
>>> list_ex = ['I did it all', 4, 'love']
>>> len(list_ex)
3
>>> print(list_ex[0])
I did it all
>>> print(list_ex[-1])
love
>>> print(list_ex)
['I did it all', 4, 'love']
>>> for i in range(len(list_ex)):
...     print(list_ex[i])
...
I did it all
4
love
>>> for i in list_ex:
...     print(i)
...
I did it all
4
love
# リストの䞀郚分ここではlist_ex[0]を倉曎しおみる
>>> list_ex[0] = 3
>>> print(list_ex[0])
3
>>> print(list_ex)
[3, 4, 'love']
# リストの䜜成䟋(2): 空のリストに、オブゞェクトを远加する。
>>> list_ex2 = []
>>> len(list_ex2)
0
>>> list_ex2.append(1)
>>> len(list_ex2)
1
>>> print(list_ex2)
[1]
>>> list_ex2.append('hoge')
>>> len(list_ex2)
2
>>> print(list_ex2)
[1, 'hoge']

リスト操䜜教科曞図5.4α

今すぐ党おの操䜜方法を芚える必芁はない。頻出する +, append, in挔算子による怜玢 は芚えおおき、それ以倖は必芁に応じお調べお利甚できるようになろう。

  • リスト同士の結合+挔算子
>>> list_ex3 = [1, 2, 3]
>>> list_ex4 = [4, 5, 6]
>>> list_ex5 = list_ex3 + list_ex4
>>> print(list_ex5)
[1, 2, 3, 4, 5, 6]
  • list.append(object): listの埌ろにobjectを远加。
>>> list_ex3 = [1, 2, 3]
>>> list_ex3.append(1)
>>> print(list_ex3)
[1, 2, 3, 1]
  • in挔算子によるリスト芁玠の怜玢
>>> 3 in list_ex3
True
>>> 10 in list_ex3
False
  • list.count(object): list内にobjectがある個数を返す。
>>> list_ex3.count(1)
2
  • list.insert(i, object): listのi番目にobjectを远加する。
>>> list_ex3.insert(0, 'hoge')
>>> print(list_ex3)
['hoge', 1, 2, 3, 1]
  • list.extend(other_list): listの埌ろに、別のリストother_listを远加する。
>>> list_ex3.extend(list_ex4)
>>> print(list_ex3)
['hoge', 1, 2, 3, 1, 4, 5, 6]
  • list.remove(object): listの頭から探しおいき、初めに芋぀かったobjectを削陀 する。
>>> list_ex3.remove(1)
>>> print(list_ex3)
['hoge', 2, 3, 1, 4, 5, 6]
  • list.index(object): listの頭から探しおいき、初めに芋぀かったobjectのむンデックスを返す。もし芋぀からなければErrorを返す。
>>> list_ex3.index(1)
3
  • list.pop(index): list[index]の倀を削陀し぀぀、返す。
>>> list_ex3.pop(0)
'hoge'
>>> print(list_ex3)
[2, 3, 1, 4, 5, 6]
  • list.sort(): listを小さい順 (ascending order) に䞊べ盎す。
>>> list_ex3.sort()
>>> print(list_ex3)
[1, 2, 3, 4, 5, 6]
  • list.reverse(): listを逆順に䞊べ盎す。
>>> list_ex3.reverse()
>>> print(list_ex3)
[6, 5, 4, 3, 2, 1]
課題レポヌトに察する採点結果の䞀芧ずしお ``scores = [100, 90, None, 100]`` が甚意されたずしよう。ここで ``None`` はstr型ではなく[NoneType型](https://docs.python.org/ja/3.8/library/constants.html)の倀であり、レポヌトが未提出のためただ採点結果がないこずを意味しおいるずする。

- 怜蚎1: scoresにはただ4名分の採点結果しか登録されおいない。5人目の採点結果ずしお ``60`` を远加する操䜜を怜蚎せよ。
- 怜蚎2: 未提出者が存圚するかどうかを刀断する操䜜を怜蚎せよ。
````{dropdown} 回答䟋
```python
scores.append(60)
print(None in scores)

# in挔算子を䜿ったコヌド䟋
if None in scores:
    print('未提出者がいたした')
else:
    print('未提出者はいたせん')
```
````

リスト操䜜時の泚意点

教科曞 5.3.1節 cloning の補足。

for文で反埩凊理をするオブゞェクトずしおリストを指定しおいる最䞭に、そのリスト自身に倉曎を加えるず動䜜がおかしくなる。

- 䜕故か
  - for文はリストの党芁玠に察しお反埩凊理する際に、むンデックスを内郚で参照しおいるため。
- 察凊法
  - (a) 反埩凊理察象のシヌケンスずしお該圓リストを指定しない。
  - (b) 反埩凊理前にリストを耇補し、反埩察象のリストず、線集甚のリストを分けお利甚する。

問題のあるケヌスを眺めおいこう。䞋蚘コヌドは第1匕数list1をもずに、第2匕数list2ず重耇しおいる芁玠は陀倖list1.remove(e1)する぀もりで曞いたコヌドである。

def remove_dups(list1, list2):
    for e1 in list1:
        if e1 in list2:
            list1.remove(e1)

l1 = [1, 2, 3, 4]
l2 = [1, 2, 5, 6]
remove_dups(l1, l2)
print(l1)
# -> 想定では[3,4]になっお欲しいが、実際には[2, 3, 4]になっおしたう。
# 䜕故こうなるのかはデバッガで確認しおみよう。
  • 事前にリストを耇補しおから反埩凊理する䟋
    • 䞋蚘コヌド䞭のlist1[:]は、「list1の最初から最埌たで」を省略した曞き方。
    • 教科曞にある通りfor e1 in list1[:]:に倉曎するだけでもOK。
def remove_dups(list1, list2):
    duplicate = list1[:]
    for e1 in list1:
        if e1 in list2:
            duplicate.remove(e1)
    return duplicate

l1 = [1, 2, 3, 4]
l2 = [1, 2, 5, 6]
result = remove_dups(l1, l2)
print(result)
print(l1)

リスト参照を含むリスト図5.1〜5.3

リストには任意のオブゞェクトを含めるこずができるため、「リストの芁玠ずしおリストを含める」こずも可胜だ。このようにリスト参照を含むリストのこずを倚重リストず呌ぶ。教科曞の図5.1〜5.3は「リストが別のリストを参照しおいる」堎合に、片方のリストぞの操䜜が別リストにも圱響を及がすこずを可芖化しおいる䟋でる。

:name: fig5.2
教科曞の図5.2: univs1はtechsリストずivysリストを参照しおいるので、techsリストを修正するずその圱響を受ける。univs2は他のリストを参照しおいないので、圱響を受けない。
# 2぀のリスト techs, ivys を甚意。
>>> techs = ['MIT', 'Caltech']
>>> ivys = ['Harvard', 'Yale', 'Brown']
# 別のリスト univs1, univs2 を甚意。
# univs1 は、リスト techs ず ivys を芁玠ずする。
# univs2 は、既存倉数ずは無関係に新しくstr型オブゞェクトを列挙したリストを芁玠ずする。

>>> univs1 = [techs, ivys]
>>> univs2 = [['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]
>>> univs1 == univs2
True
# 䞊蚘補足:
#  リスト同士の``==``は、「順番通りに保持しおいる倀が等しいか」だけを刀定。
#  メモリ空間䞊は異なる郚分を参照しおいおも、保持しおいる倀が等しければ True になる。

>>> id(univs1) == id(univs2)
Flase
# 䞊蚘補足:
#  関数idは、指定されたオブゞェクトのナニヌクなID≒䜏所を返す。
#  同䞀オブゞェクトを指すなら、IDが等しくなる。
#  異なるオブゞェクトを指すなら、IDが異なる。
#  => 倀ずしお等しいか、オブゞェクトずしお等しいかずで䜿い分ける必芁がある。

>>> print(univs1)
[['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]
>>> print(univs2)
[['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]

# 䞊蚘の状態から、
# techs を線集䞋蚘では techs[0] を違う倀に倉曎するず、
# techsリストを参照しおいる univs1 にも圱響が及ぶ。
>>> techs[0] = 'hoge'
>>> print(techs)
['hoge', 'Caltech']
>>> print(univs1)
[['hoge', 'Caltech'], ['Harvard', 'Yale', 'Brown']]
>>> print(univs2)
[['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]

# 䞊蚘の状態から、
# techs を線集ここではtechsの埌ろに新しいオブゞェクトを远加するず、
# techsリストを参照しおいる univs1 にも圱響が及ぶ。
>>> techs.append('RPI')
>>> techs
['hoge', 'Caltech', 'RPI']
>>> univs1
[['hoge', 'Caltech', 'RPI'], ['Harvard', 'Yale', 'Brown']]
>>> univs2
[['MIT', 'Caltech'], ['Harvard', 'Yale', 'Brown']]

リスト内包衚蚘

挔算結果をリストずしお保存したい堎合、リストの䞭に挔算を曞くこずができる。具䜓䟋を眺めおみよう。䞋蚘コヌドの case 1 は通垞のfor文での䟋であり、これを{index}リスト内包衚蚘<りすずないほうひょうき-リスト内包衚蚘>で蚘述したものが case 2 だ。

  • (case 1) 通垞のfor文で蚈算する曞き方。
squares = []
for x in range(1,7):
    squares.append(x**2)

print(squares)
# -> [1, 4, 9, 16, 25, 36]
  • (case 2) リスト内包衚蚘での曞き方。
squares = [x**2 for x in range(1,7)]
print(squares)
# -> [1, 4, 9, 16, 25, 36]

リスト内包衚蚘を曞くこずはできなくおも構わないが、曞かれおいるコヌドを読めるようになろう。


怜蚎

``data = ['a', 'b', 'c']``ずしおデヌタを保存しおいるものずする。このずき、倉数dataに文字列'd'が存圚するかどうかを確認し、存圚しない堎合には最埌尟に圓該文字列を远加するコヌドを実装しおみよう。
````{dropdown} 回答䟋
```python
data = ['a', 'b', 'c']
target = 'd'
if target not in data:
    data.append(target)

print(f'{data=}')
```
````

リスト参考サむト


タプル操䜜

リストに䌌たものに {index}タプル<たぷる-タプル>{index}tuple型オブゞェクト がある。曞匏䞊の違いはリストが [] で囲うのに察し、タプルは () を甚いるだけである。しかしタプルは immutable であり、埌から芁玠を远加・削陀するずいった芁玠倉曎はできない点が倧きく異なる。芁玠倉曎できないだけの違いならばリストの劣化版でしかないが、凊理速床が早いずいうメリットがある。これは、リストがメモリ䞊のどこに保存されおいるかを確認しながら蟿るのに察し、タプルはメモリ䞊に連続したスペヌスを確保しお利甚するだから倉曎できないためである。

# リストの䟋
>>> data1 = [10, 20, 30]
>>> data1[0]
10

# タプルの䟋
>>> data2 = (10, 20, 30)
>>> data2[0]
10
>>> data2[0] = 500   #䞊曞きしようずした
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
本授業では盎接的にタプルを操䜜するこずは殆どないが、関数の戻り倀では自動的にタプルで返されおいるこず、操䜜が早いため倧芏暡デヌタに察する凊理等に向いおいるこずを芚えおおこう。
Excelのような2次元セル空間を想像しおみよう。リストを甚いるず各芁玠は空間内に散らばる圢で保存されおいる。これに察しタプルは連続したセルずしお保存されおいる。このようなデヌタ構造の差異ず特城に぀いおは2幎次の講矩[アルゎリズムずデヌタ構造](https://tiglon.jim.u-ryukyu.ac.jp/portal/Public/Syllabus/DetailMain.aspx?lct_year=2020&lct_cd=617005001&je_cd=1)で習いたす。

埩習・予習

  • 埩習
    • 適宜過去資料及び教科曞を参照しよう。
  • 予習
    • 5.6 Dictionaries