PythonとPypIのおしえてA・B・C

以下は[An A-Z of useful Python tricks](https://medium.freecodecamp.org/an-a-z-of-useful-python-tricks-b467524ee747)の日本語訳です。

# An A-Z of useful Python tricks

Pythonは、以下のような理由によって、最も人気と需要のあるプログラミング言語のひとつです。

・学習が簡単
・多目的
・膨大なモジュールとライブラリが存在する

私はデータサイエンティストとしてPythonを日夜使っていて、もはや仕事に必要不可欠な要素です。
使っていて幾つか便利なトリックやtipsを発見してきたので、そのいくつかをA-Z形式で共有したいと思います。

ここでいう"トリック"のほとんどは、仕事中に遭遇したり使ってきたりしたものです。
いくつかは[Python標準Library](https://docs.python.org/3/library/index.html)に書かれているもので、その他のいくつかは[PyPi](https://pypi.org/search/)で見つけたものです。
しかし、真に栄誉が与えられるべきは[awesome-python.com](https://awesome-python.com/)です。
これは興味深いPythonツールやモジュールへの多数のリンク集で、インスピレーションを得るためにも彷徨ってみる価値はあります。


## all or any

Pythonが普及している理由の一つは、読みやすく表現力があるからです。

Pythonは[実行可能な擬似コード](https://www.artima.com/intv/tippingP.html)などと言われることもあります。
つまりは、そのようなコードを書くことができるということです。

```python
x = [True, True, False]
if any(x):
    print("At least one True")
if all(x):
    print("Not one False")
if any(x) and not all(x):
    print("At least one True and one False")
```

## bashplotlib

コンソールにグラフを表示したいですか？

```bash
$ pip install bashplotlib
```

コンソールにグラフを表示できます。

## collections

Pythonにはいくつものデータ型がデフォルトで存在しますが、時にはいずれもしっくりこないこともあるでしょう。
幸いなことに、標準ライブラリで[Collecntionsモジュール](https://docs.python.org/3/library/collections.html)が提供されています。
この便利なアドオンは、さらに多様なデータ型を提供します。

```python
from collections import OrderedDict, Counter

# 順序付き辞書
x = OrderedDict(a=1, b=2, c=3)
# 出現文字数
y = Counter("Hello World!")
```

## dir

Pythonオブジェクトがどのような属性を持っているか知りたいと思ったことはありますか？
もちろんあります。

```python
>>> dir()
>>> dir("Hello World")
>>> dir(dir)
```

Pythonをインタラクティブに実行しているときや、オブジェクトとモジュールを動的に探したいときなどに便利な機能です。
詳細は[マニュアル](https://docs.python.org/3/library/functions.html#dir)を見てください。

## emoji

絵文字？
[絵文字](https://pypi.org/project/emoji/)。

```bash
$ pip install emoji
```

使ったことがないなんていわないでください。

```python
from emoji import emojize
print(emojize(":thumbs_up:"))
```

![01.png](https://qiita-image-store.s3.amazonaws.com/0/26088/c15800ec-60af-53f8-bee9-2a11a6cd3da3.png)

## from __future__ import

Pythonの人気の理由のひとつは、常に新しいバージョンが開発中であるということです。
新しいバージョンは、新しい機能を提供します。
あなたのバージョンがサポート対象外にならないかぎり。

恐れることはありません。
[\_\_future\_\_モジュール](https://docs.python.org/2/library/__future__.html)を使用すると、あたかも時間旅行をするかのように、新しいバージョンのPythonから機能をインポートすることができます。

```python
from __future__ import print_function
print("Hello World!")
```

[中括弧もインポートできるよ](https://stackoverflow.com/questions/17811855/syntax-error-not-a-chance)。


## geopy

一からジオコーディングを行うのはなかなか難しいものです。
しかし[geopyモジュール](https://geopy.readthedocs.io/en/latest/)を使うと、心配になるほど簡単に実装できます。

```bash
$ pip install geopy
```

抽象化によって様々なジオコーディングAPIサービスを動作させられます。
ある位置の完全な住所、経緯度、そして高度も取得できます。

また距離クラスも便利です。
2点間の距離を任意の単位で取得できます。

```python
from geopy import GoogleV3

place = "221b Baker Street, London"
location = GoogleV3().geocode(place)

print(location.address)
print(location.location)
```

## howdoi

コーディングをしていて何らかの問題にぶち当たってしまった。
StackOverflowをチェックしたい、でもターミナル

大丈夫、[howdoi](https://github.com/gleitz/howdoi)ならね。

```bash
$ pip install howdoi
```

なにか疑問があるときは、関連しそうな単語を打ち込むとhowdoiがそれっぽいコードを返してくれます。

```bash
$ howdoi vertical align css
$ howdoi for loop in java
$ howdoi undo commits in git
```

しかし、注意してください。
これはStackOverflowのトップ回答から答えを集めてきます。
従って、それが常に最善の情報を返してくるとはかぎりません。

```bash
$ howdoi exit vim
```

## inspect

[inspect](https://docs.python.org/3/library/inspect.html)は非常にグレイトなモジュールで、何が起こっているかを理解するのに最適です。
自分自身を分析することすらできます。

以下のサンプルは、`inspect.getsource()`は引数のソースコードを出力します。
`inspect.getmodule()`は定義されているモジュールを出力します。
最後の行は、自身の行番号を出力します。

```python
import inspect

print(inspect.getsource(inspect.getsource))
print(inspect.getmodule(inspect.getmodule))
print(inspect.currentframe().f_lineno)
```

これらトリビアルな使い方だけではなく、inspectモジュールはコードが何をしているかを理解するのにとても役立ちます。
また、自己文書化コードの作成にも使うことができます。


## Jedi

Jediは、コード補完およびコード解析ライブラリです。
より迅速に生産的にコードを書くことができるようになります。

独自開発したIDEを使っているという事情でもないかぎり、Jediの[エディタプラグイン](https://jedi.readthedocs.io/en/latest/docs/usage.html)を導入してみる価値は十分にあるでしょう。
幸いなことに、多くのプラグインが既に用意されています。

もしかしたら、知らないうちにJediを使っている可能性すらあります。
例として、IPythonプロジェクトはコード補完機能としてJediを利用しています。


## **kwargs

言語を学ぶときには、途中で躓く場所が幾つかあります。
Pythonではおそらく、`**kwargs`がそのひとつであると思われます。

`**`は[キーワード引数](https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments)と呼ばれるもので、dictionary型の可変長引数を関数に渡すためのものです。

dictionary型のキーは引数名であり、値はその引数の値です。
一般的に`**kwargs`と呼ばれていますが、実際の名前は`kwargs`である必要はありません。

```python
dictionary = {"a": 1, "b": 2}
def someFunction(a, b):
    print(a + b)
    return

# 以下ふたつは同じ
someFunction(**dictionary)
someFunction(a=1, b=2)
```

引数の仕様がはっきり決まっていない関数を先に作らなければならないときに便利です。


## List comprehensions

Pythonについて私が最も好きな仕様のひとつが[リスト内包](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions)です。

この表記は、自然言語に似た、綺麗なコードで表すことができます。
使い方をより詳しく知りたいときは[こちら](https://www.learnpython.org/en/List_Comprehensions)を見てください。

```python
numbers = [1,2,3,4,5,6,7]
evens = [x for x in numbers if x % 2 is 0]
odds = [y for y in numbers if y not in evens]

cities = ['London', 'Dublin', 'Oslo']

def visit(city):
    print("Welcome to "+city)

for city in cities:
    visit(city)
```


## map

Pythonは、多くの組み込み機能で関数型プログラミングもサポートしています。
最も便利な関数のひとつが`map()`で、しばしば[ラムダ関数](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions)と組み合わせて使用されます。

```python
x = [1, 2, 3]
y = map(lambda x : x + 1 , x)
print(list(y)) // [2, 3, 4]
```

この例では、`map()`はxの各要素にラムダ関数を適用します。
これは`map`オブジェクトを返しますが、listやtupleなどに容易に変換可能です。


## newspaper3k

これを聞いたことがないというのであれば、[newspaperモジュール](https://pypi.org/project/newspaper3k/)を見て腰を抜かす準備をしておいてください。

このモジュールは、主要なWebサイトのニュース記事や関連するメタデータを分析することができます。
画像、テキスト、著者名などを取得可能です。

さらにいくつかの組み込み[自然言語処理](https://newspaper.readthedocs.io/en/latest/user_guide/quickstart.html#performing-nlp-on-an-article)機能まで持っています。

次のプロジェクトでBeautifulSoupや、あるいは自作のスクレイピングライブラリなどを使用することを考えているようなら、かわりに`$ pip install newspaper3k`と入力して、時間と労力を節約してください。


## Operator overloading

Pythonは[演算子オーバーロード](https://docs.python.org/3/reference/datamodel.html#special-method-names)をサポートしています。
これはあなたを真のコンピュータサイエンティストであるかのように見せかける魔法のひとつです。

実際には単純なものです。
Pythonが`+`演算子を使って、数値の加算だけではなく文字列の結合もできるのはなぜでしょうか。
演算子オーバーロードの力です。

Pythonでは演算子の動作を独自に変更するメソッドが用意されています。
これにより、使用するオブジェクトに関連する方法で演算を行うことができます。

```py
class Thing:
    def __init__(self, value):
        self.__value = value
    def __gt__(self, other):
        return self.__value > other.__value
    def __lt__(self, other):
        return self.__value < other.__value

something = Thing(100)
nothing = Thing(0)

# True
something > nothing
# False
something < nothing
# Error
something + nothing
```


## pprint

Pythonは`print`がデフォルトの表示機能です。
しかしネストの多い巨大なオブジェクトを`print`してみると、その醜さは見てられないものになります。

[pretty-print](https://docs.python.org/3/library/pprint.html)標準ライブラリが存在するので、そちらを使用しましょう。
複雑な構造化オブジェクトを見やすく表示してくれます。
データ構造を扱う開発者には欠かせないモジュールです。

```py
import requests
import pprint

url = 'https://randomuser.me/api/?results=1'
users = requests.get(url).json()

pprint.pprint(users)
```

## Queue

Pythonはマルチスレッドをサポートしていますが、標準ライブラリのQueueモジュールを使うことで使用が容易になります。
このモジュールはキューと呼ばれるデータ構造を提供します。
これは、特定のルールに従ってエントリを追加・取得することができるデータ構造です。

FIFO(First in, first out)キューを使うと、オブジェクトを追加した順番に取り出すことができます。
LIFO(Last in, first out)キューを使うと、直近に追加したオブジェクトから順番に取り出すことができます。

最後にプライオリティキューを使うと、ソートされた順番に従ってオブジェクトを順番に取り出すことができます。

参考として、[マルチスレッドプログラミングにキューを使用する例](https://www.tutorialspoint.com/python3/python_multithreading.htm)を挙げておきます。


## \_\_repr\_\_

クラスやオブジェクトを定義するときには、そのオブジェクトの文字列表現を提供しておくと便利です。
printの例を示します。

```py
>>> file = open('file.txt', 'r')
>>> print(file)
<open file 'file.txt', mode 'r' at 0x10d30aaf0>
```

これによって、デバッグがより簡単になります。
やりかたは`__repr__`を実装するだけです。

```py
class someClass:
    def __repr__(self):
        return "<some description here>"

someInstance = someClass()
print(someInstance) # <some description here>
```


## sh

Pythonは素晴らしいスクリプト言語ですが、ときに標準のOSコマンドとライブラリを使おうとして頭痛に苛まれることになります。

そんなときは[shライブラリ](http://amoffat.github.io/sh/)でばっちり解決です。
任意のプログラムを普通の関数であるかのように呼び出すことができます。
これはワークフローやタスクの自動化にも役立ちます。

```py
import sh

sh.pwd()
sh.mkdir('new_folder')
sh.touch('new_file.txt')
sh.whoami()
sh.echo('This is great!')
```


## Type hints

Pythonは動的型付け言語です。
変数、関数、クラスなどを定義するときにデータ型を指定する必要はありません。
これによって迅速な開発が可能になります。

しかしながら、ちょっとしたタイピングミスが非常に厄介なランタイムエラーをもたらすこともしばしばあります。

[Python3.5](https://docs.python.org/3/library/typing.html)以降では、関数定義時にタイプヒントを書くことができます。[^1]

```py
def addTwo(x : Int) -> Int:
    return x + 2
```

タイプエイリアスを定義することもできます。

```py
from typing import List

Vector = List[float]
Matrix = List[Vector]

def addMatrix(a : Matrix, b : Matrix) -> Matrix:
  result = []
  for i,row in enumerate(a):
    result_row =[]
    for j, col in enumerate(row):
      result_row += [a[i][j] + b[i][j]]
    result += [result_row]
  return result

x = [[1.0, 0.0], [0.0, 1.0]]
y = [[2.0, 1.0], [0.0, -2.0]]
z = addMatrix(x, y)
```

タイプヒントは必須ではありませんが、コードをわかりやすくすることができます。

タイプチェックツールなどを用いて、タイプエラーを実行前に捕捉することもできます。
大規模で複雑なプロジェクトに取り組んでいるなら、大きな恩恵があるはずです。


## uuid

ユニバーサルユニークID(UUID)を生成する最も簡単で早い方法は、標準ライブラリの[UUIDモジュール](https://docs.python.org/3/library/uuid.html)です。

```py
import uuid

user_id = uuid.uuid4()
print(user_id)
```

これだけで、ほぼ確実にユニークな128ビットの数値が生成されます。
実際に生成できるUUIDの種類は2の122乗以上、つまり5澗(5,000,000,000,000,000,000,000,000,000,000,000,000)以上です。

UUIDが重複する可能性は非常に低く、1兆個のUUIDがあったとしてもその中で重複が存在する可能性は10億分の1以下です。
わずか2行にしてはとても良いコードです。


## Virtual environments

これがおそらく、私がPythonの全機能の中で最も気に入っている機能です。

一度に複数のPythonプロジェクトに関わっています。
残念なことに、2つのプロジェクトはそれぞれ、同じライブラリの異なるバージョンに依存しています。
あなたは手元に何をインストールすればよいでしょう？

Pythonは素晴らしいことに[Virtual Environments](https://docs.python.org/3/tutorial/venv.html)をサポートしており、両方のバージョンを受け入れることができるのです。

```py
python -m venv my-project
source my-project/bin/activate
pip install all-the-modules 
```

これだけで、既にインストールされているPythonとは独立した仮想環境を実行することができます。


## wikipedia

Wikipediaには優れたAPIがあり、無限の知識と情報[^2]にプログラムでアクセスすることができます。
[Wikipediaモジュール](https://wikipedia.readthedocs.io/en/latest/quickstart.html)は、このAPIへのアクセスを極めて容易にします。

```py
import wikipedia

result = wikipedia.page('freeCodeCamp')
print(result.summary)
for link in result.links:
    print(link)
```

実際のWikipediaと同じように、このモジュールは複数の言語、曖昧さ回避、ランダムページ取得などに対応し、あまつさえ`donate()`メソッドまで持っています。


## xkcd

Pythonの重要な特徴のひとつがユーモアです。
なにしろ名前の由来からして[空飛ぶモンティ・パイソン](https://ja.wikipedia.org/wiki/%E7%A9%BA%E9%A3%9B%E3%81%B6%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3)にちなんで命名されたものです。
Pythonの公式ドキュメントの多くは、彼らの有名なコントを参照しています。

しかし、ユーモアのセンスはドキュメントだけにとどまりません。
以下を実行してみてください。

```py
import antigravity
```

センスの変わらないただ一つのPython。


## YAML

YAMLは[YAML Ain't Markup Language](http://yaml.org/)の略です。
これはデータ構造であり、JSONの上位互換です。

JSONとは異なり、より複雑なオブジェクトを格納し、独自の要素を参照することができます。
コメントを書くこともできるため、設定ファイルの作成にも適しています。

Pythonでは[PyYAMLモジュール](https://pyyaml.org/wiki/PyYAMLDocumentation)でYAMLを扱うことができます。

```py
$ pip install pyyaml
```

importするだけです。

```py
import yaml
```

PyYAMLには、任意のデータ型のオブジェクトや、任意のユーザ定義クラスのインスタンスを突っ込むことが可能です。


## zip

最後に紹介するこちらは本当にクールです。
2つのListからDictionaryを作らねばならない事態に陥ったことはありますか？

```py
keys = ['a', 'b', 'c']
vals = [1, 2, 3]
zipped = dict(zip(keys, vals))
```

ビルトインのzip関数は反復可能オブジェクトを引数に取り、タプルのリストを返します。
各タプルには、引数のオブジェクトがインデックスごとにグループ化されたものが入ってきます。

もちろんunzipも可能で、`*`を付けて呼び出すだけです。


## Thanks for reading!

AからZまで色々な機能を紹介しました。
運がよければ、次のプロジェクトで役立つトリックを見つけられたかもしれません。

Pythonは広く開発された言語なので、まだ私も使ったことのない多くの機能が存在します。
あなたの好きな独自のPython機能があるなら、ぜひコメントなどで共有してください。


# コメント欄

「とても勉強になった！ありがとう！」
「OrderedDictはもう必要ない。Python3.7からはデフォルトで順序がついてるよ。」
「\_\_repr\_\_は\_\_str\_\_と[同じではない](https://stackoverflow.com/questions/1436703/difference-between-str-and-repr/1436756#1436756)と主張したい。あと仮想環境は[このパッケージ](https://virtualenvwrapper.readthedocs.io/en/latest/)が有用だったよ。」
「mapよりlistとgeneratorのほうがお勧め」
「圧縮ファイル操作をよく使う。マルチプラットフォームでWindowsでも動くので便利。`python -mzipfile -l some.zip`とか`python -mtarfile -l some.tar.gz`とか。」
「`from sh import *`こいつを[やってはいけない](https://www.python.org/dev/peps/pep-0008/#imports)。`from sh import sh`と書くべき。」
「2018年7月以降[geopyはAPIキーと金が必要](https://developers.google.com/maps/documentation/geocoding/usage-and-billing)になってしまった。」

# 感想

正直タイトルはちょっと強引すぎた。

PypI(というかPython自体)機械学習系以外でほとんど触ったことがないので色々と面白かった。
最近はJupyter Notebookを突っ込むだけで使えるから、ちょっと試してみるのも簡単でいいよね。
inspectすげえ。

なかなか楽しいので今度PHPでやってみようかな。

[^1]: Intじゃなくてintにしないと未定義のエラーになった。
[^2]: 正しいとは限らない。