Pythonを書き始める前に見るべきTips

  • 2388
    いいね
  • 12
    コメント

Pythonを使ってこの方さまざまな点につまずいたが、ここではそんなトラップを回避して快適なPython Lifeを送っていただくべく、書き始める前に知っておけばよかったというTipsをまとめておく。

Python2系と3系について

Pythonには2系と3系があり、3系では後方互換性に影響のある変更が入れられている。つまり、Python3のコードはPython2では動かないことがある(逆もしかり)。

Python3ではPython2における様々な点が改善されており、今から使うなら最新版のPython3で行うのが基本だ(下記でも、Python3で改善されるものは明記するようにした)。何より、Python2は2020年でサポートが終了する。よって今からPython2を使う理由はない。未だにPython2を使う者は、小学生にもディスられる

しかし、世の中にはまだPython3に対応していないパッケージもあり、自分のプロジェクトでそうしたパッケージに当たるかどうかが運命の分かれ道になる。対応状況については、こちらから一覧で確認することができる。ただ、ほとんどのパッケージは対応済みかPython3で動かすすべがあると思ってよいと思うし(2から3への自動変換もある。また、Google App EngineはFlexible EnvironmentでPython3に対応した)、逆にPython3に対応していないならメンテナンス状況を疑うべき状況に来ているともいえる。なお、人工知能の先端的研究機関であるOpenAIでもPython3へ移行しているので、「機械学習周りはまだ~」という者は少なくとも先端でない人間なので、言うことを当てにする必要はない。

Pythonのセットアップ

Pythonの開発をする場合Python本体以外にpip、virtualenvのインストールがほぼ必須になるので、各環境でのPython・pip・virtualenvのセットアップ方法をまとめておく。

  • Python3.4からpipは標準搭載されたので、pipのインストールを明示的に行う必要はなくなった。
  • Python3.3から仮想環境を作成するための仕組み(venv)が組み込まれたので、virtualenvも必要はなくなった・・・が、当然Python2では使えないため普及には時間がかかると思われる。また、venvを呼び出すためのpyvenvコマンドは、Python3.6から非推奨となった。理由としては、pyvenvのコマンドはどのPythonで環境を作っているのかわからないからやめよう!ということらしい。そのため、venvを利用する際はpython -m venvとしてpythonコマンドから明示的にvenvモジュールを呼び出すようにする。

Mac/Linuxの場合
システムデフォルトでPythonが入っているが、開発したいバージョンとは一致しないこともある。そのため、pyenvを利用してプロジェクトごとに利用するPythonのバージョンを切り替えられるようにするのが良い。

各プロジェクトで使用するPythonは、pyenv local x.x.xで設定する。Minicondaなどで作成した仮想環境は、miniconda-x.x.x/envs/<your_env>で適用できる(pyenv versionsで確認可能。普通にsource activate xxxを使うとシェルが落ちることがあるので、こちらの方を推奨)。

なお、pyenvで新しいPython環境をインストールした後はpyenv rehashが必要pyenv global x.x.xを実行してもなんだかおかしい?(例えばMinicondaをインストールしたけどcondaコマンドが使えないとか)という場合は忘れていないかを要確認。あとは、念のためターミナルを再起動する。

Windowsの場合
普通にインストールしてもよいが、Minicondaをお勧める。これをインストールすることでcondaというコマンドが使えるようになり、パッケージのインストールが楽になる。上述のpyenvはWindowsに対応しておらずまたその予定も多分ないが、condaで代替することができる。※ただ、Windows10のAnniversary UpdateでUbuntu環境がWindowsでも使えるようになった(bash on Windows)。こちらを使えば上記のMac/Linuxと同じ手順で環境を構築できるほか、下記で述べるようなパッケージインストールできない問題にも遭遇しないで済む。bash on Windowsのセットアップ方法については、こちらを参考されたし。

  • WindowsでPythonを使う場合に最もお勧めする手順
    • Pythonのインストール: Minicondaでインストール
    • pipのインストール: conda install pip(上記同様、Python3.4以降は不要)
    • virtualenvのインストール: pip install virtualenv ただしcondaを仮想環境として使う場合不要(その旨の警告が表示される)

※Python3.5版のcondaは、Visual Studio 2015 の Visual C++ 再頒布可能パッケージを入れないといけいない可能性があるので、インストールが途中で止まったりした場合はインストールを試してみてください(参考: Python 3.5 missing VCRUNTIME140.dll)。

