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

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


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

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

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

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

下記のようにすると良い

```python
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を初めて学ぶ人はだいたいナニコレってなると思います。

```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モジュールに実行権限をつけると、そのまま実行できる

```python:hello.py
#!/usr/bin/env python3

print('hello world')
```

```sh
$ 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を返す

```python
>>> a = 'hoge'
>>> b = a

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

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

だが下記の場合は、

```python
>>> 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

```python
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

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

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

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

```python
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文字列になる。

```python:python2.7
# coding: utf-8

print len('あ'), type('あ')
print len(u'あ'), type(u'あ')
```

```:結果
3 <type 'str'>
1 <type 'unicode'>
```

Python3の文字列はUnicode文字列。

```python: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への移行を見据えて、基本的には全てのモジュールで下記を書いておく

```python
from __future__ import absolute_import, division
```

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



## docstring

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



## デコレータ

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



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