これでもうエラーは怖くない

Python
Photo by Marina Vitale on Unsplash

前回は「見やすさ」にこだわった出力方法を見てきました。
プログラムを書く際の誤りを減らすためにぜひ覚えておきたい内容です。
今回は年齢プログラムの改良を通して、
関数とデータ型、例外処理について学んでいきます。

次回は条件分岐について説明します。

JUVET
JUVET

本記事も実践を意識したプログラミングになっています!

関数は自動販売機のような働きをもつ

Photo by Victoriano Izquierdo on Unsplash

まずはこれまでに出てきた2つの関数をおさらいします。
print( )関数とinput( )関数が登場しました。

print( )はカッコの中に書いた内容が出力されるのでした。
input( )はカッコの中に書いた内容が(画面に)表示され、ユーザーの行動を促すのでした。

ここで、話を分かりやすくするために、たとえ話を導入したいと思います。
見出しタイトルにありますように、関数を自動販売機に例えて説明します。

まず、自動販売機を使用する際に必要となるものを考えます。
必要なものといえば、お金だけですね。
お金を入れることで金額に応じたボタンが点灯し、
飲み物を購入できるようになります。
その際に、ほしい飲み物のボタンを押すと、
該当する飲み物が取り出し口に落ちてくる仕組みです。

したがって、自動販売機の仕組みは以下のように要約できます。
お金を入れる(入力する)ことで、
飲み物が出てくる(出力される)。

つまり、
何かを入れると(別の)何かが出てくる構造になっているということです。

関数もこれによく似ています。
print( )関数であれば、入力に文字列などの変数を受け取り
受け取った値を(そのまま)画面に出力します

input( )関数はユーザーから入力された値(文字など)を受け取り
値を文字列にして返します

自動販売機で飲み物を購入するとき、
機械内部の細かい仕組みまで考える人は少数派だと思います。

「細かいことは分からないけど、使い方は分かる」
という状態の人が大半ではないでしょうか。
これは言い換えると、私たちは自動販売機をブラックボックスとして使っており、
その中身を熟知していなくても使いこなすことができるのです。

これまで使ってきた関数(print( ) と input( ))も同じように、
特に細かいことは意識しないでプログラムに書いてきました。
ふつうはこの姿勢でいいのですが、今回だけ特別に、
あえて関数の中身を見てプログラムの理解を深めていきます。

データ型とはお金の種類のこと

Photo by Tengyart on Unsplash

関数の中身を見ていくわけですが、その際に必要となる概念がデータ型になります。
データ型というのは、取り扱うデータの種類のことで、
先ほどの自動販売機の例で例えると、投入できるお金の種類を指しています。

硬貨であれば10円玉や100円玉などの種類があり、
お札であれば1000円札や5000円札などがあります。
これらのお金を投入口に入れた場合、自動販売機はお金の種類を判別して、
液晶パネルに金額を表示したり、購入ボタンを点灯させたりします。

関数も同じように、データの種類を明確にして処理を実行します。
データ型には以下のようなものがあります。

strデータ型:データの中身は文字列(’Hello’ や ‘こんにちは’ など)
intデータ型:データの中身は整数(1, 5, 10, 1000 など)
floatデータ型:データの中身は少数(1.0, 5.5, 99.9 など)

strデータ型の str は string(文字列)の省略形で、
intデータ型の int は integer(整数)、
floatデータ型の float は floating point number(浮動小数点数)の省略です。

自動販売機の話に戻り、
投入口に1円玉や5円玉を入れた場合のことも考えてみましょう。
購入ボタンが点灯することもなく、
硬貨が返却口から出てきてしまいます。
自動販売機はお金の種類を制限しているということですね。

関数でも同じように、
データ型を制限して処理しないとプログラムが動かないことがあるのです。
例えば前回の例で登場した、
「たしかに愛歳に見えますね!」のような出力を回避するためには
関数の入力を数値のみに限定し、処理を実行するべきです。

それではデータ型の話を踏まえて、
前回のプログラムを改良してみましょう。

年齢プログラムを改良する

入力された文字列を整数に変換して出力している


まずは以下のプログラムを書いてください。

age = input('あなたの年齢を教えてください。')

# int()関数で入力(文字列)をintデータ型(整数)に変換する
age = int(age)

# 変数ageはintデータ型のため, カンマで区切って書く
print('たしかに', age, '歳に見えますね!')

前回のコードと異なるのはint( )関数を使用している点と、
print( )関数内での変数の書き方です。

まず int( )関数はカッコの中身をintデータ型に変換するために使います。
そのため、一行目の age変数(入力された文字列)は整数に変換され、
最後にprint( )関数で出力されます。

また、前回の記事に書いたとおり、
print( )関数で複数の値を出力するときはカンマを使うのでしたね。
ただし、変数が文字列の場合は
以下のように加算で表現しても問題ありませんでした。

print('たしかに' + age + '歳に見えますね!')


しかし今回は変数 age が intデータ型のため、
カンマを使った表現でないとプログラムを実行できません。

