標準入力の受け取りtips@python

# 入力を受け取るには

コンソールからの入力をオブジェクトに代入するときはinput関数を使う。
ちなみraw_input関数はpython3では廃止されている。

```python
inp=input('なんか入力しろ>')

 # [In]# なんか入力しろ>hogehoge
 # [In]# inp
 # [Out]# 'hogehoge'
```



# 標準入力を正しい値が出るまで求める

「こういう形式で打ち込んでほしい！」という希望があれば、その形が打ち込まれるまでループするテクニック。
`while True:`で無限ループし、'hoge'が入力されるまで`inp`の値を聞いてくる。
'hoge'が入力されたらループを`break`する。

```python
while True:
	inp=input('hogeって入力して>>')
	if inp=='hoge':break

 # [Out]# hogeって入力して>>foo
 # [Out]# hogeって入力して>>hogehoge
 # [Out]# hogeって入力して>>hoge

 # [In]# inp
 # [Out]# 'hoge'

```


## 数字を6桁入力するまでエラーメッセージを返して入力を聞き返してくる

入力が間違っているとき、間違っているというエラーメッセージが表示されるとなおよい。
`while True`に加えて`try-except`文を使い、エラーが発生した場合に`except`まで飛ぶようにする。


```python
while True:
	try:
		inp=input('6桁の数字を入力してや >> ')
		if inp.isdigit() and len(inp)==6:
			break
	except:
		pass
	print('入力まちごうとるで')


 # [Out] # 6桁の数字を入力してや >> 3
 # [Out]#入力まちごうとるで
 # [Out] # 6桁の数字を入力してや >> 45
 # [Out]#入力まちごうとるで
 # [Out] # 6桁の数字を入力してや >> 666666
 # [In] # inp
 # [Out]# 666666

```

`while True:`で無限ループ
isdigit関数で、文字列の中身が数字であるどうか判断
かつlen関数で文字列の長さ確認
間違った値を入力するとtry文抜けてエラーメッセージがプリントされ、while節の最初に戻る。




## yes/noを聞いてくる

よくある'Yes'の頭文字'y'が入ると`True`で'No'の頭文字'n'が入ると`False`が入るようにする。
'y'を入力するとbool値`True`、'n'を入力するとbool値`False`がinpに入る。



~~inp=True if input('y/n? >> ')=='y' else False~~
真偽値を真偽値で置き換えるオロカナコトをしているので、簡略化

```python
inp=input('y/n? >> ')=='y'




 # In# inp=True if input('y/n? >> ')=='y' else False
 y/n? >> y

 # In# inp
 # Out# True

 # In# inp=True if input('y/n? >> ')=='y' else False
y/n? >> n

 # In# inp
 # Out# False
```


一行で書けるので「自分が絶対'y','n'のどちらかしか入力しない」の条件のもと、テスト的に書くなら便利。
しかし簡単だけどこれじゃあ不十分。
'y'が入力されたときには`True`返すけど、'yes'が入力されたときには`False`返す。
'y','n'以外の文字列が入力された場合も`False`を返してしまう。


```python

 # In# inp=True if input('y/n? >> ')=='y' else False
y/n? >> yes

 # In# inp
 # Out# False

 # In# inp=True if input('y/n? >> ')=='y' else False
y/n? >> t

 # In# inp
 # Out# False

```





## 選択肢に辞書を利用する

そこで、'y','yes','n','no'が入った辞書を用意する。
辞書はC言語のswitch-case文のようにして使える。

```python
dic={'y':True,'yes':True,'n':False,'no':False}
dic[input('[Y]es/[N]o? >> ').lower()]




 # [In]# dic[input('[Y]es/[N]o? >> ').lower()]
 # [Out]# [Y]es/[N]o? >> y
 # [Out]# True

 # [In]# dic[input('[Y]es/[N]o? >> ').lower()]
 # [Out]# [Y]es/[N]o? >> NO
 # [Out]# False

 # [In]# dic[input('[Y]es/[N]o? >> ').lower()]
 # [Out]# [Y]es/[N]o? >> ye
 # [Out]# ---------------------------------------------------------------------------
 # KeyError                                  Traceback (most recent call last)
 # <ipython-input-34-67f9611165bf> in <module>()
       # 1 dic={'y':True,'yes':True,'n':False,'no':False}
 # ----> 2 dic[input('[Y]es/[N]o? >> ').lower()]
 # 
 # KeyError: 'ye'

```

さりげなくlower関数使って入力をすべて小文字にすることで、'YES'も'yes'も同義とみなさせている。
まだこれでは不十分で、'yes'と打ちたいところを'ye'と打っちゃったら`KeyError`

