LoginSignup
12
17

More than 5 years have passed since last update.

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

Posted at

以下はAn A-Z of useful Python tricksの日本語訳です。

An A-Z of useful Python tricks

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

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

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

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

all or any

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

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

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

$ pip install bashplotlib

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

collections

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

from collections import OrderedDict, Counter

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

dir

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

>>> dir()
>>> dir("Hello World")
>>> dir(dir)

Pythonをインタラクティブに実行しているときや、オブジェクトとモジュールを動的に探したいときなどに便利な機能です。
詳細はマニュアルを見てください。

emoji

絵文字?
絵文字

$ pip install emoji

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

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

01.png

from future import

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

恐れることはありません。
__future__モジュールを使用すると、あたかも時間旅行をするかのように、新しいバージョンのPythonから機能をインポートすることができます。

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

中括弧もインポートできるよ

geopy

一からジオコーディングを行うのはなかなか難しいものです。
しかしgeopyモジュールを使うと、心配になるほど簡単に実装できます。

$ pip install geopy

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

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

from geopy import GoogleV3

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

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

howdoi

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

大丈夫、howdoiならね。

$ pip install howdoi

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

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

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

$ howdoi exit vim

inspect

inspectは非常にグレイトなモジュールで、何が起こっているかを理解するのに最適です。
自分自身を分析することすらできます。

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

import inspect

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

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

Jedi

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

独自開発したIDEを使っているという事情でもないかぎり、Jediのエディタプラグインを導入してみる価値は十分にあるでしょう。
幸いなことに、多くのプラグインが既に用意されています。

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

**kwargs

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

**キーワード引数と呼ばれるもので、dictionary型の可変長引数を関数に渡すためのものです。

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

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

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

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

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()で、しばしばラムダ関数と組み合わせて使用されます。

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

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

newspaper3k

これを聞いたことがないというのであれば、newspaperモジュールを見て腰を抜かす準備をしておいてください。

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

さらにいくつかの組み込み自然言語処理機能まで持っています。

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

Operator overloading

Pythonは演算子オーバーロードをサポートしています。
これはあなたを真のコンピュータサイエンティストであるかのように見せかける魔法のひとつです。

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

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

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標準ライブラリが存在するので、そちらを使用しましょう。
複雑な構造化オブジェクトを見やすく表示してくれます。
データ構造を扱う開発者には欠かせないモジュールです。

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)キューを使うと、直近に追加したオブジェクトから順番に取り出すことができます。

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

参考として、マルチスレッドプログラミングにキューを使用する例を挙げておきます。

__repr__

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

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

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

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

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

sh

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

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

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以降では、関数定義時にタイプヒントを書くことができます。1

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

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

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モジュールです。

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をサポートしており、両方のバージョンを受け入れることができるのです。

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

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

wikipedia

Wikipediaには優れたAPIがあり、無限の知識と情報2にプログラムでアクセスすることができます。
Wikipediaモジュールは、このAPIへのアクセスを極めて容易にします。

import wikipedia

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

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

xkcd

Pythonの重要な特徴のひとつがユーモアです。
なにしろ名前の由来からして空飛ぶモンティ・パイソンにちなんで命名されたものです。
Pythonの公式ドキュメントの多くは、彼らの有名なコントを参照しています。

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

import antigravity

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

YAML

YAMLはYAML Ain't Markup Languageの略です。
これはデータ構造であり、JSONの上位互換です。

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

PythonではPyYAMLモジュールでYAMLを扱うことができます。

$ pip install pyyaml

importするだけです。

import yaml

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

zip

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

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__と同じではないと主張したい。あと仮想環境はこのパッケージが有用だったよ。」
「mapよりlistとgeneratorのほうがお勧め」
「圧縮ファイル操作をよく使う。マルチプラットフォームでWindowsでも動くので便利。python -mzipfile -l some.zipとかpython -mtarfile -l some.tar.gzとか。」
from sh import *こいつをやってはいけないfrom sh import shと書くべき。」
「2018年7月以降geopyはAPIキーと金が必要になってしまった。」

感想

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

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

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


  1. Intじゃなくてintにしないと未定義のエラーになった。 

  2. 正しいとは限らない。 

12
17
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
12
17