condaを利用すれば大抵pip installで躓くようなパッケージはインストール可能だが、conda packageがなく、かつpipもコケる場合は以下の対応を行う。

  1. Unofficial Windows Binaries for Python Extension Packagesで該当するパッケージを見つけ、pip install <file_path> でインストールを行う(余談だが、wheelを使うことで依存ライブラリをコンパイルした状態でリポジトリに含めることができる。これにより配布・デプロイする際相手先の環境でpip installできないという事態を防ぐことができる。詳細はドキュメント参考)。
  2. exe形式のファイルが提供されている場合は、easy_installを頑張って入れてインストールする。
  3. コンパイルするしかない!という場合は・・・まずはVisual Studioをインストールしよう。その後、以下を参考に環境変数を設定をする。

Pythonでの開発の流れ

Pythonの開発はだいたい以下の段取りで行う。

  1. プロジェクト用の仮想環境を作成する(virtualenv/conda)
    Pythonではプロジェクトの稼働に必要なライブラリはグローバルにインストールせず、個別の仮想環境にインストールするのが通例で、そのためのツールがvirtualenv/condaになる
  2. 仮想環境に必要なモジュールをインストールする(pip/conda)
    pipはパッケージ管理ツール。Pythonプロジェクトを外部に公開する際は、pip freezeで必要なパッケージを一覧にし、これを元に各環境でインストールしてもらう(condaの場合はconda list --export)
  3. 作成したPythonを実行する

コマンドに書き直すと以下のような感じになる(以下は、仮想環境としてvirtualenvを使う。condaベースの場合はこちら参照)。

# プロジェクトのフォルダを作成
mkdir myproject 
cd myproject

# 1.仮想環境の作成 venvはフォルダ名でここにプロジェクト用の環境が用意される
virtualenv venv 

# 2.仮想環境を有効化し、pipで必要なモジュールをインストール
# Windowsの場合、venv/Scripts/activate.bat なお、Gitのシェルを利用すると同じようにsourceでできる
# 仮想環境のactivateを行わないと、グローバルにインストールされるので注意 なお、無効化はdeactivate

source venv/bin/activate

pip install xxxx
# pip freezeで作成した一覧(requirements.txt)からインストールする場合は以下
pip install -r requirements.txt

# 3.実行する
python xxx.py

バージョン管理の対象としてはずしておくべきなのが、上記の仮想環境のフォルダ(venvなど)と、.pycファイルになる。
.pycファイルは実行を高速化するためのファイルで、一旦実行すると一ファイルにつき一つできていく。これをバージョン管理に入れてしまうとファイルが二倍になってしまうので、これははずしておく必要がある(-Bオプションをつけるか、環境変数 PYTHONDONTWRITEBYTECODEを設定することで生成しないようにすることもできる(参照))。
その他無視すべきファイルについては、Pythonの.gitignore等を参考にしてください。

これでPythonの開発環境は整ったので、以下からは本題であるPythonで開発をする際に気を付けるべき点を挙げていく。

ファイルのエンコードを宣言する必要がある(2のみ)

各ファイルの先頭に以下を付けておかないと、日本語などは文字化けるので注意。こちらで言及されているように、ファイルの先頭に常につけるようにした方がよいだろう。

# -*- coding: utf-8 -*-

なお、Python3ではデフォルトのエンコードがUTF-8となっているのでこの対応は不要となっている(PEP 3120 -- Using UTF-8 as the default source encoding)。

幾つか下記でも述べるがPython2/3両対応をが想定される場合、そうでなくてもPython3の恩恵(特にunicode統一)を受けたい場合は以下のimportもしておくと良い(こちらご参考)。

from __future__ import division, print_function, absolute_import, unicode_literals

コーディングガイドがあり統合開発環境でチェックできる

Pythonには公式に定められたコーディングガイド(PEP8)があり(原文/日本語訳)、多くの統合開発環境ではこれを利用したチェックが可能になっている。

改行が多すぎる、空白文字の有無、といった点など結構細かくチェックでき、自分でも見落としていた点を修正できるので便利。
・・・逆に、最初から入れていないと後で修正が大変なのでそこが注意点。環境セットアップ時に入れておこう。

Pylintなどより多様なチェックができるツールもあり、これとエディタとの統合も進んでいる。

