- GAFAMに転職した現役の技術職が執筆
- 2流文系卒からプログラマーに転身
- 初心者からプログラマーになって、一人前のエンジニアとして歩んでいける戦略を公開
- 年収1800万円以上
Python(パイソン)勉強しだしたんですが、変数(へんすう)っていうのがいまいちよくわかりません。
変数の名前とか勝手につけてよいのかわからないし、スコープ?もよくわかりません。
教えてほしいです。
その気持ちよくわかります。私もプログラミングを始めたとき、変数がよくわかりませんでした。私は当時本当にわかっていなくて、変数の名前自体に何か意味があって、変数名を変えると何かプログラムの動作が変わってしまうんじゃないかと思って、講師に質問して笑われた経験があります。知ってる人からしたら当たり前なんでしょうけど、知らない人にとっては、本当にわからないんですよ;
というわけで、今回は、プログラミング初心者が変数についてわからないこと8個厳選して、解説していきたいと思います。
プログラミング初心者が、変数(へんすう)でわからないこと8つを分かりやすく解説
変数って何をするもの?
変数とは、プログラムでデータを一時的に入れておく箱のようなものです。この箱には、数や文字などのいろいろな情報を入れることができます。例えば、モンスターを倒すロールプレイングゲーム(例えばドラクエ)のヒットポイント(HP)を考えてみましょう。HPを表す変数があれば、モンスターに攻撃されて減ったり、回復呪文で増えたりするのを簡単に管理できます。プログラムではこの箱に入れたデータを使って、計算をしたり表示をしたりします。つまり、変数はデータを扱いやすくするために使う大事な道具です。
実際のプログラミングコードを書いてみましょう。例えば、ドラクエのHPを管理する簡単なプログラムを考えてみます。
# HPの初期値を設定
hp = 50
print(f'初期のHP: {hp}') # 初期のHPを表示
# モンスターに攻撃された場合
hp -= 10 # HPを10減らす
print(f'攻撃を受けた後のHP: {hp}') # 攻撃を受けた後のHPを表示
# 回復呪文で回復した場合
hp += 20 # HPを20回復する
print(f'回復後のHP: {hp}') # 回復後のHPを表示
このように、変数hp
を使うことでHPの増減を簡単に管理することができます。
- データを一時的に入れる箱のようなもの
- 数や文字などを記憶できる
- 算数や情報の扱いを便利にするために使う
どうして変数を使う必要があるの?
変数を使うと、プログラムがとても便利になります。なぜなら、変数を使うことで同じデータを何度も使ったり、あとから簡単にデータを変えたりすることができるからです。変数を使わないとプログラミングが非常に面倒です。例えば、ドラクエのHPを管理するプログラムで、変数を使わずにHPを減らす場合、次のようなコードを書くことになります。
print(50) # 初期のHP
print(50-10) # 攻撃(-10)を受けた後のHP
5print(50-10-15) # さらに攻撃(-15)を受けた後のHP
このように、攻撃を受けるたびに最初の状態のHPから計算していく必要があり、とても面倒です。というか、HPは変数でなくては現在の状態を管理できません。この例は無理やり書いた変な例です。
変数名は何でもいいの?
変数名は基本的に自由につけることができます。変数名自体が、プログラムの処理に影響を与えることはありません(変数名が重複していない場合)。しかし、ルールもあります。まず、使ってはいけない記号や言葉が決まっています。そして、人間にとって分かりやすい名前にすることが大切です。例えば、「数字を入れる変数」なら「number」や「count」という名前にすることで、プログラムを読んだときに何をするための変数かがすぐにわかります。わかりにくい名前にすると、あとからプログラムを見直す時に困ってしまいますし、他人が理解するのが難しくなります。
例えば、ドラクエのキャラクターたちのHPを管理するプログラムを考えてみましょう。この例では、変数名で誰のHPかを人間に分かりやすく表現しています。
# 各キャラクターのHPを設定
yusha_hp = 100
senshi_hp = 120
souryo_hp = 80
mahou_tsukai_hp = 70
# 初期のHPを表示
print(f'Yusha no HP: {yusha_hp}')
print(f'Senshi no HP: {senshi_hp}')
print(f'Souryo no HP: {souryo_hp}')
print(f'Mahou Tsukai no HP: {mahou_tsukai_hp}')
# モンスターにパーティアタックされた場合
yusha_hp -= 15 # 勇者の HP を 15 減らす
senshi_hp -= 10 # 戦士の HP を 10 減らす
souryo_hp -= 20 # 僧侶の HP を 20 減らす
mahou_tsukai_hp -= 25 # 魔法使いの HP を 25 減らす
# 攻撃を受けた後のHPを表示
print(f'Yusha no HP: {yusha_hp}')
print(f'Senshi no HP: {senshi_hp}')
print(f'Souryo no HP: {souryo_hp}')
print(f'Mahou Tsukai no HP: {mahou_tsukai_hp}')
このように、各キャラクターのHPを別々のわかりやすい変数で管理することで、誰がどのくらいダメージを受けたかを、人が簡単に追跡することができます。
- 自由に名前をつけられるがルールもある
- 記号や予約語は使えない
- 読みやすくて分かりやすい名前をつける
実際のプログラムでは、この変数名はあまり良い例ではありません。パーティーに加えられる職業は変更できるからです。ですので実際には、配列を使って管理するのが良いでしょう。
例えば、4人のパーティのHPを配列で表現するプログラムは以下のようになります。
# 4人のパーティのHPを配列で管理
party_hp = [100, 120, 80, 70]
# 初期のHPを表示
for i, hp in enumerate(party_hp):
print(f'Character {i + 1} no HP: {hp}')
# モンスターにパーティアタックされた場合
party_hp[0] -= 15 # 勇者のHPを15減らす
party_hp[1] -= 10 # 戦士のHPを10減らす
party_hp[2] -= 20 # 僧侶のHPを20減らす
party_hp[3] -= 25 # 魔法使いのHPを25減らす
# 攻撃を受けた後のHPを表示
for i, hp in enumerate(party_hp):
print(f'Character {i + 1} no HP: {hp}')
このように配列を使うことで、キャラクターのHPをより簡単に管理することができます。この例で配列を使ってしまいました。また別途解説しますね。
変数にどんな値を入れられるの?
変数にはいろいろな種類の値を入れることができます。例えば、数字、文字、文章、そして「はい」や「いいえ」のような値です。これらの値のことを「データ型」といいます。データ型が違うと、変数の使い方も変わります。例えば、数字の変数は足し算や引き算に使えるし、文字の変数は文章を作るために使います。つまり、どんな値を入れるかによって変数の使い方が決まってきます。
例として、1人のプレイヤーを変数で表現してみましょう。
# プレイヤーの名前(文字列)
namae: str = "Taro"
# プレイヤーの職業(列挙型の宣言)
from enum import Enum
class Shokugyo(Enum):
YUSHA = "Yusha"
SENSHI = "Senshi"
SOURYO = "Souryo"
# プレイヤーの職業(変数)
shokugyo: Shokugyo = Shokugyo.YUSHA
# プレイヤーの性別(列挙型の宣言)
class Seibetsu(Enum):
MALE = "Male"
FEMALE = "Female"
# プレイヤーの性別(変数)
seibetsu: Seibetsu = Seibetsu.MALE
# プレイヤーのHP(整数)
hp: int = 100
# プレイヤーのMP(整数)
mp: int = 50
# 各変数の値を表示
print(f"名前: {namae}")
print(f"職業: {shokugyo.value}")
print(f"性別: {seibetsu.value}")
print(f"HP: {hp}")
print(f"MP: {mp}")
このように、プレイヤーの情報を変数で管理することで、ゲームのキャラクターに関する情報を整理して扱いやすくすることができます。
- 数字、文字、文章などいろいろな値を入れられる
- 入れられる値の種類を「データ型」と呼ぶ
- データ型に応じて変数の使い方が変わる
実際のプログラミングだと、上の例はあまり使いません。実際にはplayerという辞書型の変数にそれぞれの情報を格納し、初期化しておくことが一般的です。
# プレイヤーの情報を辞書型で宣言
from enum import Enum
class Shokugyo(Enum):
YUSHA = "Yusha"
SENSHI = "Senshi"
SOURYO = "Souryo"
class Seibetsu(Enum):
MALE = "Male"
FEMALE = "Female"
# プレイヤーを辞書型の変数で宣言
player = {
"namae": None,
"shokugyo": None,
"seibetsu": None,
"hp": None,
"mp": None
}
# 各情報を変数に代入
player['namae'] = "Taro"
player['shokugyo'] = Shokugyo.YUSHA
player['seibetsu'] = Seibetsu.MALE
player['hp'] = 100
player['mp'] = 50
# 各変数の値を表示
print(f"名前: {player['namae']}")
print(f"職業: {player['shokugyo'].value}")
print(f"性別: {player['seibetsu'].value}")
print(f"HP: {player['hp']}")
print(f"MP: {player['mp']}")
このように、辞書型を使うことで関連する情報を一つの変数にまとめて管理することができます。
変数の中身を変えるにはどうすればいい?
変数の中身を変えるには、新しい値をその変数に「代入」すれば良いだけです。例えば、「りんごの数」を数える変数があったとして、初めは3個入っていたけど、あとから2個追加したいとします。その場合は「りんごの数」に5を入れ直せば、変数の中身は自動的に新しい値になります。同様に、ドラクエのヒットポイント(HP)も考えてみましょう。初めはHPが50だったのが、攻撃を受けて40に減り、その後回復して60に増えるといった操作も、変数に新しい値を代入することで簡単に管理できます。また、変更前の値を保持しておくことも重要です。以下のプログラムを見てみましょう。
# HPの初期値を設定
hp = 50
print(f'初期のHP: {hp}') # 初期のHPを表示
# 攻撃を受けた場合、前のHPを保持しつつ、新しい値に変更
previous_hp = hp
hp -= 10 # HPを10減らす
print(f'攻撃前のHP: {previous_hp}, 攻撃後のHP: {hp}') # 前後のHPを表示
# 回復した場合、前のHPを保持しつつ、新しい値に変更
previous_hp = hp
hp += 20 # HPを20回復する
print(f'回復前のHP: {previous_hp}, 回復後のHP: {hp}') # 前後のHPを表示
このように、変数の前の値を別の変数に保持しておくことで、変更前後の状態を追跡することが可能です。プログラムを書くときには、変数に新しい値を簡単に入れ替えることができるので、とても便利です。
- 新しい値を「代入」して変える
- 何度でも中身を変更可能
- プログラムの途中で値を更新できる
変数に入れた値はどこまで使えるの?
変数に入れた値が使える範囲のことを「スコープ」と呼びます。スコープが広ければ広いほど、その変数をいろんな場所で使うことができます。しかし、スコープが狭いと、その変数は特定の場所でしか使えません。例えば、ある関数の中で作った変数は、その関数の外では基本的に使えません。一見、スコープが広い方が、人にとって使い勝手が良さそうに思えますが、プログラムとしては良いとは言い切れません。スコープを考えることは、プログラムのミスを防ぐためにとても重要です。
- 変数が使える範囲を「スコープ」と呼ぶ
- スコープが広いと多くの場所で使える
- スコープを考えることでミスを防ぐ
できる限り関数(メソッド)内で、小さいスコープで変数を宣言すると不具合が少なく、メモリ効率も良いプログラムになります。
PC上で色々なアプリを使っているとPCの動作が重たくなることありませんか?これは、使っているアプリケーションの中で利用中の変数が多くなり、PC上のメモリを使いつくし、代わりにハードディスクをメモリの代わりに利用することが原因の場合があります。アプリをOS上から終了すればアプリケーションで利用している変数は解放され、メモリも解放されます。
メモリを使い尽くす現象は、アプリの仕様の場合もありますが、不具合の場合もあります。Webアプリの場合は、サーバーリソースを余計に消費することになり、ランニングコストに影響します。優秀なプログラマーは、変数の宣言の場所やスコープを考慮することで、メモリ効率のよいプログラムを書くことができます。そのシステムの運用にかかるメモリ消費量を最小限に抑えることができ、サーバーリソースの利用料を下げることができます。
変数の値を使いまわしたいときはどうする?
変数の値を使いまわす場合、その変数を必要なところで呼び出すだけで済みます。例えば、何度も同じ計算をしたいときに、変数に計算結果を入れておけば、それを他の場所で再利用することができます。また、変数の値を他の変数にコピーすることも可能です。これにより、一度計算したデータを別の用途で使うことができ、効率的にプログラムを書くことができます。
- 変数を必要な場所で呼び出して使う
- 値を他の変数にコピーできる
- 効率よくデータを再利用できる
変数の使いまわしには注意が必要です。変数の参照は複数で参照することは良いですが、変数の中身を更新するのは、単一の処理で行うようにすることが不具合を抑えることにつながりますし、不具合が発生しても、その原因を探しやすくなります。
C言語などで書かれた古くから受け継がれたプログラムを見ると、複数の処理から同時に更新されたりしそうな危なっかしいコードを目にします。危なっかしいコードだけど、奇跡的に品質は保たれた状態にあると推測します。このコードを更新すると、その更新者がその危なっかしいソースコードの品質を担保する責任を負うので、そのコードは誰も更新されることはなく、そのまま受け継がれることになります。そのようなコードをよく、レガシーコードと言ったりします。
OSや利用しているライブラリのサポートが終了するようなタイミングで、そのレガシーコードを更新する必要に迫られ、どうしようとみんな悩みだします(笑)
変数と定数の違いって何?
変数と似たものに「定数」というものがあります。変数は中身を自由に変えられるのに対し、定数は一度決めたらその値を変えることができません。例えば、「1年は12か月」という事実は変わらないので、こういう時に定数を使います。変数は変更が必要なデータに使い、定数は変わらないデータに使うことで、プログラムの信頼性を高めることができます。
- 変数は値を変えられるが、定数は変えられない
- 変わらないデータに定数を使う
- 信頼性の高いプログラム作成に役立つ
というわけで、今回は変数についてわかりにくいこと8選をまとめてみました。皆さんの理解の助けになれば幸いです。
ここまで読んでいる方でHello Worldをやったことがない人はいないと思いますが、念のため、Hello Worldする記事について紹介します。
Pythonの基本を学びたいという方はこちらの書籍もおすすめです。