シェルスクリプトマガジン

Pythonあれこれ(Vol.77掲載)

著者:飯尾 淳

本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温
かく見守ってください。皆さんと共に勉強していきましょう。第7回は、Pythonで実装されたWebアプリケーションフレームワーク「Flask」の使い方と、Pythonのユニークな文法である「デコレータ」について紹介します。

シェルスクリプトマガジン Vol.77は以下のリンク先でご購入できます。

図5 ルーティングのサンプルWebアプリケーションのコード

from flask import Flask
app = Flask(__name__)
@app.route('/hello')
def hello_flask():
  return '<h1>Hello, Flask!</h1>'
@app.route('/goodbye')
def goodbye_flask():
  return '<h1>Good bye, Flask!</h1>'

図7 簡単なメッセージを表示するプログラム

#!/usr/bin/env python

def hello():
  print('Hello, World')
def goodbye():
  print('Goodbye, World')
def main():
  hello()
  goodbye()
if __name__ == '__main__':
  main()

図9 デコレータを追加したプログラム

#!/usr/bin/env python

def deco(func):
  def decorator():
    print('-- start --')
    func()
    print('-- end --')
  return decorator
@deco
def hello():
  print('Hello, World')
@deco
def goodbye():
  print('Goodbye, World')
def main():
  hello()
  goodbye()
if __name__ == '__main__':
  main()

図11 Flaskのルーティング設定処理を模したプログラム

#!/usr/bin/env python
 
class Flask():
  def __init__(self):
    self.url_map = {}
    print(f'url_map on init: {self.url_map}')
  def add_url_rule(self, rule, func):
    self.url_map[rule] = func
  def route(self, rule):
    def decorator(f):
      self.add_url_rule(rule, f)
      return f
    return decorator
  def dispatch_request(self, rule):
    return self.url_map[rule]()

app = Flask()
print(f'url_map after create: {app.url_map}')
@app.route('/index')
def index():
  print("hello world")
print(f'url_map after function def: {app.url_map}')
app.dispatch_request('/index')

図13 図9のプログラムを修正した「greeting_deco2.py」

#!/usr/bin/env python
 
def deco(rule):
  def decorator(func):
    print(f'rule = \'{rule}\', func = {func}')
    return func
  return decorator
@deco('/hello')
def hello():
  print('Hello, World')
@deco('/goodbye')
def goodbye():
  print('Goodbye, World')

図15 デコレータを使わないように修正した「greeting_deco3.py」

#!/usr/bin/env python

def deco(rule):
  def decorator(func):
    print(f'rule = \'{rule}\', func = {func}')
    return func
  return decorator
def hello():
  print('Hello, World')
hello = deco('/hello')(hello)
def goodbye():
  print('Goodbye, World')
goodbye = deco('/goodbye')(goodbye)

図16 関数の挙動を変えるデコレータの使用例

#!/usr/bin/env python

def plus_n(n):
  def decorator(func):
    def func_modified(*args, **kwargs):
      return (func(*args, **kwargs) + n)
    return func_modified
  return decorator
@plus_n(3)
def square(x):
  return x*x
def main():
  print(square(2))
if __name__ == '__main__':
  main()

図17 関数に複数のデコレータを適用したプログラム「greeting_deco4.py」

#!/usr/bin/env python

def DECO(func):
  def decorator():
    print('-- START --')
    func()
    print('-- END --')
  return decorator
def deco(func):
  def decorator():
    print('-- start --')
    func()
    print('-- end --')
  return decorator
@DECO
@deco
def hello():
  print('Hello, World')
def main():
  hello()
if __name__ == '__main__':
  main()