Pythonで作ったコードを関数にする流れ

Pythonで作ったコードを関数にする流れ Python

Pythonでコードを書いたけれど、長くなって読みにくい。

こういう時はコードを関数化すると読みやすく、管理しやすくなります。

基本的には30行から50行程度のコードでも、処理や変数が複数登場するコードは関数化するとメリットが多いです。積極的に関数化していきましょう。

コードを関数化するメリットとしては、

  • 同じ処理が出てくる場合それを何度も書かなくてよくなる
  • コードを読む人がより処理を理解しやすくなる
  • コード修正時に関数単位で修正すればいいので負担が減る
  • 変数が複数ある場合、変数を修正の度に複数個所を変更しなくて済むので楽ちん

など色々あります。

特に、同じ変数を複数個所に書いたり、同じ処理をコピーして何度も書くことはプログラムを書く際にはバグの温床となりやすいため避けたほうがよいので、繰り返し同じ処理が出てくる場合には関数にするのがベターです。

結果としてコードを関数化すると、

書きやすくなり、読みやすくなり、修正しやすくなる

ということで恩恵は大きいです。

ですが、Pythonを学びはじめたうちは、どうやって関数化すればいいのかの流れが分からないという方も多いです。

そこで、今回は自分の書いたコードを関数化する方法についてシンプルに解説していきます。

関数化する手順はこの3段階

結論から言うと、関数化の流れは以下3段階に分けて考えると分かりやすいです。

  • ①処理単位ではなく、機能単位でひとまとまりにして関数化する。
  • 繰り返し入力しないといけない「変数」を見つけてそれを関数の引数にする
  • 実行部分を書く

上記のような流れで関数化していきます。

①についてですが、一つ一つの処理単位であんまり細かく関数化してしまうと、修正する際にその関数の数だけテストする必要が出てくるので大変になってきます。

なので、機能単位で処理をまとめて関数化するようにするのがコツです。

これだけだと分からないので具体的に見ていきます。

今回、関数化するコード

今回説明に使っていくのは下記のコードとなります。

# ライブラリをインポート
from bs4 import BeautifulSoup
import requests
import openpyxl

# 調べたいデータを指定
code = 調べたい銘柄コード
year = 調べたいデータの年号

# URLを取得
url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
title = soup.select_one("span.jp").text

# 株価を取り出す
all_tr = soup.find_all('tr')

#Excelファイルを作成
wb = openpyxl.Workbook()
ws = wb.active
ws.title = str(title)
ws['A1'].value = '日付'
ws['B1'].value = '始値'
ws['C1'].value = '高値'
ws['D1'].value = '安値'
ws['E1'].value = '終値'
ws['F1'].value = '出来高'
ws['G1'].value = '終値調整'

# 書き込み
for i in range(1,len(all_tr)):
    tr = all_tr[i].find_all('td') #リスト型
    for n,td in enumerate(tr, 1):
        new_cell = ws.cell(row=(i+1), column=n)
        new_cell.value = td.text

# ワークブックをExcelファイルとして保存
wb.save(str(title)+'.xlsx')

なお、ここではコードの意味が分からなくても関数化する流れだけ分かるように解説していきます。

上記コードはURLから株価を取得して、その値をエクセルに書き出して保存するコードになります。

それでは関数化する流れを見ていきます。

①機能単位で関数化する。

コードをざっと見ると

URLから株価をスクレイピングで取得している部分」と、「エクセルファイルを使って取得した株価を保存している部分」に機能を分けることができますよね。

このように機能単位をひとまとめにして関数化するのがコツです。

(もしもコードの順番がごちゃごちゃになっている場合はまず機能単位にコードをまとめる作業をします。)

 

では、機能単位で関数化していきましょう。

下記がURLから株価をスクレイピングで取得している部分です↓

#調べたいデータを指定
code = 調べたい銘柄コード
year = 調べたいデータの年号

#URLを取得
url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
title = soup.select_one("span.jp").text

#株価を取り出す
all_tr = soup.find_all('tr')

まずはこれを関数化します。

Pythonでの関数の定義は下記のような形でしたよね。

関数の定義

この形にしていきます。関数名はなんでもいいですが、今回はとりあえずstock_valueにします。

#調べたいデータを指定
code = 調べたい銘柄コード
year = 調べたいデータの年号

def stock_value():

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')

とりあえず返り値を返さない形で書いてみました。

 

ただ、取り出した株価のall_trは次の関数の中でエクセルに記入したいのと、次のエクセルの処理の中で変数titleを使うので、all_trとtitleを返り値にしてあげる必要があります。

ポイント
今作っている関数より下のコードで現在の関数内の処理で得られる値が必要な場合は返り値をその得られる値にします。

そのように修正すると、下記のようになります。

#調べたいデータを指定
code = 調べたい銘柄コード
year = 調べたいデータの年号

def stock_value():

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')
    return all_tr, title

次にエクセルファイルに書き込む部分する関数化していきます。
関数名はmake_excelとします。

 

今回は、エクセルに何を書き込むのか?の「何を」の部分を関数の引数とします。

引数名は何でもいいです。とりあえずstock_listとします。

この引数は実際には先ほど作ったstock_value関数の返り値を受け取ることになります。