ユニットテストフレームワークが標準搭載

Pythonにはunittest標準搭載されているため、単体テストをするためにパッケージを追加する必要はない。

unittest2はあたかも新式フレームワークのように見えるが、これは古いバージョンで新しいバージョン用の単体テストフレームワークを利用するためのものなので、基本的に導入する必要はない(余談だがこの数字を振ったパッケージ名はやめてほしいと思う。urllib2とか)。

文字列には通常の文字列とユニコード文字列がある(2のみ)

Pythonでは通常の文字列のstrとユニコード文字列を扱うunicodeが分かれている。

str = "abc" # An ordinary string
uni_str = u"abc" # A Unicode string

内部的にはstrのままであまり問題ないが、Webアプリケーションなど外部からの入力/外部への出力が絡む場合、unicodeで統一しておいた方がよい(フレームワークを利用する場合は、どちらで入ってくるか、どちらで値を渡すべきかを押さえておく必要がある)。
なお、Python3ではunicodeに統一される。また、Python2でもfrom __future__ import unicode_literalsを使うことでunicodeに統一できる。

割り算の結果がfloat型にならない(2のみ)

Python2系では1/3といった整数同士の割り算の結果がfloat型にならない。

>>> 1/3
0
>>> 3/2
1

これが、Python3では解消する(上記の例では、0.333・・・、1.5という風に普通の算術演算結果となる)。
Python2系でもPython3と同じようにしたい、という場合は以下のimportを先頭で行うことで解消できる。

from __future__ import division

なお、除算では//という符号も存在する。これは一見商を出すための演算子と思いきや、そうではない。//による演算は、厳密には「計算結果を超えない最大の整数値」になる。
例えば3を2で割った場合、1.5となり、これを超えない最大の整数は1になる。これは商と等しく問題ないのだが、問題は値が負の場合。

>>> -3 / 2
-2

符号がマイナスになっただけで結果が変わっている。何これ?と思うかもしれないが、マイナスの場合は-1.5を超えない最大の整数は-2になる、とそういうことになっており、バグではなく仕様である。そして、この仕様はPython3でも同様である。
よって、安全に商を計算したい場合は、結果がfloatになるよう計算し小数点以下を切り捨てる方が良い。Python3であれば、これは単純に/で計算した結果を切り捨てればよい。

なお、divmodという商と余りを同時に計算してくれる組み込み関数があるが、この関数における「商」は//の演算結果と同様なので注意が必要(ドキュメントで「商」としている以上、これはさすがにバグと言っていい気もするが・・・)。

新スタイルクラスと旧スタイルクラスがある(2のみ)

良く紹介されている下記のクラス宣言では、旧スタイルクラスになる。

class MyClass():
    pass

旧スタイルクラスと何が違うか?とはいろいろあるが、少なくとも今旧スタイルクラスで作成することは何のメリットもないということだ。
旧スタイルクラスでは親クラスを呼び出すsuperが機能しないので何のための継承かわからなくなる。

そのため、クラスは以下のように宣言する。

class MyClass(object):
    pass

objectを継承するということだ。
なお、Python3からはデフォルトで新スタイルクラスになり旧スタイルクラスは削除される

また、Python3では親クラスの呼び出し処理も簡易化される。Python2ではsuper(子クラス名, self).parent_method()といった煩雑な呼び出し方法だったが、Python3では普通にsuper().parent_method()で呼び出せるようになる。

抽象クラス/インタフェースがない

継承は可能だが、下位クラスに実装を強制するような仕組みがない。
ただ、Python2.6からはabcが標準で追加され、疑似的に抽象クラスを実装できるようになった(abcとはabstract base classの略)。

from abc import ABCMeta

class MyABC:
    __metaclass__ = ABCMeta

    def describe(self):
        print("I'm abc")

    @abstractmethod
    def must_implements(self):
        pass

Python3ではクラスの作成時にmetaclassを使用できるようになったので、よりシンプルに書ける。

from abc import ABCMeta

class MyABC(metaclass=ABCMeta):
    ...

また、registerを使うことであるクラスを自分の配下(サブクラス)に登録できる。ただ、単に「そう振る舞っているように見せる」だけなので、以下例でも実際にtupleがMyABCの継承クラスになっているわけではなく、現にMyABCで実装されているメソッドも使用することができない。

MyABC.register(tuple)

assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)

().describe()  # Attribute Error

