Pythonで時計(時間)を生み出す
1.身の回りのものをプログラムで再現する
一通りコードが書けるようになったら、身の回りのものをプログラムで再現してみるととても勉強になります。
今日はクラスを使って信号機と時計を再現してみます。
2.信号機のモデル化
(1) 信号機を抽象化する
プログラムに置き換える際は、まず対象を抽象化します。
青・黄・赤のライトがあって、一定の時間で転倒するライトが変わります。
押しボタン式信号だと、ボタンが押されたことをきっかけに信号が切り替わりますがまずは時間で自動的に切り替わる信号機のイメージにします。
(2) プログラムで再現する信号機を具体化する
一旦特徴を抽象化したら、具体的にどうプログラムで再現するかを考えてみます。
まず、赤・青・黄の3つのライトは、点灯している・いないの2つの状態で表せます。時間で切り替わるのであれば、赤信号でいる時間、黄色信号でいる時間、青信号でいる時間を定義する必要があります。
ここで、さらに上位概念として「時間」が必要になってきます。
プログラムの世界に、時間を生み出して、生み出した時間を利用して信号機を点灯させるわけです。
3.時間のモデル化
さて、では時間はどのように生み出すか。
(1) 現在時刻を利用する
pythonにはtimeモジュールがあるので、処理開始時刻から経過時間を取得する方法がまずあります。
timeモジュールで処理開始時刻を取得し、sleepメソッドで1秒経過させ都度現在時刻(秒数)と処理開始時刻の差分を取得して出力しています。
import time
import math
start_time = math.floor(time.time())
while True:
time.sleep(1)
end_time = math.floor(time.time()) - start_time
print(end_time)
(2) classを利用して、属性として時刻をオブジェクト自身に持たせる
では例えば時間というオブジェクトを生み出して、時刻を属性としてオブジェクト自身に持たせ、1秒ごとに自分の時刻を更新していくメソッドを持たせてみましょう。
import time
import math
class Clock:
def __init__(self):
self.self_time = 0
def count_clock(self):
start_time = math.floor(time.time())
while True:
time.sleep(1)
self.self_time = math.floor(time.time()) - start_time
print(self.self_time)
Clockというクラスを作成して、self_timeという属性を定義しています。これがClockというクラスが保有する時刻のプロパティです。
さらに、Clockというクラスにcount_clockというメソッドを持たせ、ループ処理で1秒ごとに現在時刻と開始時刻の差分を求めながら自身の時刻を更新する処理を定義しています。
次に、定義したクラスを使って時計オブジェクトを実体化し、メソッドを利用してみましょう。
my_clock = Clock()
my_clock.count_clock()
my_clockというオブジェクトを作成して、Clockクラスが持つcount_clock()メソッドを実行しています。
出力結果を見ると・・・
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
時刻が1秒ずつ更新されているのが分かります。
4.時計を作ってみよう
ついでに寄り道して、デジタル時計を作ってみましょう。
もう信号機は次回にします笑
(1) デジタル時計の抽象化
デジタル時計を抽象化すると・・・
(2) プログラムで再現するデジタル時計の具体化
1分は60秒、1時間は3,600秒です。
ちなみに24時間は3,600 × 24 = 86,400(秒)です。
つまり、3,601〜86,400秒だと時間表記がされ、秒数 ÷ 3,600 = 時間数。時間の2桁目は時間数÷10の商(商が0なら0)、時間の1桁目はその余り。
61秒以降分数表記がされ、秒数 - 時間数 × 3,600 ÷ 60 = 分数。分の2桁目は分数÷10の商(商が0なら0)、分の1桁目はその余り。
秒表記部分は、秒数 - 時間数 × 3,600 ÷ 分数 × 60 = 秒数。秒の2桁目は秒数÷10の商(商が0なら0)、秒の1桁目はその余り。
(3) 実際に計算してみる
仮に現在が80,000秒の場合、を考えてみましょう。
時間数は80,000÷3,600 = 22。
時間の2桁目は22÷10の商である2、時間の1桁目は余りの2となります。
分数は(80,000 - 22 × 3,600) ÷ 60 = 13。
分数の2桁目は13÷10の商である1、分数の1桁目は余りの3となります。
秒数は(80,000 - 22 × 3,600 - 13 × 60) = 20。
秒数の2桁目は20÷10の商である2、秒数の1桁目は余りの0となります。
つまり、22時間13分20秒となり、デジタル時計の表記は22:13:20となります。(22 × 3,600 + 13 × 60+20 = 80,000になると思います)
(4) デジタル時計を再現する
先ほどのClockクラスに、時間数2桁・分数2桁・秒数2桁の6つのプロパティ(属性)を持たせ、clock_countメソッドに上記6つのプロパティを更新する処理も追加します。
class Clock:
def __init__(self):
self.self_time = 0
#時間・分・秒の2桁ずつのプロパティを持たせる
self.seconds_counter_one = 0
self.seconds_counter_ten = 0
self.minutes_counter_one = 0
self.minutes_counter_ten = 0
self.hours_counter_one = 0
self.hours_counter_ten = 0
def count_clock(self):
start_time = math.floor(time.time())
while True:
time.sleep(1)
self.self_time = math.floor(time.time()) - start_time
#時間・分・秒の2桁ずつのプロパティを更新していく
if self.self_time > 86400:
self.self_time = 0
else:
if self.self_time // 3600 == 0:
hours = 0
else:
hours = self.self_time //3600
if (self.self_time - hours * 3600) // 60 == 0:
minutes = 0
else:
minutes = (self.self_time - hours * 3600) // 60
seconds = (self.self_time - hours * 3600 - minutes * 60)
if seconds == 0:
self.seconds_counter_one = 0
self.seconds_counter_ten = 0
else:
self.seconds_counter_ten = seconds // 10
self.seconds_counter_one = seconds - \
self.seconds_counter_ten * 10
if minutes == 0:
self.minutes_counter_one = 0
self.minutes_counter_ten = 0
else:
self.minutes_counter_ten = minutes // 10
self.minutes_counter_one = minutes - \
self.minutes_counter_ten * 10
if hours == 0:
self.hours_counter_ten = 0
self.hours_counter_one = 0
else:
self.hours_counter_ten = hours // 10
self.hours_counter_one = hours - \
self.hours_counter_ten * 10
#更新したら表示する
print("{}{}:{}{}:{}{}".format(self.hours_counter_ten, \
self.hours_counter_one, self.minutes_counter_ten, \
self.minutes_counter_one, self.seconds_counter_ten, \
self.seconds_counter_one))
再度、Clockクラスをもとにオブジェクトを作成し、clock_countメソッドを実行してみましょう。
my_clock = Clock()
my_clock.clock_count()
実行して2分35秒経過後の出力内容を抜粋すると・・・
00:02:35
00:02:36
00:02:37
00:02:38
00:02:39
デジタル時計のように表示ができていますね。
このように、身の回りのものを「どうすればプログラムで実現できるか」を考え試していくことはとても勉強になると思います。
実現方法をアルゴリズムと言いますが、コードの書き方を知っているかどうかは重要ではなく、どういう実現方法があるかを考えられるかが重要であり、楽しい部分でもあるかと思います。
では、最後にここまでのコード全文を載せて、次回は信号機を作ってみたいと思います。
import time
import math
class Clock:
def __init__(self):
self.self_time = 0
self.seconds_counter_one = 0
self.seconds_counter_ten = 0
self.minutes_counter_one = 0
self.minutes_counter_ten = 0
self.hours_counter_one = 0
self.hours_counter_ten = 0
def count_clock(self):
start_time = math.floor(time.time())
while True:
time.sleep(1)
self.self_time = math.floor(time.time()) - start_time
if self.self_time > 86400:
self.self_time = 0
else:
if self.self_time // 3600 == 0:
hours = 0
else:
hours = self.self_time //3600
if (self.self_time - hours * 3600) // 60 == 0:
minutes = 0
else:
minutes = (self.self_time - hours * 3600) // 60
seconds = (self.self_time - hours * 3600 - minutes * 60)
if seconds == 0:
self.seconds_counter_one = 0
self.seconds_counter_ten = 0
else:
self.seconds_counter_ten = seconds // 10
self.seconds_counter_one = seconds - \
self.seconds_counter_ten * 10
if minutes == 0:
self.minutes_counter_one = 0
self.minutes_counter_ten = 0
else:
self.minutes_counter_ten = minutes // 10
self.minutes_counter_one = minutes - \
self.minutes_counter_ten * 10
if hours == 0:
self.hours_counter_ten = 0
self.hours_counter_one = 0
else:
self.hours_counter_ten = hours // 10
self.hours_counter_one = hours - \
self.hours_counter_ten * 10
print("{}{}:{}{}:{}{}".format(self.hours_counter_ten, \
self.hours_counter_one, self.minutes_counter_ten, \
self.minutes_counter_one, self.seconds_counter_ten, \
self.seconds_counter_one))
#オブジェクト作成し、メソッドを実行
my_clock = Clock()
my_clock.count_clock()