これで前回のプログラムが改良できたかのように見えるかもしれませんが、
実は今回のプログラムでは、
数値以外の文字列を受け取った場合、以下のように例外を発生してしまいます。

不適切な文字列を整数に変換しようとすると例外が発生する


この例外(ValueError)は関数に不適切な値が入力されたときに発生します。
たとえば ’10’ (全角入力も可)のような文字列であれば数値に変換できても、
‘愛’ のような文字列はどう頑張っても数値には変換できないということを表しています。

そのため、前回のプログラムを改良するにはもう少しの工夫が必要になります。
具体的にどんな工夫かといいますと、
整数の場合にはこれまで通りの出力をして、
不適切な値の場合には数値を入力するように促す、
そんなプログラムを作成するということです。

このように想定される例外(リスク)に応じて処理を変えることを例外処理といいます。
さっそく例外処理の実装に取り掛かりましょう。

JUVET
JUVET

エラーが予想されるような場面で使われます!

例外を防ぐ処理を書く

:(コロン)を書いた状態で改行(enter)すると自動でインデントされる


実現したいこと:
入力値が数値に変換できる場合に限り、年齢を出力するプログラムを書くことです。

まずは以下のコードを書きましょう。

age = input('あなたの年齢を教えてください。')

try:
  age = int(age)
  print('たしかに', age, '歳に見えますね!')
except ValueError:
  print('数字のみを入力してください。')


上記のコードの try: 以下にはこれまで通りの処理を書きます。
つまり、入力された文字列を整数に変換して出力するコードを書くということです。
このとき、注意すべき点として
try の右側にある : (コロン)を書き忘れないことと、
改行した後のコードにはインデント(字下げ)を行うことです。

ここでインデントとは、
space キーもしくは tab キーで先頭に余白をつくることを指します。
このように余白をつくっておくと、
コードが見やすくなり、処理内容が明確になるというメリットがあります。

今回のプログラムでは、以下の2文がインデントされているため
この2文が処理内容なのか、と一目で分かるようになっているということです。

# インデントされたコード(処理部分) 
  age = int(age)
  print('たしかに', age, '歳に見えますね!')


他のプログラミング言語と違い、
pythonではこのインデントが行われていないと例外を発生させる仕組みを採用しています。
つまり、見やすさを大事にした目に優しい言語なのです。

また Colaboratory 上ではデフォルトの設定で
インデントがspaceキー2マス分の余白になっていますが、
本来pythonにおけるインデントは4マス分の余白を指します。

本記事では、デフォルトの余白2マスでプログラミングを行っていきます。

JUVET
JUVET

ルール4: 例外処理ではインデントを行う!


例外処理を行うとき、
構文(pythonで定められた文法)のルールを守らなければいけません。
書き方は以下のとおりです。

try:
  上手くいくときに行いたい処理
except 例外名:
  想定される例外が発生したときの処理

※このプログラムは構文の説明のために書いているので、実際には動きません。

except 例外名: 以下には、
想定される例外が発生したときに行いたい処理をインデント付きで書きます。

今回の例外名は ValueError (不適切な値が入力されると発生)でした。
つまり、年齢を表す数値ではなく、「愛」などの数値に変換できない
文字列が入力されたときに行うべき処理を書いておくと、例外が発生しても
プログラムが止まることなく実行される仕組みを整えることができるのです。

ちなみにインデントを行わないと以下のように例外を発生します。

try以下とexcept以下はインデントを行う


この例外は、インデント忘れであることを教えているのです。
またインデントされた領域にあるコードはまとめてブロックと呼ばれます。
余力があればぜひ覚えましょう。

このように例外処理ができると、前回の例に登場した、
「たしかに歳に見えますね!」のような出力を回避できるようになります。
実際に上記のプログラムで「愛」と入力した場合は、
以下の図のように例外を発生させることなく、プログラムが実行されます。

数値に変換できなかった場合は、数値のみを入力するように促す


これで前回のプログラムは改良できましたが、
たとえば年齢に応じて処理を変えたい場合はこの例外処理のみでは実現できません。
その場合には条件分岐と呼ばれる処理を行う必要があります。
具体的な説明は次回に譲ります。

まとめ

本記事では関数とデータ型ついて学びました。
関数は基本的にブラックボックスとして使用するけれど、
データ型について学ぶためにあえて中身を覗いたのでした。

例外処理ではインデントやブロックといった用語が登場しました。
これは想定されるリスクを回避するために使用するのでした。
また次回説明する条件分岐は、今回の例外処理と同じような構文なので、
コロンとインデントはおさえておくとよいでしょう。

今回出てきたルールは以下の通りです。

ルール4: 例外処理ではインデントを行う

例外処理の実装方法とインデントについての知識があれば、
事前にエラーを防ぐことができるようになるため、
何も恐れることはありません。

次回は関数についての補足と条件分岐について説明していきます。



【P.S.】
今後もあなたのお役に立てるような記事を作成していきますので、
@AI_JUVETをフォローしていただけると大変励みになります🙂

コメント

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