def make_excel(stock_list):
    #Excelファイルを作成
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = str(title)
    ws['A1'].value = '日付'
    ws['B1'].value = '始値'
    ws['C1'].value = '高値'
    ws['D1'].value = '安値'
    ws['E1'].value = '終値'
    ws['F1'].value = '出来高'
    ws['G1'].value = '終値調整'

    # 書き込み
    for i in range(1,len(stock_list)):
        tr = stock_list[i].find_all('td') #リスト型
        for n,td in enumerate(tr, 1):
            new_cell = ws.cell(row=(i+1), column=n)
            new_cell.value = td.text

    # ワークブックをExcelファイルとして保存
    wb.save(str(title)+'.xlsx')

エクセルファイルに保存して終わりなので、返り値はいりません。

こんな感じで2つの処理のコードの関数化ができました。

②繰り返し入力しないといけない「変数」を見つけてそれを関数の引数にする

株価を取り出す部分についてのコードについて見ていくと…

#調べたいデータを指定
code = 調べたい銘柄コード
year = 調べたいデータの年号

def stock_value():

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')
    return all_tr, title

下記の変数の部分が関数の外に出てしまっています。

code = 調べたい銘柄コード
year = 調べたいデータの年号

こういう形で関数の外に出ている変数をグローバル変数と言います。

グローバル変数は関数の引数にしたほうが管理が楽ですし、コードが複雑になった場合に支障が少なくなります。

実際にグローバル変数を引数にした形に書き直すと、

#調べたいデータを指定
def stock_value(code, year):

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')
    return all_tr, title

こうなります。

あとはここまでをまとめてみます。

# ライブラリをインポート
from bs4 import BeautifulSoup
import requests
import openpyxl

# 株価を調べる関数
def stock_value(code, year):

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')
    return all_tr, title

# エクセルファイルに株価を書き込んで保存する関数
def make_excel(stock_list):
    #Excelファイルを作成
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = str(title)
    ws['A1'].value = '日付'
    ws['B1'].value = '始値'
    ws['C1'].value = '高値'
    ws['D1'].value = '安値'
    ws['E1'].value = '終値'
    ws['F1'].value = '出来高'
    ws['G1'].value = '終値調整'

    # 書き込み
    for i in range(1,len(stock_list)):
        tr = stock_list[i].find_all('td') #リスト型
        for n,td in enumerate(tr, 1):
            new_cell = ws.cell(row=(i+1), column=n)
            new_cell.value = td.text

    # ワークブックをExcelファイルとして保存
    wb.save(str(title)+'.xlsx')

こうなりますね。

このままだと実際には何も実行されないので、次は実行部分を書きます。

③実行部分を書く

最後は実行部分を書いていきます。

関数の引数に実際に値を入れていくだけです。

今回は2019年の銘柄コードが6875のメガチップスの株価を取得してエクセルに保存しようと思います。

if __name__ == '__main__':
    # 株価を取得
    stockvalue = stock_value(6875, 2019)
    # 株価をエクセルに書き込んで保存
    make_excel(stockvalue)

上記のようになります。

if __name__ == '__main__':

の意味については

を読んでみて下さい。

if __name__ == '__main__':

の次に続く処理はインデントしてあげる必要があります。

さて、ここまでのコードをまとめると、

下記のようになります。

# ライブラリをインポート
from bs4 import BeautifulSoup
import requests
import openpyxl

# 株価を調べる関数
def stock_value(code, year):

    #URLを取得
    url = "https://kabuoji3.com/stock/"+str(code)+"/"+str(year)+"/"
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15"}
    soup = BeautifulSoup(requests.get(url, headers = headers).content,'html.parser')
    title = soup.select_one("span.jp").text

    #株価を取り出す
    all_tr = soup.find_all('tr')
    return all_tr, title

# エクセルファイルに株価を書き込んで保存する関数
def make_excel(stock_list):
    #Excelファイルを作成
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = str(title)
    ws['A1'].value = '日付'
    ws['B1'].value = '始値'
    ws['C1'].value = '高値'
    ws['D1'].value = '安値'
    ws['E1'].value = '終値'
    ws['F1'].value = '出来高'
    ws['G1'].value = '終値調整'

    # 書き込み
    for i in range(1,len(stock_list)):
        tr = stock_list[i].find_all('td') #リスト型
        for n,td in enumerate(tr, 1):
            new_cell = ws.cell(row=(i+1), column=n)
            new_cell.value = td.text

    # ワークブックをExcelファイルとして保存
    wb.save(str(title)+'.xlsx')

# 実行部分
if __name__ == '__main__':
    # 株価を取得
    stockvalue = stock_value(6875, 2019)
    # 株価をエクセルに書き込んで保存
    make_excel(stockvalue)

実行部分だけを見るとすごくシンプルになったことが分かりますね。

これでコードの運用をより楽にすることができました。

実際に実行してみると

株価データ

ちゃんと株価がエクセルに出力されて保存されました。

まとめ

書いたコードを関数化する時にやることは以下の流れになります。

  • ①処理単位ではなく、機能単位でひとまとまりにして関数化する。
  • 繰り返し入力しないといけない「変数」を見つけてそれを関数の引数にする
  • 実行部分を書く

関数化の流れは以上です。

慣れてきたら細かい手順をショートカットして関数化できるようになっていきますのでぜひ試してみて下さい。

コメント

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