そこでさっきの`while True:`と`try`ステート使う。


```python
dic={'y':True,'yes':True,'n':False,'no':False}
while True:
	try:
		inp=dic[input('[Y]es/[N]o? >> ').lower()]
		break
	except:
		pass
	print('Error! Input again.')


 # [Out]# [Y]es/[N]o? >> ye
 # [Out]# Error! Input again.
 # [Out]# [Y]es/[N]o? >> yes

 # [In]# inp
 # [Out]# True
```

____
以下[shiracamus](http://qiita.com/shiracamus)様よりご指摘いただいた方法

### inを使う方法


```python
while True:
    inp = input('[Y]es/[N]o? >> ').lower()
    if inp in dic:
        inp = dic[inp]
        break
    print('Error! Input again.')
```

### 入力された文字列の最初の文字が'y'か'n'か判断する方法

```python
while True:
    inp = input('[Y]es/[N]o? >> ').lower()
    if inp in ('y', 'yes', 'n', 'no'):
        inp = inp.startswith('y') # inp[0] == 'y'と同義
                                  # string.startwithは最初の文字列を調べる
        break
    print('Error! Input again.')
```

### 辞書の中にない値が入力されたらboolじゃない値返して再度ループする方法

```python
while True:
    inp = dic.get(input('[Y]es/[N]o? >> ').lower(), -1)   #inpのデフォルト値を-1(←bool値でなければなんでもよい)にしておく
    if type(inp) is bool:
        break
    print('Error! Input again.')
```


# 標準入力を複数受け取る


## 指定した数だけ標準入力を受け取りリストに格納したい

3回連続で聞いてきて、それをリストに格納したいとき、リスト内法表記が使える。

```python
[input() for _ in range(3)]
 # [In]# a
 # [In]# d
 # [In]# v
 # [Out]#: ['a', 'd', 'v']
```







## 一行で複数の標準入力を受け取りリストに格納したい

一行の間に複数のinputを受け付けたいときがある。
そういう時はinput関数の後にsplit関数つけて分割する。
split関数のデフォルト引数は空白文字なので、スペースで区切りでリストに格納される。
別の文字で区切りたいときはsplit関数の引数にその文字を入れてあげる。
例えばコンマで区切りたいときは以下のようにする。


```python
a=input('コンマ区切りでなんか入力しろ >> ').split(',')


	# [In] a=input('コンマ区切りでなんか入力しろ >> ').split(',')
	# [Out] コンマ区りでなんか入力しろ >> 2016,2017

	# [In] a
	# [Out] ['2016', '2017']
```








## 標準入力から任意の数だけ受け取りリストに格納したい

中断コマンド(windowsではctrl+Z)が押されるまで標準入力を受け取り、リストに格納するテクニック。
`sys.stdin.readline`のシリーズは、`input`よりも広い用途で標準入力を取得するための関数群。

`sys`ライブラリをimportすることで使えるようになる。

`readline()`は標準入力から1行取得するための関数。
`input()`とのちがいは、inputが改行文字を自動的に削除するのに対し、`readline()`は標準入力に与えられた内容をそのまま取得してくる。
改行を削除するには`strip()`メソッドを使う。

```python
import sys
inp=sys.stdin.readline().strip()




 # [In]# inp=sys.stdin.readline()
 # [In]# pp

 # [In]# inp
 # [Out]# 'pp\n'

 # [In]# inp=sys.stdin.readline().strip()
 # [In]# inp
 # [Out]# 'pp'
```






readlines は標準入力から複数行取得するための関数。
戻り値はリストで、入力された文字列が1行ずつ要素として格納される。
こちらも改行文字の自動削除はないので、`sprit()`を使う。



```python
import sys
[i.strip() for i in sys.stdin.readlines()]


 # [In]# ho
 # [In]# hsop
 # [In]# hpoge
 # [In]# ^Z
 # [Out]# ['ho', 'hsop', 'hpoge']
```



### 参考
1. [stack overflow : Get a Try statement to loop around until correct value obtained](http://stackoverflow.com/questions/2244270/get-a-try-statement-to-loop-around-until-correct-value-obtained)
1. [Pythonで競技プログラミングする時に知っておきたいtips(入出力編)](http://qiita.com/lethe2211/items/6cbade2bc547649bc040)
1. [LIFE WITH PYTHON : Python Tips：標準入力から文字列を取得したい ](http://www.lifewithpython.com/2014/05/python-get-stdin-standard-input.html)