IDLEでPython3：シーケンス型編


　ここでは，Python3におけるシーケンス型，すなわちリスト，タプル，レンジ，バイナリシーケンス，文字列の扱いについてまとめていきます．よろしくお願いいたします．

　Pythonドキュメントの「[ドキュメント » Python 標準ライブラリ » 組み込み型][pydoc]」を参考にしています．リンクのページは日本語で見れますので，より詳しい情報が知りたい方はそちらをご確認ください．

### 目次

* [シーケンス型](#シーケンス型とは)
* [基本の演算](#基本の演算)
* [リスト](#リスト)
* [タプル](#タプル)
* [レンジ](#レンジ)
* [文字列](#文字列)
    * [生成](#文字列の生成)
    * [操作](#文字列の操作)
        * [整形・変換](#整形変換)
        * [検索・置換](#検索置換)
        * [分割・結合](#分割結合)
        * [判定](#判定)
    * [フォーマット](#フォーマット)
* [参考資料](#参考資料)

# シーケンス型とは
　リスト，文字列のような順番を持った複数データを扱う型で，Pythonではリスト，タプル，レンジ，バイナリシーケンス，文字列などがあります．バイナリシーケンスは別記事で扱い，ここでは他の４つについて扱います．

```python
>>> type([1,2,3]), type((1,2,3)), type(range(1,4))
(<class'list'>, <class'tuple'>, <class'range'>)
>>> type("123"), type('123')
(<class'str'>, <class'str'>)

>>> def f(a):
	for i in a:
		print(i, end=',') # カンマ区切りで出力
>>> f((1,2,3))
1,2,3,
>>> f([1,2,3])
1,2,3,
>>> f('123')
1,2,3,
>>> f(range(1,4))
1,2,3,
```

# 基本の演算
　シーケンス型にはミュータブル(可変)なものとイミュータブル(不変)なものがあります．ミュータブルな方は`s[i] = x`によって要素を変更でき，自由に長さも変えられます．イミュータブルな方はハッシュ値を求められ，辞書型のキーとして使うことができます．

　次はこれらに共通の演算です．

|演算|結果|例|
|:--:|:--:|:---|
|x in s|xがsに入っている|'or' in 'Hello, World!' = True|
|x not in s|xがsに入っていない|'and' not in 'Hello, World!' = True|
|s + t|sとtを結合|[1,2,3] + [4,5,6] = [1,2,3,4,5,6]|
|s * n|sをn回繰り返す|3 * 'spin ' = 'spin spin spin '|
|s[i]|sの(i+1)番目の要素(0が最初)|'apple'[3] = 'l'|
|s[i:j]|sのiからjの手前までの部分をスライス|(1,2,3,4,5)[2:4] = (3,4)|
|s[i:j:k]|sのiからjまでkごとのスライス|(1,2,3,4,5,6,7,8,9)[2::2] = (3, 5, 7, 9)|
|len(s)|sの長さ|len(range(0, 10, 3)) = 4|
|min(s)|sの最小の要素|min('hello') = 'e'|
|max(s)|sの最大の要素|max('hello') = 'o'|
|s.index(x[, i[, j]])|s[i,j]で最初にxが出る位置|'apple'.index[p] = 1|
|s.count(x)|s内のxの個数|'apple'.count('a')|

　次はミュータブルなシーケンス型のみの演算です．

|演算|結果|
|:--:|:--:|
|s[i] = x|sのi+1番目の要素をxと入れ替え|
|s[i:j] = t|スライスs[i:j]をtで入れ替え|
|del s[i:j]|s[i:j]を削除|
|s[i:j:k] = t|スライスs[i:j:k]をtで入れ替え|
|s.append(x)|sの最後にxを追加|
|s.clear()|sからすべての要素を削除|
|s.copy()|コピー(s[:]に同じ)|
|s.extend(t)|s+=t．sの末尾にtを追加|
|s.insert(i, x)|s[i]の直後にxを挿入|
|s.pop(), s.pop(i)|s[i]または末尾の要素を取り出して出力|
|s.remove(x)|s内の最初のxを取り除く|
|s.reverse()|sを逆順にする|

例

```python
>>> a = list(range(10)) # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[2] = 'a' # a = [0, 1, 'a', 3, 4, 5, 6, 7, 8, 9]
>>> a[2:4] = 'b' # a = [0, 1, 'b', 4, 5, 6, 7, 8, 9]
>>> del a[4:9] # a = [0, 1, 'b', 4]
>>> a.append(list(range(6))) # a = [0, 1, 'b', 4, [0, 1, 2, 3, 4, 5]]
>>> a += a.pop() # a = [0, 1, 'b', 4, 0, 1, 2, 3, 4, 5]
>>> a[0:len(a):2] = 'cdefg' # a = ['c', 1, 'd', 4, 'e', 1, 'f', 3, 'g', 5]
>>> a.reverse() # a = [5, 'g', 3, 'f', 1, 'e', 4, 'd', 1, 'c']
>>> a.clear() # a = []

>>> a = [0,1]; b = a; c = a.copy()
>>> a,b,c
([0, 1], [0, 1], [0, 1])
>>> a[1]=2
>>> a,b,c
([0, 2], [0, 2], [0, 1])
```

# リスト
　ミュータブルなシーケンス型です．sort, sortedが使えます．sortがインプレースなソート，sortedが新しいリストを作ってソートします．
 
```python:list
>>> list((1,2,3))
[1,2,3]
>>> a = [1,2,3]
>>> a.sort(reverse=True) # a = [3, 2, 1]
>>> b = sorted(a) # sorted(a, key=None, reverse=False)
>>> a, b
([3,2,1], [1,2,3])
```

# タプル
　タプルはイミュータブルなシーケンス型です．

```python:tuple
>>> t = tuple('abc') # t = ('a', 'b', 'c')
>>> t = ([1,2], t) # t = ([1,2], ('a', 'b', 'c'))
>>> type((1,)) # <class'tuple'>
>>> type(()) # <class'tuple'>

>>> tuple(sorted([3, 2, 1]))
(1, 2, 3)
```

# レンジ
　レンジはミュータブルなシーケンス型で，`range(start, stop, step)`で初期化され，３つの変数のみのデータで表されます．forステートメントなどで活用されます．

```python:range
>>> r = range(1, 50, 5)
>>> for i in r:
	print(i, end=',')


1,6,11,16,21,26,31,36,41,46,
```

# 文字列
　文字列はテキストシーケント型strで表されます．

## 文字列の生成

```python:str
>>> type('abc'), type("abc"), type('''\
Hello? How are you?
I'm fine, thank you.
''')
(<class'str'>, <class'str'>, <class'str'>)
```

　これはイミュータブルなので，多数の文字列の結合にはリストを使って最後にjoinメソッドで文字列にすることが推奨されています．また，sortをするときも一度リストに変換されてインプレースで並び変えてから，joinで文字列にします．

```python:sort_of_str
>>> ''.join(['hello'] + [', '] + ['world!'])
'hello, world!'
>>> ''.join(sorted('hello, world!'))
' !,dehllloorw'
```

## 文字列の操作
### 整形・変換

|メソッド|結果|
|:--:|:---|
|capitalize()|最初の文字を大文字，残りを小文字にした文字列を返す|
|swapcase()|大文字と小文字の入れ替え|
|upper()|大文字化|
|lower()|小文字化|
|casefold()|大文字小文字の区別をなくす|
|title()|文字列をタイトルケースにして返す|
|center(width[, fillchar])|width幅で中央寄せ|
|ljust(width[, fillchar])|width幅で左寄せ|
|rjust(width[, fillchar])|width幅の右寄せ文字列|
|strip([chars])|文字列の先頭および末尾を除去|
|lstrip([chars])|文字列の先頭を除去したコピーを返す|
|rstrip([chars])|文字列の末尾を除去したコピーを返す|
|expandtabs(tabsize=8)|タブ`\t`をスペースで置換して返す|
|zfill(width)|width幅になるように0で埋める|
|encode(encoding="utf-8", errors="strict")|エンコードしてバイト列を返す|
|str.maketrans(x[, y[, z]])|変換テーブルの作成|
|translate(table)|変換テーブルに基づいて文字列を変換|

```python
>>> s = 'helLo wOrld!' # str: immutable
>>> s.swapcase(), s.upper(), s.lower()
('HELlO WoRLD!', 'HELLO WORLD!', 'hello world!')
>>> s.capitalize(), s.casefold(), s.title()
('Hello world!', 'hello world!', 'Hello World!')
>>> s.center(20), s.ljust(20, '-')
('    helLo wOrld!    ', 'helLo wOrld!--------')
>>> s.rjust(20,'0') == s.zfill(20)
True
>>> s.strip('hld!'), s.lstrip('hld!'), s.rstrip('hld!')
('elLo wOr', 'elLo wOrld!', 'helLo wOr')
>>> s.zfill(20)
'00000000helLo wOrld!'
>>> s.translate(str.maketrans('lh','rH'))
'HerLo wOrrd!'
```

### 検索・置換

|メソッド|結果|
|:--:|:---|
|count(sub[, start[, end]])|[start, end]の範囲に部分文字列subが重複せず出現する回数|
|find(sub[, start[, end]])|文字列[start:end]中のsubの位置，見つからなければ-1|
|index(sub[, start[, end]])|findと同様．見つからなければValueError|
|rfind(sub[, start[, end]])|文字列[start:end]中のsubの最大の位置．見つからなければ-1|
|rindex(sub[, start[, end]])|文字列[start:end]中のsubの最大の位置．見つからなければValueError|
|replace(old, new[, count])|文字列中のoldをすべてまたはcount個newに置換|

```python
>>> s
'helLo wOrld!'
>>> s.count('l')
2
>>> s.count('l'), s.casefold().count('l')
(2, 3)
>>> s.casefold().find('l'), s.casefold().rfind('l')
(2, 9)
>>> try:
	s.index('ll')
except Exception as e:
	print('Result of index: {0}'.format(e))
finally:
	print('Result of find: {0}'.format(s.find('ll')))

	
Result of index: substring not found
Result of find : -1
>>> s.replace('Lo w', 'lo W')
'hello WOrld!'
```

### 分割・結合

|メソッド|結果|
|:--:|:---|
|s.join(iterable)|sをセパレータとして引数中の文字列を結合した文字列|
|partition(sep)|文字列をsepの前，sep，sepの後に分割|
|rpartition(sep)|partitionと同じ．区切れなかったら後に文字列|
|rsplit(sep=None, maxsplit=-1)|右からmaxsplitまでsepで分割|
|split(sep=None, maxsplit=-1)|文字列をsepで分割したリスト|
|splitlines([keepends])|文字列を改行で分解.keependsがTrueなら改行を保持|

```python
>>> '/'.join('hello')
'h/e/l/l/o'
>>> s = 'a\rb\nc\td\ne'
>>> print(s)
a
b
c	d
e
>>> s.partition('\n'), s.rpartition('\n')
(('a\rb', '\n', 'c\td\ne'), ('a\rb\nc\td', '\n', 'e'))
>>> s.split(maxsplit=2), s.rsplit(maxsplit=2)
(['a', 'b', 'c\td\ne'], ['a\rb\nc', 'd', 'e'])
>>> s.splitlines()
['a', 'b', 'c\td', 'e']
```

### 判定

|メソッド|結果|
|:--:|:---|
|startswith(prefix[, start[, end]])|文字列がprefixで始まるか？|
|endswith(suffix[, start[, end]])|文字列がsuffixで終わるか？|
|isspace()|一文字以上の空白文字のみか？|
|islower()|小文字か?|
|issupper()|大文字か？|
|istitle()|タイトルケース文字列か？|
|isprintable()|印字可能か？|
|isascii()|ASCIIか？|
|isalpha()|英字か？|
|isalnum()|英数字か？|
|isdecimal()|数字か？|
|isdigit()|数字か？ローマ数字等を含む|
|isidentifier()|識別子か？|
|isnumeric()|数を表す文字か？漢数字等を含む|

```python
>>> 'hello'.startswith('hel') and 'hello'.endswith('lo')
True
>>> '\t'.isspace()
True
>>> 'hello'.islower() and 'HELLO'.upper().isupper()
True
>>> 'Hello world'.istitle(), 'Hello World'.istitle()
(False, True)
>>> s.isascii() and s.isalpha()
True
>>> 'a12'.isalnum() and 'a'.isalnum() and '1'.isalnum()
True
>>> '123'.isdecimal() and '123'.isdigit() and '123'.isnumeric()
True
```

　数字判定のメソッドについて，挙動の違いが分からなかったのでこちらを参照しましたが、再現できませんでした．色々調べて後日追記します。

* [Pythonのisdigit(),isdecimal(),isnumeric()の違いを調べてみた][ref1]

## format関数
　文字列にはformat関数があり、C言語のprintfのように変数を代入した文字列を生成することができます。後日別の記事で扱いますが、ここでは基本的な使い方だけ紹介しておきます。

```python
>>> "{}, {}!".format('Hello', 'World')
'Hello, World!'
>>> "{0} + {1} = {2}".format(2, 4, 2+4)
'2 + 4 = 6'
>>> "It's {time} o'clock.".format(time=10)
"It's 10 o'clock."
>>> "{0[0]} * {1[1]} - {0[1]} * {1[0]}".format([2,-1], [1,2])
'2 * 2 - -1 * 1'
>>> class A:
	def __init__(self, name, age):
		self.name = name
		self.age = age

		
>>> "{0.name} is {0.age} years old.".format(A('Bob', 12))
'Bob is 12 years old.'
```
 
―――以上

# 参考資料
*  [Python » 3.7.3 Documentation » The Python Standard Library » Built-in Types][pydoc]
* [Pythonのisdigit(),isdecimal(),isnumeric()の違いを調べてみた][ref1]

|previous|next|
|:---|:---|
|[IDLEでPython3：数値型編][prev]|coming soon|

[pydoc]: https://docs.python.org/ja/3/library/stdtypes.html#sequence-types-list-tuple-range
[ref1]: http://kk6.hateblo.jp/entry/20110526/1306395713

[prev]: https://qiita.com/LostEnryu/items/83ff8beb7e7c2f29d9e9