isinstanceでTrueになっているにもかかわらず、メソッドでAttribute Errorが出るのは正直混乱をきたす気がするので、利用シーンはあまりイメージできない。普通に継承したほうがよいと思う。

標準以外ではzope.interfaceが有名のよう(こちら参考)。
もちろん、普通にクラスを宣言して実装が強制されるメソッドは親クラスで例外をraiseするという手もある。

多重継承が可能

Pythonは数少ない多重継承をサポートしている言語になる。

class MultiInheritance(Base1, Base2, Base3):
...

解決は左から順に行われ、上記では自分自身になければBase1、その次にBase2・・・と探索が行われる。
superは、普通に呼んだ場合一番左のクラスになる。

上述の通りPythonにはインタフェースがないため、その代りに多重継承を利用することになる(あるいはModule/Mix-in的な利用)。多重継承はそれ以外の用途には使用しない方が良いと思う。
ただ、見た目は全員クラスになるのでインタフェース的に使用するものはIから始めるなどクラス名のルールを決めておくと良いだろう(あるいはInterface/Moduleといったクラスを作りそれを継承させるなど)。

コンストラクタ(と思われるもの)が2つある

Pythonには__new____init__という、どちらともコンストラクタなんじゃないの?と見える関数が2つある。
基本的には__init__を利用する。
ただ、引数のselfを見ればわかるとおり__init__は「インスタンスが作成された後の初期化処理」であり、厳密にはコンストラクタではない。__new____init__で初期化するためのインスタンスを返却する処理になる。やろうと思えば自分のクラス以外のインスタンスを返却したりもできるが、そのメリットはあんまりない。シングルトンの実装に使うぐらいか。

クラスに隠し属性が存在する

Pythonのインスタンスには上述の__init__のように、アンダースコア2つで囲われている隠し属性が存在する(クラス定義/関数定義自体にも存在する)。
これらはメタ情報を格納したり基本的な操作の実行(属性に値をセットする/取り出す際の挙動など)に使われている。
詳細はデータモデルに詳しいが、よく使う/役立ちそうなものは下記となる。

属性名 内容
__class__ クラス定義。__class__.__name__でクラス名が取得可能
__dict__ 全属性(メソッド含む)をディクショナリ化したもの
__doc__ クラスやメソッドのdocstringを取得可能。使い方が分からないけどソースコードやAPIドキュメントを探すのが面倒、という時にさくっと見られる
メソッド名 内容
__getattr__ 属性アクセスを行い、対象の属性がなかった場合呼び出される
__getattribute__ 属性アクセスを行う際、常に呼び出される
__setattr__ 属性への代入時に呼び出される
__delattr__ 属性の削除時に呼び出される(del obj.xxx)
__getstate__ オブジェクトの直列化(pickle化)を行う
__setstate__ 直列化したオブジェクトから復元を行う
__str__ クラスを文字列化するためのメソッド(いわゆるtoString)
__repr__ インスタンスの表記を出力するためのメソッド(型や一部のメンバなどを表記)

__str__とは__repr__は似ているが、__str__は人間が変数の内容を知るためのもの(Readable)、__repr__は意図した型の変数かどうかを確認するためのもの(Unambiguous)という使い分けがある(参考)。行列変数などで__repr__にshapeを含めるのは良い使い方で、意図した変数を受け取り処理が行われているかを確認できる。ログ・コンソールなどに出力する際に人間が読めるようにするために、__str__でインスタンスの状態をフォーマット出力するのは意図に沿っている。

obj["xxx"]といった文字列でなく、obj.xxxと属性でアクセスしたい場合が多々あるが、その場合に上記の__getattr__などが有効になる。以下、soundcloud-pythonでの実装例(__init__で渡されているobjはWeb APIから取得したディクショナリ型オブジェクト)。

class Resource(object):
    """Object wrapper for resources.

    Provides an object interface to resources returned by the Soundcloud API.
    """
    def __init__(self, obj):
        self.obj = obj

    def __getstate__(self):
        return self.obj.items()

    def __setstate__(self, items):
        if not hasattr(self, 'obj'):
            self.obj = {}
        for key, val in items:
            self.obj[key] = val

    def __getattr__(self, name):
        if name in self.obj:
            return self.obj.get(name)
        raise AttributeError

    def fields(self):
        return self.obj

    def keys(self):
        return self.obj.keys()

