[JAWS-UG CLI] Lambda Blueprint解説: Python2.7 基礎

LambdaのPython初心者向け解説です。

- Lambda Blueprint解説: Lambda共通編 (Python): http://qiita.com/tcsh/items/e119d7fd8257e15e599b

- Lambda:#16 sns-message (Python版): http://qiita.com/tcsh/items/c776221b000e5f921fcc
- Lambda:#15 canary (Python版): http://qiita.com/tcsh/items/15815f61df418fbe6be7


# 基礎

コメント
--------------

\#から行末がコメントとして無視される。

```python:コード(行コメント):
   word = 'hello'   #対象のワード
```

複数行をコメントアウトする場合、前の行のインデントと同じ位置で、シングルクォートもしくはダブルクォートを3つでコメント部分を挟む。 (文字列として扱われるため実行されない。)

```python:コード(事実上の複数行コメント):
   def validate(res):
     '''[ここから] Return False to trigger the canary

     Currently this simply checks whether the EXPECTED string is present.
     However, you could modify this to perform any number of arbitrary
     checks on the contents of SITE.
     [ここまで]'''
     return EXPECTED in res
```

変数(定数)
----------------------

Pythonは定数をサポートしていない。 

慣習的に定数を大文字で記述する(らしい)。

```python:コード(例):
   SITE = 'https://www.amazon.com/'  # URL of the site to check
   EXPECTED = 'Online Shopping'  # String expected to be on the page
```

関数の外で宣言されている場合、スコープはこのモジュール(ファイル)全体になる。


in演算子
--------------

ある値が存在するかどうかを調べる。

```python:コード(関数の返り値での利用例):
   return EXPECTED in res
```

resオブジェクト内に定数EXPECTEDで定義した文字列が存在するかどうかを調べる。


# モジュール

インポート方法
--------------------------

from:   パッケージやモジュール名を指定する。

import:   パッケージやモジュール名、またはクラスや関数名、変数名などを指定する。

```python:datetimeモジュールからdatetime関数オブジェクトをインポートする:
from datetime import datetime
```

```python:urllib2モジュール(Python2用)からurlopen関数オブジェクトをインポートする:
from urllib2 import urlopen
```

注釈: urllibモジュールは、Python3でurllib.request,urllib.parse,urllib.parse に分割された。


futureモジュール
----------------------------

Python3に実装されている、Python2と互換性のない機能をPython2で使用できるようにする。

```python:コード(例):
from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

from future_builtins import *
```

注釈: from __future__ import * は定義できない。


futureモジュール (print_function)
---------------------------------------------

Python2ではprint文だったが、Python3では関数print()になった。

下記を記述することで、Python3互換のprint()が使えるようになる。

```python:コード(例):
from __future__ import print_function
```

# 関数

print()
-------------

Python3ではprint()で、文字列オブジェクトの内容を出力する。

```python:コード(例):
   print('hoge')
   print('hoge' + variable_a)
   print('a: [', variable_a, ']')
```

```python:コード(printの末尾指定例):
   print('hoge', end='')
```

```python:コード(ファイル出力例):
   f = open('test.txt', 'w')
   print('hoge', file=f)
```

datetime.now()
--------------------

datetimeオブジェクトに含まれるメソッド。 現在のローカルな日付および時刻を返す機能を提供する。

```python:コード(例):
datetime.now()
```

```python:結果(例):
   datetime.datetime(2016, 5, 29, 18, 52, 57, 727727)
```

注釈: 年、月、日、時、分、秒、マイクロ秒


str()
-----------

オブジェクトを印字可能な形に表現した文字列を返す。

```python:コード(例):
   print(str(datetime.now()))
```

```python:結果(例):
   2016-05-29 18:52:57.727714
```

urlopen()
---------------

urllib2モジュールに含まれるオブジェクト。 Web上のコンテンツを取得する機能を提供する。

取得したレスポンスはファイルライクオブジェクトなので、read()で読み取ることができる。

