Python

定型処理は関数にまとめる【自動クラムシェルモードにするプログラム】

Python

[PR]当サイトはアフィリエイト広告を利用しています。

前回はPythonでWindows11のノートパソコンを自動でクラムシェルモードにするプログラムを作成しました。

あれで完成じゃないの?

あれでも動くからいいんだけど、プログラムっていうのは基本的に同じことをズラズラ書かないほうがいいとされているんだよね。前回の完成したプログラムを見てみよう。

import datetime
import subprocess

dt_now = datetime.datetime.now()

if dt_now.hour>18:
   subprocess.call('powercfg /SETACVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 0')
   subprocess.call('powercfg /SETDCVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 0')
elif dt_now.hour<8:
   subprocess.call('powercfg /SETACVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 0')
   subprocess.call('powercfg /SETDCVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 0')
else:
   subprocess.call('powercfg /SETACVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 1')
   subprocess.call('powercfg /SETDCVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION 1')

これで同じ命令が何回も出ていて、読むのも書くのも面倒だなあって部分がない?

subprocess.callが何回も出てくるね

正解。まあコピペして、0か1かの数値の部分だけ変えれば済む話なんだけど、なんかゴチャゴチャして読みにくいよね。

こういう時は「関数」を使うよ。これから説明していくね。

初歩的な関数の使い方

いきなり電源管理をいじるプログラムで関数を使う前に、簡単な関数を使ったプログラムを解説していきます。次のプログラムは受け取る数値が0か1かで「こんにちは」「こんばんは」と出力するプログラムです。

def hello(t):
    if t==0:
        print("こんにちは")
    elif t==1:
        print("こんばんは")
    else:
        print("時間がわからないよ")
hello(0)

プログラムを解説していきます。まずhello(0)の数値をhello(1)とかhello(2)と入力して出力を見てみましょう。hello()の数値を変えると出力が変わりますね。関数とはこうやって名前で呼び出して()の中に何らかの値を入れて、何らかの出力を得る仕組みです。

使いたいのはhello(0)の部分なんだね。

上のdef hello(t)の部分を解説していきましょう。defはおまじないだと思ってください。「これから関数を作りますよ」とコンピューターにお知らせするようなものです。

helloは「関数名」です。これで関数を呼び出します。呼び出すというのはhello(0)のように関数を使うことです。

()の中のtを引数ひきすう)と呼びます。ここに記述したtは関数の中で変数tとして働きます。ただしtはdefの中だけで有効です。関数を呼び出すときに引数の部分に入れた数値(0とか1とか2とか)は関数を呼び出したときにtに代入されて動きます。hello(0)ならここの部分が動いたときt=0と代入されます。

関数本体を見てみましょう。前回やったif, elif, elseの構文ですね。最初にt==0という条件式が実行されます。これが0なら「こんにちは」が出力されます。1ならelifに移って「こんばんは」が出力されます。0か1でないならelseが実行されて「時間がわからないよ」が出力されます。

そしてインデントがdefと同じ深さに戻ります。戻ったらdefは終わりです。関数が出来上がりました。

最後にhello(0)で関数を呼び出しています。

関数はこのように「ある処理をひとまとまりのセットにして、名前を呼ぶだけで使える」機能です。

いまいちメリットがわからないんだけど…

例えばコピペして長い処理を何度も書いていた前回のプログラムは、長いテキストをコピーして0か1かを書き換えていました。間違えなければ済むだけですが、よくやりがちなのは書き換える時にデリートキーを間違って入力して、テキストの余計な部分を消してしまう、なんてことが起こりえます。

プログラムは一文字間違っただけで動かなくなります。すると、長いテキストを読み直して「どこだどこだ」と辛い検証の海を漂わなければいけなくなるでしょう。

こういう辛い作業は関数にまとめて、関数が正常に動けば他の部分も間違わずに動く、みたいな状態にしておいた方が、プログラムは読みやすく、作りやすくなります。長い似たような処理は関数にまとめましょう。

電源管理のプログラムを関数でスッキリさせる

では前回のクラムシェル化のための電源管理のプログラムを関数でスッキリさせましょう。

import datetime
import subprocess

dt_now = datetime.datetime.now()
def change(t):
   if t==0:
      subprocess.call('powercfg /SETACVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION ' + str(0))
      subprocess.call('powercfg /SETDCVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION ' + str(0))
   elif t==1:
      subprocess.call('powercfg /SETACVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION ' + str(1))
      subprocess.call('powercfg /SETDCVALUEINDEX SCHEME_CURRENT SUB_BUTTONS LIDACTION ' + str(1))
   else:
      print("0か1を入力してください")   
if dt_now.hour>18:
   change(0)   
elif dt_now.hour<8:
   change(0)
else:
   change(1)

電源プランが変わったかどうかは前回の記事を参考にやってみてください。

かえってプログラムが長くなっちゃったような…

まあそうなんだけどね。上のプログラムくらいなら関数を使う必要はあんまりないんだ。でも「似たような処理を何度も呼び出すときは関数を使う」ということはプログラムの基本だから覚えておいてね。

一応プログラムの解説もしていきます。

上のプログラムの関数名はchangeです。引数はtです。tが0なら「LIDACTION 0」を使います。tが1なら「LIDACTION 1」を使います。

「+ str(0)」の部分は「文字列結合」です。文字列に「+」記号を使うと文字列を結合します。

str()は()の中に数値を入れるとそれを文字列の数値に変換する命令文です。数値と文字列を「+」で繋ぐとエラーになるので、数値を文字列に変換して結合します。

あとは前回やったようにif文で時間で分岐させて、0を入れるか1を入れるか判断するという話になります。

if文は見やすく、小さくなったね

これだとプログラムの中で、その部分が何の処理をやっているかわかりやすくなるよね。関数はこういうメリットもあるんだ。関数にできそうな部分を見つけたら、積極的に関数化しよう。

まとめ

今回はクラムシェル化するときの電源管理のプログラムを題材に関数の使い方を解説しました。関数についてまとめると次のようになります。

  • ある処理をひとまとまりのセットにして、名前を呼ぶだけで使える
  • 関数が正常に動けば他の部分も間違わずに動くようにしておいた方がいい
  • 似たような処理を何度も呼び出すときは関数を使う
  • 関数を使うとその部分が何の処理をやっているかわかりやすくなる

関数を使いこなしてわかりやすいプログラムを書けるようになろう!

当ブログ(シルルスのコードおきば)ではPython入門用の記事を他にも執筆しています。参考になりましたら幸いです。

●Pythonでは日本語変数も使える【変数基礎】

●条件分岐で決まった時間帯にPCの電源モードを変える

●【繰り返し】でトマトの収穫時期を予想する

●補数を使って引き算【原理的なところも解説】