WebAPIのラッパーなど、相手のレスポンスによって動的に属性を変えたい場合などに利用できるテクニックになる。詳細な利用方法はこちらも詳しい。

なお、インスタンス/クラス定義等の属性はinspectモジュールで抽出することができる。

>>> import inspect
>>> inspect.getmembers(some_instance)

Enumがない(2のみ)

Python3.4.1からは標準搭載されるが、それまではEnumがない。
使いたい場合は、pip install enum34でenumをインストールして使用する。

import enum


class Color(enum.Enum):
    Red = 10
    Blue = 20
    Yellow = 30

>>> Color.Red == Color.Red
True

>>> Color.Red == 10
False
# EnumはあくまでEnum型オブジェクトのためこれはFalse。これをTrueにするIntEnumもある

>>> Color.Red == Color(10)
True
#コンストラクタに値を渡すことで該当のEnumを作成可能

>>> Color.Red == Color["Red"]
True
#名前から作成する際は[]で名称を指定

>>> {Color.Red:"red", Color.Blue:"blue"}
{<Color.Blue: 20>: 'blue', <Color.Red: 10>: 'red'}
# リストのキーとしても使用可能

なお、各項目の文字列を定義したい場合、__str__と併用することも可能。ラベル表示などを行う際、その定義を分散させたくないときに役に立つ。

class Color(enum.Enum):
    Red = 10
    Blue = 20
    Yellow = 30

    def __str__(self):
        if self.value == Color.Red.value:
            return "赤"
        elif self.value == Color.Blue.value:
            return "青"
        elif self.value == Color.Yellow.value:
            return "青"
>>> print(Color.Red)

PrivateやProtectedがない

ないが、Privateなものは先頭に___を付けるという慣習がある。継承クラスにだけ見せたいなど、いわゆるProtectedに相当する概念はない。
では、___は何が違うのか?これは外部から隠蔽される度合いが変わってくる。

class Test(object):
    def __init__(self):
        self.__a = 'a' # two underscores
        self._b = 'b' # one underscore

>>> t = Test()
>>> t._b
'b'

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'
t.__a isn't found because it no longer exists due to namemangling

>>> t._Test__a
'a'

上記のように、アンダースコア一つの場合は一応通常通りアクセス可能だが(PEPでチェックしていると警告を出してくれる)、アンダースコアを二つ付けた場合は_Test__aとしないとアクセスできない、というようによりPrivate的な形(普通は見えない)にしてくれる。

<参考>
The meaning of a single- and a double-underscore before an object name in Python
Difference between , _ and xx in Python

const/finalがない

Pythonでは定数を定義することができない。
ただ、後述するタプルは変更不可能なリストとなるので、これを利用すれば疑似的に定数を作成することは可能(変更不可なリストがあるくらいならconstがあっていい気もするが・・・)。

ここはPEP8では定数は全大文字でアンダースコアでつなぐべしとしているが、これに対するチェックはない。

メソッドの第一引数が予約されている

※ここではメソッド=クラス内の関数、としています。通常の関数にこの制約はありません。
メソッドの最初の引数は、普通のメンバメソッドはself、クラスメソッドの場合clsで予約されている(引数名はじつは何でもよいが、慣例としてselfclsが使用されている)。

class Test(object):
    def __init__():
        pass

    def get_num(self):
        return 1

    def add_num(self, num):
        return self.get_num() + num

    @classmethod
    def test_print(cls):
        print "test"

上記のget_numは明らかに引数一つとっているように見えるが、これは実質的には引数なしのメソッドである。
そして、同クラス内のメンバ関数はself.get_num()となっているようにこの暗黙の第一引数であるselfclsを利用して呼び出しを行う。

リストとタプル(+可変長の引数)

Pythonには、ざっくり言えば「変更できないリスト」であるタプルというオブジェクトが存在する。これらは宣言方法が異なる。

v_list = [10, 20, 30] # list
v_tuple = (10, 20, 30) # tuple

v_list[1] = 11 # ok
v_tuple[1] = 11 # error! 'tuple' object does not support item assignment

タプルは、その特性上ディクショナリのキーになることも可能である。
リストとタプルは可変長の引数を扱う関数/メソッドにも深く関わっている。

def out_with_tuple(a,b,*args):
    # a,b以降の引数はtupleにまとめられる
    print(a,b,args)