```python:コード(例):
   if not validate(urlopen(SITE).read()):
```

ユーザ定義関数
--------------------

ユーザが独自に関数を定義できる。

```python:構文:
   def 関数名(引数):
     記述

     return 返り値
```

returnステートメントの記述が無い場合、'None'を返す。

```python:コード(例):
   def validate(res):
     # (snip)
     return EXPECTED in res
```

- 引数: res
- 返り値: Bool値 (resの中にEXPECTEDの文字列があるかどうか)

```python:コード(例):
   def lambda_handler(event, context):
     # (snip)
```

- 引数: eventとcontext
- 返り値: None


# 制御構文

if文
--------------

条件により分岐することができる。

```python:構文:
   if (条件):
     記述

   elif (条件):
     記述

   else:
     記述
```

```python:サンプル:
   if not validate(urlopen(SITE).read()):
       raise Exception('Validation failed')
```



# 例外関連

try文
---------------

例外を取得し、発生に応じて処理することができる。

```python:構文:
   try:
     例外が発生しうる記述

   except:
     例外が発生した場合の記述 (例外型毎に複数記述可能)

     組み込み例外: http://docs.python.jp/2/library/exceptions.html

   else:
     例外が全く発生しなかった場合の記述

   finally:
     例外が発生したかどうかに関わらず、try文を抜ける前に常に実行される動作の記述
```

```python:サンプル:
   def lambda_handler(event, context):
     print('Checking {} at {}...'.format(SITE, event['time']))
     try:
         if not validate(urlopen(SITE).read()):
             raise Exception('Validation failed')

     except:
         print('Check failed!')
         raise

     else:
         print('Check passed!')
         return event['time']

     finally:
         print('Check complete at {}'.format(str(datetime.now())))
```

### tryステートメントとexceptステートメントの部分

(後述のExceptionクラスとraiseステートメントを参照)

### elseステートメントの部分

```python:コード(例):
   else:
       print('Check passed!')
       return event['time']
```

validate()がFalseでない場合、print文を実行し、eventデータのtimeキーの値を返す。

### finallyステートメントの部分

```python:コード(例):
   finally:
         print('Check complete at {}'.format(str(datetime.now())))
```

'Check complete at 今の時刻' が標準出力に出力される。

```python:結果(例):
   Check complete at 2016-05-29 18:00:15.508132
```


モジュール: Exceptionクラス
---------------------------

exceptionモジュールに含まれる例外クラスの1つ。 
exceptionモジュールはインポート不要。

組み込み例外: http://docs.python.jp/2/library/exceptions.html

```python:コード
raise Exception('Validation failed')
```

全ての組み込み例外のうち、システム終了でないものはこのクラスから導出されている。
全てのユーザ定義例外はこのクラスの派生クラスであるべき。


ステートメント: raise
---------------------

意図的に例外を発生したい場合に利用する。

単体で利用すると、即時に例外を送出する。

try .. exception文で利用する場合、try文にraiseで送出したい例外を定義し、except句の中で'raise'を記述することで、実際に例外を返す。

```python:コード(例):
   try:
       if not validate(urlopen(SITE).read()):
           raise Exception('Validation failed')
```

validate()がTrueでない場合、例外(Exceptionクラス'Validation failed'を送出する)を定義をする。

```python:コード(例):
   except:
       print('Check failed!')
       raise
```

例外が発生した場合、print文を実行し、try文で定義した例外を発生させる。


# メソッド

文字列オブジェクト.format()
-------------------------------------

文字列オブジェクトに対して、複雑な変数置換と値の書式指定をする機能を提供する。

```python:コード(例):
   print('Checking {} at {}...'.format(SITE, event['time']))
```

```python:結果(例):
   'Checking サイトのURL at 時刻...'
```

ファイルオブジェクト.read()
-------------------------------------

ファイルオブジェクトに含まれるメソッド。 ファイル内容を読み出す機能を提供する。

```python:コード(例):
   if not validate(urlopen(SITE).read()):
```