読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

便利なPythonTips10選

今回のエンジニアブログを担当する藤岡です。
宜しくお願い致します。

Pythonには「電池付属("Battery Included")」の概念があり、様々な機能がディストリビューションに含まれています。
痒いところに手が届く言語なのではないかと感じております。

今回は、私がPythonでコーディングしてきて役に立つと思ったTipsを幾つかご紹介したいと思います。
※ 対話モードでの実行結果になります。


1, 文字列埋め込み

文字列内に変数を埋め込む機会は多いかと思います。
format()はコーダーに対して分かりやすい形で文字列埋め込みを行ってくれます。

>>> str = u'{0} the {1}.'.format(u'Feel', u'Wonder')  
>>> print str  
Feel the Wonder.  
  
>>> str = u'{hoge} the {fuga}.'.format(fuga=u'Wonder', hoge=u'Feel')  
>>> print str  
Feel the Wonder.  

どちらの方法でも同じ結果にはなりますが、後者の方が分かりやすく感じます。

2, アクセス修飾子

Pythonにはprivateやprotectedといったアクセス修飾子がありません。
その代わりに「_(アンダーバー)」を規則とし、アクセス制限をかけています。

>>> class Foo:  
...     def __init__(self, str):  
...         self._hoge = str  
...         self.__hoge = str  
...  
>>> spam = Foo(u'Spam')  
>>> print spam._hoge  
Spam  
>>> print spam.__hoge  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
AttributeError: Foo instance has no attribute '__hoge'  

「_(アンダーバー一つ)」だと明示的なアクセス制限(一応外部からのアクセスは可能)、
「__(アンダーバー二つ)」だとさらに厳しいアクセス制限を設定する事が可能です。

モジュール内でのみ使用する変数やメソッドにはいつも「__(アンダーバー二つ)」をつけております。

3, namedtuple

タプルに名前を持たせる事が可能になります。
各カラム名をリストとして取得する事が出来るので、CSVアウトプット等、役に立つ部分は多かったです。

>>> from collections import namedtuple  
>>> model = namedtuple('spam', ['ham', 'egg'])  
>>> hoge = model(ham='ham', egg='egg')  
>>> print hoge.ham  
ham  
>>> print hoge.egg  
egg  

またフィールド名を纏めて取得する事が可能なので、CSVのカラム名を設定する際便利でした。

>>> print hoge._fields  
('ham', 'egg')  
  
>>> for v in hoge._fields:  
...     # CSV書き込み等の処理...  

4, リストの内包表記

Pythonではリスト、辞書をfor文で扱う際に内包表記が可能となっています。
一行で書けるのでコードがスッキリします。

# 通常のループ文  
>>> [x ** 2 for x in [2, 4, 6, 8]]  
[4, 16, 36, 64]  
  
# 二重ループ  
>>> [x + y for x in range(3) for y in [1, 2, 3]]  
[1, 2, 3, 2, 3, 4, 3, 4, 5]  
  
# フィルタリングも可能  
>>> [x for x in [1, 2, 3, 4, 5] if x % 2 == 0]  
[2, 4]  

こんな感じに。
あまりに横に長いと見づらいので注意しましょう。

5, enumerate

for文内でシーケンスのインデックスにアクセスできる機能です。
シーケンスのすべての要素に対して、要素番号付属で何らかの処理を行いたいとき、便利です。

>>> list = [u'spam', u'egg', u'ham']  
>>> for i, v in enumerate(list):  
...     print i, v  
...  
0 spam  
1 egg  
2 ham  

6, 例外処理

アプリケーションを作成する上で例外処理は欠かせません。
throw Exceptionと書くところをPythonではraiseキーワードを用います。
raiseは受け取った例外を伝える役割を持っています。
raise の引数はそれぞれ、例外の型を表すオブジェクト、例外オブジェクトに渡す引数、トレースバック情報となります。

>>> if hoge is None:  
...     raise RuntimeError('hoge is required.')  
...  
Traceback (most recent call last):  
  File "<stdin>", line 2, in <module>  
RuntimeError: hoge is required.  
  
>>> def raise_func():  
...     raise Exception, 'error'  
  
>>> def raise_func():  
...     raise Exception('error')  
  
# どちらも同じ結果になる。  
# 後者の記法が許されるのはExceptionがクラスであるため。  

7, passキーワード

passキーワードはなにもしません。
ですが、新しくコードを記述していた場合に関数、クラスまた条件文の中身として扱うことが多いです。
関数、クラスまた条件文に具体的な実装をする必要が無くなるので、大まかな実装をする時に役立ちます。

>>> class Foo:  
...     pass # 後々実装すること  
  
>>> def foo_func(*args):  
...     pass # 忘れず実装すること  

8, isと==の違い

>>> if hoge == None:  
...    pass  
  
>>> if hoge is None:  
...    pass  

上記のコードは同じ用に動作しますが、isと==は違うものです。

・isはメモリ上の同じアドレスに存在する同一のものか比較
・==は値が同一か比較
という用に機能が分けられています。

>>> hoge = 'spam'  
>>> fuga = 'spam'  
>>> foo = 'spam'  
>>> hoge is fuga is foo  
True  
>>> [a, b] is [a, b]  
False  
>>> [a, b] == [a, b]  
True  

プリミティブ型はisで比較しても==で比較しても良いですが、リストやタプルはisだと上手く比較出来ない、という事です。

9, ConfigParser

Configファイルを読み込み、パースしてくれる機能です。

[SUKIYAKI]  
FAVORITE=beef  
EGG_NUM=2  
>>> from ConfigParser import ConfigParser  
>>> config = ConfigParser()  
>>> config.read('food.ini')  
>>> for section in config.sections():  
...     print '[%s]' % (section)  
...  
[SUKIYAKI]  
  
>>> for item in config.items('SUKIYAKI'):  
...     print item  
...  
('favorite', 'beef')  
('egg_num', '2')  
  

SUKIYAKIというセクションから、タプル型で中身を取り出しています。
Configファイルを作る機会は多いと思うので、スマートにパースしてくれるConfigParserは便利に感じます。

10, with構文

with構文は、機能の利用者が、安全かつ簡潔にその機能を使えるようにしてくれる構文です。

>>> with open("sample.txt") as f:  
...     print(f.read())  
  
>>> f = open("sample.txt")  
>>> print(f.read())  
>>> f.close()  

この二つのコードは同等の意味を持ちます。
with構文を使っているコードのほうが一行分簡潔ですね。
with構文を使うと、close()記述が不要になります。ブロックを抜けると、自動的にclose()してくれるのです。

with構文は複数定義することが可能です。
ファイルを一気に二つ開いて処理を行うときにも、with構文を使えばこんな感じに。

 # 二つのファイルを読み込み、表示  
>>> with open("foo.txt", "r") as f1, open("bar.txt", "r") as f2:  
...    print(f1.read())  
...    print(f2.read())  

ファイル操作を行う場合はwith構文を使っておけば安泰だと思われます。


以上になります。
わりと有名な機能を纏めただけのエントリになってしまいましたが、私自身がPythonで実装をしていく上でとても役に立った機能達でした。