LoginSignup
11
16

More than 5 years have passed since last update.

個人的に思うPythonのハマり所と要点

Last updated at Posted at 2018-03-03

説明

Pythonを1年以上仕事で使ってみて思ったハマり所やポイントなどを随時追加していきます。

listやdictなどのミュータブルなデータ型をデフォルト引数値として使いたい時

デフォルト引数の値が計算されるのは定義された時。関数が実行された時ではない。

def hoge(arg, result=[]):
    result.append(arg)
    print(result)

>>> hoge(1)
[1]
>>> hoge(1)
[1, 1]
>>> hoge(1)
[1, 1, 1]

下記のようにすると良い

def hoge(arg, result=None):
    if result is None:
        result = []
    result.append(arg)
    print(result)

>>> hoge(1)
[1]
>>> hoge(1)
[1]
>>> hoge(1)
[1]

if name == 'main':

Pythonを初めて学ぶ人はだいたいナニコレってなると思います。

tmp.py
def hoge():
    print('hoge!')


if __name__ == '__main__':
    print('main!')

$ python tmp.pyとして実行した時、main!が標準出力されます。
tmp.pyが他のモジュールからimportされた時はmain!は出力されません。
tmp.pyがスクリプトとして実行された時、__name__には'__main__'が入ります。

forとwhileループのelse

ループ中でbreakが実行されなかった場合に、elseが実行される。

tryのelse

例外が発生しなかった場合に、elseが実行される。

Shebang

Shebangを書いてPythonモジュールに実行権限をつけると、そのまま実行できる

hello.py
#!/usr/bin/env python3

print('hello world')
$ chmod 755 hello.py
$ ./hello.py
hello world

# coding: utf-8

1行目か2行目に書ける
Python2の場合、デフォルトエンコーディングはascii。エンコーディングを指定する事でPythonインタープリタはそのモジュールがUTF-8で書かれていると判断する。
Python3の場合、デフォルトエンコーディングはUTF-8なので書かなくてもいい。

isと==

isは同じオブジェクトidを持っている場合にTureを返す
==は同じ値の場合にTureを返す

>>> a = 'hoge'
>>> b = a

>>> id(a)
2888814974432
>>> id(b)
2888814974432
# 'hoge'オブジェクトが存在する場所に、変数a, bという付箋を貼っていると考えればよい

>>> b is a
True
>>> b == a
True

だが下記の場合は、

>>> l1 = [1, 2, 3]
>>> l2 = [1, 2, 3]
>>> l1 is l2
False
>>> l1 == l2
True

# なぜならオブジェクトidが違うから
>>> id(l1)
2888833847176
>>> id(l2)
2888833790408

Pythonでは全てがオブジェクトとして実装されている

リスト、辞書、セット、タプルの内包表記

タプルには内包表記は無い。ジェネレーター内包表記になる。

listは順序保持される。dictは保持されない。

dictでも順序保持したいならOrderedDictを使う。

*args **kwargs

def fuga(*args, **kwargs):
    print(args, type(args))
    print(kwargs, type(kwargs))
結果
>>> fuga(1, 2, 3, tom=25, mike=35)
(1, 2, 3) <class 'tuple'>
{'tom': 25, 'mike': 35} <class 'dict'>

浅いコピーと深いコピー

  • 浅いコピー

    • copy.copy()
  • 深いコピー

    • copy.deepcopy()

違いはオブジェクトの中にオブジェクトがあった場合、参照を挿入するか再帰的にコピーするかどうか
https://docs.python.jp/3/library/copy.html

タプルになる場合と文字列になる場合

>>> type(('a',))
<class 'tuple'>
>>> type(('a'))
<class 'str'>

カンマが入るとタプルになる。
後者はpycodestyleのE501 line too longにならないようにするために使う。継続文字のバックスラッシュを使うよりコードが見やすくなると思う。

this_text = ('Beautiful is better than ugly.'
             'Explicit is better than implicit.'
             'Simple is better than complex.'
             'Complex is better than complicated.'
             'Flat is better than nested.'
             'Sparse is better than dense.'
             'Readability counts.....')

マルチバイト文字のlen()

Python2.7の文字列はバイト列。u''をつけることでUnicode文字列になる。

python2.7
# coding: utf-8

print len('あ'), type('あ')
print len(u'あ'), type(u'あ')
結果
3 <type 'str'>
1 <type 'unicode'>

Python3の文字列はUnicode文字列。

python3.6
print(len('あ'), type('あ'))
print(len('あ'.encode('utf-8')), type('あ'.encode('utf-8')))
結果
1 <class 'str'>
3 <class 'bytes'>

Pythonのデストラクタ

__del__で定義できるがあまり使わない方が良いらしい

python2系での__future__モジュール

python3への移行を見据えて、基本的には全てのモジュールで下記を書いておく

from __future__ import absolute_import, division

個人的にはprint_functionも書いている。sep=とかend=とか便利なので。

docstring

関数やクラス、モジュールに書く説明文の事です。
googleスタイルが個人的に好き
ぱっと見でわからないような関数は、概要と引数・返り値の型と例も書いとくと、他の人が読む時に理解が早いです
docstringをしっかり書いておけば、Sphinxとかでドキュメントを簡単に作る事ができます

デコレータ

最初は理解に苦しむ
オライリーの「入門 Python3」の中のデコレーターの説明はとてもわかりやすかった
個人的に使う場面は、キャッシュを使うor使わない場面で簡単に切り替えたい時
デコレータをコメントアウトすることでキャッシュを使わないようにできるので便利

関数内からグローバル変数を書きかえたい時

11
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
16