LoginSignup
26
39

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-09-04

入力を受け取るには

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

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

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

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

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

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まで飛ぶようにする。

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
真偽値を真偽値で置き換えるオロカナコトをしているので、簡略化

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を返してしまう。


 # 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文のようにして使える。

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ステート使う。

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様よりご指摘いただいた方法

inを使う方法

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

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

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じゃない値返して再度ループする方法

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回連続で聞いてきて、それをリストに格納したいとき、リスト内法表記が使える。

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

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

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

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()メソッドを使う。

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()を使う。

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
  2. Pythonで競技プログラミングする時に知っておきたいtips(入出力編)
  3. LIFE WITH PYTHON : Python Tips:標準入力から文字列を取得したい
26
39
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
39