>>> out_with_tuple(1,2,3,4,5)
(1, 2, (3, 4, 5))

def out_with_dict(a,b,**args):
    print(a,b,args)

>>> out_with_dict(1,2,one=3,two=4,three=5)
(1, 2, {'three': 5, 'two': 4, 'one': 3})

*というとポインタと思ってしまいがちだが、これは任意個数の引数を表し*の場合タプル、**の場合ディクショナリにまとめられる(併用も可能)。

そして、呼び出し側で*,**使うと逆にリスト/タプルの値を展開して引数として渡すことができる。

>>> def out(a,b):
...    print(a,b)

>>> out([1,2])  # 普通にリストを渡した場合、当然NG
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: out() takes exactly 2 arguments (1 given)


>>> out(*[1,2])
(1,2)  # *によって、リスト内の要素が展開され、out(1,2)と呼び出したのと同じになる

>>> out_with_dict(**{"a":1,"b":2})
(1, 2, {})  # 上記同様、**によってディクショナリで渡した引数が展開される

デフォルト引数はimmutableである必要がある

メソッドや関数のデフォルト引数として与える値は、immutableである必要がある。大体はそうなので問題はないが、空の配列はmutableに該当するので注意する必要がある。


>>> class ArrayDefault():
>>>    def __init__(self, array=[]):
>>>        self.array = array  #! mutable default value

>>> a = ArrayDefault()
>>> len(a.array)
0
>>> a.array += [1,2,3]
>>> a.array
[1,2,3]

>>> b = ArrayDefault()
>>> b.array
[1, 2, 3]  # !!!!!

aとは全く関係ないbのインスタンスになぜかあらかじめ値が入っている。完全に複雑怪奇な挙動に見えるが、これが引数がimmutableでなければならない理由である。デフォルト引数のスコープはそのメソッド/関数と同じであるようで、immutableでない場合グローバル変数と同じような働きをし上記のような挙動を起こす。

よって、上記の場合はNoneをデフォルト引数にしてNoneなら[]を設定するといった処理に変える必要がある。配列同様、参照を初期値として設定するようなケースは同様に注意が必要。

Default Parameter Values in Python

メソッドのオーバーロードができない

Pythonでは引数を変えて同名で定義するオーバーロードが使用できない。
そのためオーバーロードを使用したい場合は、デフォルト引数を使用したり内部で引数の型を判定するなどして、1メソッド内の分岐で対応する必要がある。
また、同名のクラスメソッドとメンバメソッドも許容されない。

ただ、singledispatchを利用することで条件分岐を排してオーバーロード的な実装を実現できる(Python3.4からは標準搭載)。

演算子による計算を実装可能(オペレーターオーバーロード)

Pythonでは、+-といった演算子による計算を実装することができる(いわゆるオペレーターオーバーロード)(参考)。

class Point(object):
    def __init__(self, x, y):
        self.x = 0 if x is None else x
        self.y = 0 if y is None else y
    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Point(x, y)
    def __str__(self):
        return "x:{0}, y:{1}".format(self.x, self.y)

>>> print(Point(1, 2))
x:1, y:2
>>> print(Point(1, 2) + Point(1, 2))
x:2, y:4

また、==>といった論理演算子の実装も可能。ただ、演算子をすべてスキなく定義するのはかなり骨が折れる。数値演算系なら自前で実装するより適切なライブラリがないかどうか確認したほうがよい。

型定義を記述することができる(3より)

Python3より(特にPython3.5から)、引数や関数の返り値について型を書くことができるようになった。

def greeting(name: str) -> str:
    return 'Hello ' + name

Python3.6からは変数にも型情報を付けることができるようになった(PEP 526)。

my_string: str
my_dict: Dict[str, int] = {}

これはtype annotationといい、実行時にエラーを出すわけではないが事前にこの情報を使いチェックをかけることができる。チェックのためのツールとしては、mypyなどがあり、これを利用することで実行前に型の整合性チェックを行うことができる。詳細は以下を参照。

Pythonではじまる、型のある世界

なお、Javaのアノテーションと記述が同じに見える@がつくものがあるが、これはアノテーションではなく「デコレーター」であり、その挙動は全く異なりこちらは関数の実行に作用する。
デコレート、の名の通り「関数をラップする関数」として機能するのだ。

import functools

def makebold(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return "<b>" + func(*args, **kwargs) + "</b>"
    return wrapper

def makeitalic(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return "<i>" + func(*args, **kwargs) + "</i>"
    return wrapper

@makebold
@makeitalic
def hello(your_name):
    return "hello {0}.".format(your_name)

>>> print hello("hoge") ## returns <b><i>hello hoge.</i></b>

参考:How can I make a chain of function decorators in Python?

上記は、makebold(makeitalic(hello))(your_name)を実行したのと同じことになる(関数定義に近いデコレーターから順次実行されていく)。
メソッド実行前にチェックを入れたい場合(権限など。Overridesのチェックなどもできたりする)、また実行前後に処理を入れたい場合(実行時間の計測など)に利用される。なお、functools.wrapはデコレートしたことで関数の情報が元の関数でなくデコレート関数に置き換わってしまうのを防ぐためのもの(こちら参照)。

メソッドに付与されたデコレーターを取得するのはかなり難しいので、メタプログラミング用途の場合(アノテーションが付与されたメソッドを取得して実行など)は潔くPython3に上げてアノテーションを利用したほうがよい。

名称空間とimportについて

PythonではNamespaceやpackageの宣言をしなくても、名称空間がファイルごとに(自動的に)切られるようになっている。ファイルごとに切られた名称空間の名前はファイル名と同義になるため、package/test_class.pyの中に定義されたTestClassを呼び出す場合、from package.test_class import TestClassとする必要がある。
※このため、他のパッケージ名とファイル名がバッティングするとインポートしたいパッケージがインポートできなくなったりするので注意が必要(こちらはファイル名をunittest.pyにしたために標準のunittestとバッティングした例)。'module' object has no attribute 'xxxx'といったエラーが出たら要注意。

また、ファイル単位で切られるため同じフォルダ内のファイルでも参照する際にimport宣言が必要になる。なお、フォルダは__init__.pyというファイルがあるとパッケージと認識される(Python3からはなくてもよくなる)。

Javaなどと同様、パッケージ/クラス名でインポートを行いたい場合(from package import TestClassというような感じ)、__init__.pyにファイルのimport文を書いておくことで対応できる。from package部分で読み込まれるのはフォルダ内の__init__.pyであるため、ここにimport文があればファイルをインポートしたのと同じになるためである。

なお、相互参照しているファイルのimportの場合(AはBを参照していて、BはAを参照しているようなケース)はデッドロックのようになりインポートできなくなるので注意。これを回避するには、ファイル先頭でなく必要な処理内でimportするなどの工夫が必要になる(参考)。

あらゆるファイルをスクリプトとして実行可能

if __name__ == "__main__":は、スクリプトとして実行された際(python xxx.pyと実行したとき)の処理を記載できる(トップレベルのスクリプト環境参照)。

if __name__ == "__main__":
    print "Run Script"

これはクラスを定義しているファイルだろうが関数を定義しているファイルだろうが関係ない。
そのため、ちょっと今定義しているクラスの動作を確認してみたい、という場合ファイル下部に上記のようなif文を設置しておき、その配下に動作確認用の処理を書いておけばpython xxx.pyとすることで確認が可能だ。これは非常に便利。

配列内で処理を記載できる(リスト内包表記)

Pythonでは以下のように、配列内での演算が可能になっている。

>>> [ x for x in [1, 2, 3, 4, 5] if x > 3]
[4, 5]

>>> [ x*2 for x in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10]

# 関数を利用することも可能
>>>def calc_double(x):
>>>    return x*2

>>> [ calc_double(x) for x in [1, 2, 3, 4, 5]]
[2, 4, 6, 8, 10] 

動作はmapfilterといった組み込み関数と同じだが、場合によっては可読性を上げつつ簡単に書くことができる。なお、Python3からはmapfilterはlistそのものでなくiteratorを返すようになったので、Python2同様listで扱いたい場合はリスト内包表記、iteratorから後続処理にチェインさせたい場合はmap/filterなどを使うといった棲み分けをしておくと両バージョン対応しやすい。
また、実行速度が速いらしい

Python3.6から、このリスト内包表記でも非同期のイテレーターを扱うことが可能になった(PEP 530)。

result = [i async for i in async_iter() if i % 2]
result = [await fun() for fun in async_funcs if await condition()]

匿名関数の作成

Pythonではlambdaを使用することで匿名関数を作成できる。

>>> list(map(lambda x: x * 2, range(5)))
[0, 2, 4, 6, 8]

上記ではmapを利用しlambda x: x * 2という関数をrange(5)の各値に対して適用している。
lambdaで作成した関数は変数に代入することも可能で、上記は以下と等価である。

>>> f = lambda x: x * 2
>>> list(map(f, range(5)))
[0, 2, 4, 6, 8]

上記のリスト内包表記と合わせると、以下のような処理もかける。

>>> f = lambda a, b: a + b
>>> [f(*z) for z in zip([1, 2, 3], [4, 5, 6])]
[5, 7, 9]

zipは複数の配列を引数にとりインデックスごとにまとめてくれる便利関数で、zip([1, 2, 3], [4, 5, 6])[(1, 4), (2, 5), (3, 6)]となる。これを*を使って関数fの引数に展開し、処理を行っている。

for文について

Pythonのfor文はfor eachのような形で、デフォルトではインデックスがとれない。
ループ文中でindexを利用したい場合は、以下のようにする。

for index, value in enumerate(list):
    print "index:" + index

単純にインデックスだけで回したい場合、以下のようにも書ける(list.lengthのようなものはPythonにはないので、長さを取得する際はlen(list)でとる)。

for index in range(len(list)):
    print "index:" + index

非常に便利な特性として、Pythonのfor文ではelseを設定することができる(whileの方が利用シーンは多いかもしれないが)。

>>> for x in range(5):
...     print x
... else:
...     print "hoge"
...
0
1
2
3
4
hoge

このように、ループ終了後の処理をきれいに書くことができる。ただ、ループ中でbreakを行った場合は発動しないため注意が必要。

if文について

Pythonにはswitch文がないため、if-elseで代用する。
えっ、と思うかもしれないが、Pythonはインデントが定められておりifでもかなりきれいになるのでこれで困ることはあまりない。

また、このためPythonでは1行のif文(いわゆる三項演算子)が書けないのではと思う方がいるかもしれないが、Python 2.5以降では以下のように書くことができる(PEP 308 -- Conditional Expressions(条件演算式) 参照)。

>>> test = 1
>>> "test eq 1" if test == 1 else "test not eq 1"
'test eq 1'

非同期処理を実装するためのシンタックスがある(3から)

Python3.5から、async/awaitというシンタックスを利用し非同期処理が簡単に実装できるようになった(その前からasyncioで実装は可能だったのだが、はれて文法として実装された)。
ある連続した処理(以下ではtasks)を、複数プロセスで処理する場合は以下のような感じで書くことができる。

import asyncio
import random


tasks = asyncio.Queue()
for t in range(10):
    tasks.put_nowait(t)


async def execute(p):
    while not tasks.empty():
        t = await tasks.get()
        await asyncio.sleep(random.randint(0, 3))  # emulate the waiting time until task t finish
        print("Process{} done task {}".format(p, t))
    return True


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    execution = asyncio.wait([execute(process_no) for process_no in range(2)])
    loop.run_until_complete(execution)

実行結果は以下のようになる(※当然、実行するたびに結果は異なる)。

Process1 done task 0
Process0 done task 1
Process1 done task 2
Process0 done task 3
Process1 done task 4
Process0 done task 5
Process1 done task 6
Process0 done task 7
Process0 done task 9
Process1 done task 8

詳細については以下の記事にまとめているので、ご参考ください。

Pythonにおける非同期処理: asyncio逆引きリファレンス

なお、Python3.6からyieldを使用しより簡単に非同期イテレーターを作成することが可能になった(PEP 525)。

async def ticker(delay, to):
    """Yield numbers from 0 to *to* every *delay* seconds."""
    for i in range(to):
        yield i
        await asyncio.sleep(delay)

作成したパッケージの公開が可能(PyPI)

PythonではパッケージをホスティングしているPyPIというサイトがあり、こちらに作成したパッケージを公開することでpip installなどでほかの人に広く使ってもらうことが可能になる(JavaにおけるMaven、Rubyにおけるrubygems.org、.NETにおけるnugetのようなもの)。

この方法については、普通に検索すると旧い手法がよく引っかかってしまうので、最新のアップロード方法については以下を参照されたし。

Pythonで作成したライブラリを、PyPIに公開する

その他

ここに上げた以外のものについては、以下も参照ください。
[python] 細かすぎて伝わりにくい、Pythonの本当の落とし穴10選