魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

Pythonの特徴

投稿日:
修正日:
タグ:

以前少しだけPythonを触ったが、今回改めてちゃんと覚えようと勉強している。本稿はその学習のメモやまとめ、特に本稿ではPythonの特徴についてのまとめである。学習には主に次の2つの情報源を使用した。

Pythonの方針は次の通りである。


オンラインマニュアル

Pythonは、さまざまなバージョンの公式のオンラインマニュアルが用意されている(例えば2と3に互換性がない)。また、その内容もしっかりしており、いくつかのプログラミング言語で曖昧としているようないくつかの細かな仕様がしっかり規定されている。それゆえ非常に学習し易い。


開発者にとって便利な仕様

Pythonにはコードリーディングやコードライティングを助けるための仕様がいくつもある。以下にそれらをいくつか紹介する。

組み込み関数

Pythonには、コーディングやデバッギング助ける関数がある。また、Pythonではドキュメントの読み書きを行う共通のインタフェースがあり、ドキュメントを読むための関数がある。

  • locals関数
  • globals関数
  • dir関数
  • help関数

locals関数
globals関数
locals関数はローカルの名前空間の、globals関数はグローバルの名前空間の名前(識別子)の一覧を返す。これらの関数はデバッグの際に有効である。例えば次のような関数があったとする。
def func():
  v = 100
  w = "hoge"
  print(locals())
この時、ローカルの名前空間の名前一覧を画面に出力すると次のようになる。
{'x': 'hoge', 'w': 100}
次にglobals関数を使った対話的処理を以下に示す。
user% python3
>>> globals()
{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__',
'__doc__': None, '__package__': None}
>>> import sys
>>> v = 0
>>> globals()
{'__builtins__': <module 'builtins' (built-in)>, '__package__': None,
'sys': <module 'sys' (built-in)>, 'v': 0, '__name__': '__main__',
'__doc__': None}
help関数
Pythonには、モジュールやクラス、関数などのドキュメントを読み書きするための共通のインタフェースがある。そしてドキュメントを読むのに使用するインタフェースがhelp関数である。help関数は、環境変数PAGERが設定されていればそのページャを使用する。全てのモジュールやクラスなどにドキュメントをしっかり設定していれば、help関数の使い方さえ覚えていれば、他の関数の使い方を知らなかったり忘れたりしていてもどうにかなるだろう(help関数自身もドキュメントはあるが)。ドキュメントの書き方については、「ドキュメンテーション文字列」で説明する。
help(dir)
Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current
    scope.
    Else, return an alphabetized list of names comprising (some of) the
    attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used;
    otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the
    attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.
オブジェクトを指定した場合、その型のドキュメントが表示される。
dir関数
指定したモジュールやクラス、インスタンスなどの名前空間の名前一覧を返す関数である。もし引数を省略した場合は現在のスコープの名前一覧を返す。これを使用すれば、モジュールに含まれたクラスの名前や、クラス内のメンバの名前を調べることができる。そして、名前さえ分かればそれをhelp関数で詳細を調べることができる。例えばsysモジュール内の名前を調べるにはこのようにする。
>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_getframe', '_mercurial',
'_xoptions', 'abiflags', 'api_version', 'argv', 'builtin_module_names',
'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace',
'hash_info', 'hexversion', 'int_info', 'intern', 'maxsize',
'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'subversion', 'version', 'version_info', 'warnoptions']
class Cls:
  v = 100
  w = "hoge"
この時dir(Cls)は次のような値を返す。
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'v', 'w']

ドキュメンテーション文字列

優れたコードには可読性を向上させるためのコメントが、そしてライブラリにはその使い方を正しく理解するためのコメントやマニュアルがある。前述の通り、Pythonにはそれらをサポートするための仕様が備わっている。ドキュメンテーション文字列は、そのようなドキュメントを書くためのインタフェースである。ユーザが関数やクラス、モジュールを定義する場合、ドキュメンテーション文字列を書くことで前述のhelp関数を使ってドキュメントを読むことができる。

関数アノテーション

Pythonでは、関数アノテーションを用いて関数の引数や返り値の説明を記述できる。例えば、次のコードは、関数sumの返り値と第1引数addee、第2引数adderの説明を記述している。

def sum(addee:"被加数", adder:"加数") -> "和":
  return addee + adder
この関数は次のような実行結果となる。
>>> sum(1, 4)
5
関数のドキュメントは、help関数で閲覧できる。
>>> help(sum)
Help on function sum in module __main__:

sum(addee: '被加数', adder: '加数') -> '和'

ドックストリング

Pythonでは、ドックストリングによって関数やクラス、モジュールの説明を記述できる。ドックストリングの記述するには、スイート内の文が始まる前に文字列リテラルを置く。

def sum(addee:"被加数", adder:"加数") -> "和":
  """
  2つの値を受け取ってその加算結果を返す
  """
  return addee + adder
Python文字列リテラルの書き方は4つある。
文字列引用符説明
'string'一重引用符
"string"二重引用符
'''string'''三連一重引用符エスケープなしで改行や引用符を書くことが可能。
"""string""" 三連二重引用符
Help on function sum in module __main__:

sum(addee: '被加数', adder: '加数') -> '和'
    2つの値を受け取ってその加算結果を返す

ドキュメンテーション文字列は、共通化されたコメントのようなもので省略可能である。しかし、省略してもあまりメリットはないだろう。

名前(識別子)

Pythonの名前(識別子)に使用できる文字は、次のいずれかである。

  • 大文字アルファベット
  • 小文字アルファベット
  • アンダースコア(_)
  • 数字
  • ASCII以外の文字(詳しくはPEP-3131を参照されたし)
Cでは、ASCII文字以外の文字を使用できないが、Pythonでは、日本語名の変数や関数などが定義できる。なおCと同様に先頭文字に数字は使用できない。

また、Cでは次の名前はいくつかのライブラリや言語処理系で予約されている。

  • _が接頭辞のグローバルな名前
  • _が接頭辞でそれに大文字の名前
  • __が接頭辞の名前
これは言語的な制約ではなく、名前の競合を防ぐための注意やマナーである。

他にも、Cでは、ユーザが定数を全て大文字にしたり、グローバル変数の接頭辞をg_にしたりすることで、定義した場所以外でもそれらの意図を分かりやすくなるような工夫がある。これはコードの可読性を上げ、コードリーディングを助ける。Pythonには言語仕様で特別な意味を持つ名前があり、その分可読性が高い。

  • _で始まる名前は、モジュールから*(ワイルドカード)でインポートする場合に除外される。
  • クラス内の__で始まるメンバの名前はクラス内でだけ有効である。
なお2つ目のルールは、実際には呼び出せない訳ではなく、Pythonによって名前が変更され、オリジナルの名前でアクセスできない状態となる(それゆえdir関数で名前を調べられる)。

これに加えて、Pythonでメンバ関数を定義する場合、インスタンス変数へのアクセスは、メンバ関数の第一引数を通じて行う。

class Cls:
  def set(self, val):
    self.v = val
  def get(self)
    return self.v
そのため、他の変数(ローカル変数やクラス変数など)との区別がしやすいだろう。

文法

Cでは、空白文字(スペースや改行、タブ)に字句の区切り以外の意味はない。そして、文は;(セミコロン)までを1文として、ブロックは{と}を使って表す。それゆえ"Hello, World"を画面に出力するためのプログラムは次のように記述できる。

int printf(const char *, ...);int func(){int
i=0;while(i<3){printf("Hello, World\n");i += 1;}return 0;}
しかし多くのユーザは、次のような工夫によってコードの可読性を挙げる。
  • 1文を1行に記述して文の区切りを分かりやすくする。
  • 同じブロックの文を同じサイズのインデントにしてブロック階層を分かりやすくする。
これを適用すると、前述のコードは次のように記述できる(改行の位置はユーザのスタイルによって異なる)。
int printf(const char *, ...);
int func()
{
  int i=0;
  while(i<3){
    puts("Hello, World");
    i += 1;
  }
  return 0;
}
Pythonでは、言語仕様によって改行やインデントで文やブロックの区切りを表すように定められている。それゆえ、自然と可読性の高いコードとなる。以下に前述のコードをPythonで記述したものを紹介する。
def func():
  i = 0
  while(i<3):
    print("Hello, World")
    i += 1
  return 0

いくつかの言語には、データのコンセプトを表すがある。よくある組み込み型には、整数や小数、文字を表すものがある。Pythonには、これらの基本的な型に加えて開発者向けのコンセプトを表す型がある。

NotImplemented

Pythonには、未実装を表す型としてNotImplementedがある。この型の値は1つだけで、かつこのオブジェクトは全て同一である。また、評価結果は常に真となる。

def func():
  return NotImplemented

Ellipsis

Pythonには、省略を表す型としてEllipsisがある。この型の値は1つだけで、かつこのオブジェクトは全て同一である。また、評価結果は常に真となる。

def func():
  return Ellipsis

None

Cのvoidに該当する型として、Pythonには値が存在しないことを表すNone型がある。Cのvoid型がオブジェクトも値も持っていないのに対し、None型のオブジェクトは1つだけあり、値も1つ(None)だけある。それゆえ、引数としてNoneを指定でき、返り値もなにも返さない訳ではなくNoneを返す。Pythonの関数がreturn文に到達しなかった場合、その関数はNoneの値を返す。

def func():
  pass

print(func())
Cでは、返り値を持たない関数が存在する。それらはサブルーチンのような意図で記述されるものだが、定義上それは関数である。しかし、Pythonには値がないというコンセプトのデータを返すことで、全ての関数が返り値を持つ。

Noneの値はCのNULLポインタに該当し、評価結果は常に偽となる。


最適化のために

多くのスクリプト言語では、書き方の柔軟性や多様性、利便性などに優れている。Pythonもその1つだが、Pythonはそれに加えてプログラムの処理速度を向上させるようないくつかの工夫がある。以下にいくつか紹介する。

tuple

Pythonには、組み込みシーケンス型のコンテナが2つある。

  • list
  • tuple
この2つの型は基本的にほとんど性質を持つが、tupleがイミュータブルで、listがミュータブルであるという違いがある。

tupleを使用する利点は以下の2つである。

  • ハッシュ(辞書型)のキーとして利用できる。
  • list型より速い。
v = {(1,1):0, (1,2):2, (3, 5):4}
v[(1, 2)]

比較演算

Pythonの比較演算子は以下の通りである。

  • <
  • <=
  • ==
  • !=
  • >=
  • >
  • is
  • is not
  • in
  • not in
Cとは異なり、比較演算子の優先順位は全て同じである。また、Cでは比較演算子は2つの項を受け取り1つの値を返す単純なものであるが、Pythonではブール演算のように左から右に連鎖する。例えばこのように記述する。
10 > func() >= 3
これがCのコードならば、まず"10 > func()"を評価し、その結果として1か0が返され、それと3を>=で比較する意味となる(すなわち常に0になる)。もし範囲を表したいコードを書きたいならば、次のようなコードとなる。
10 > func() && func() >= 3
しかしこのコードはfunc()が2回評価される。 それゆえ、呼び出し毎に返り値が異なる場合に問題となる。また、2回呼び出される分冗長である。これを避けるため、Cでは次のように記述する。
10 > (tmp=func()) && tmp >= 3
これに対してPythonはこのように記述するだけで良い。
10 > func() >= 3
この時、"10 > func()"の評価結果がFalseの場合は処理を終了してその結果を返し、Trueの場合、func()の結果と3を>=演算で比較し、その結果(TrueかFalse)を返す。それゆえコードの可読性が高いだけでなく、効率が良い。


注意点

Cっぽい言語としてPythonを使おうとすると,いくつかの落とし穴がある。前述に紹介した比較演算などがそれである。また,わかりづらい表現も1つでない。ここでは,それらのいくつかを紹介する。

除算

Pythonの除算には2種類がある。型を持つ多くの言語では,整数同士の除算の場合,結果は整数を返し,余りはモジュロ演算によって計算される。これに対し,Python3の場合は次のような除算結果となる。

>>> 5/2
2.5
>>> 5//2
2
なお前述の結果はPythonのバージョンが3の結果で,2の場合は以下のようになる。
>>> 5/2
2
>>> 5//2
2
>>> 5.0//2
2.0
>>> 5.0/2
2.5

また,計算機の世界では符号付き除算の結果は,言語や実行環境に依存する。Pythonの場合,それは言語の仕様として定義されている。ここで気をつけないといけないのは,数学などで習う結果とは異なる結果を返す点である。 Pythonのモジュロ演算の結果は、0か符号が常に除数(この場合y)と同じになる。モジュロ演算の結果の絶対値は、常に除数以下になる。また、Pythonでは、切り捨て除算演算結果と除数の積に剰余を加えた値は、元の値と常に等しい。 以下に例を示す。

切り捨て除算演算除算結果モジュロ演算剰余
5//225%21
-5//-22-5%-2-1
-5//2-3-5%21
5//-2-35%-2-1

2進数

Pythonで2進数を扱う場合,いくつかの注意が必要である。Pythonは負の値を表現するのに2の補数が使用される。それゆえ,ビット反転と加算を使うと次のように符号を反転できる。

>>> 5
5
>>> (~5)+1
-5
>>> ~5
-6
それにも関わらず,負の値の時,2の補数の文字列を返す関数は,次のような結果を返す。
>>> bin(5)
'0b101'
>>> bin(-5)
'-0b101'
同様に2進数のリテラルを記述する場合,マイナスを表現するには次のように表現する。
>>> 0b101
5
>>> -0b101
-5


デコレータ

いくつかの言語では、次のような関数やクラスのための関数やクラスを定義できる。

  • 関数やクラスを受け取りその振る舞いを変更する関数
  • クラス生成の振る舞いを変更するクラス
Pythonでは、このようなものを記述するための仕様がある。これはコードの意図を分かりやすくし、可読性を向上させる。

関数デコレータ

Pythonには、関数に機能を明示的に追加または変更するための機能がある。それが関数デコレータである。Pythonを含むいくつかの言語では、関数を別の関数に渡すことができる。これを利用すれば関数デコレータと同様のコードを記述できるが、関数デコレータを使用すればその意図を明示的に表すことができる。関数デコレータは次のように定義し、使用できる。

def decorator_called(f):
  def wrapper():
    print("called ", f.__name__)
    return f()
  return wrapper

@decorator_called
def hello():
  print("Hello, World")
hello関数を呼び出した結果を以下に示す。
called  hello
Hello, World
このように関数デコレータは、関数定義の際に生成する関数に対して機能の追加や変更ができる。

関数デコレータには以下のようなものが用意されている。
  • @staticmethod
  • @classmethod
  • @abstractmethod
ちなみにabstractmethodはabcモジュールで定義されている。

クラスデコレータ

デコレータは関数だけでなく、クラスにも適用できる。これをクラスデコレータという。関数デコレータのようにクラスデコレータは、クラス定義の際にクラス情報を受け取り処理を加えたクラスを生成できる。

import sys
def py_major_version(major):
  def wrap(cls):
    if sys.version_info[0] < major:
      raise RuntimeError("version error")
    return cls
  return wrap

@py_major_version(3)
class Hoge:
  pass
このコードは、Pythonのメジャーバージョンが2以下の場合に例外を発生させる。 Python2の場合このコードは問題なく実行できるが、python2で実行すると次のような結果となる。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in wrap
RuntimeError: version error
クラスデコレータは、クラスが定義された(クラスオブジェクトが生成された)後で呼び出される。これに対し、クラスの生成方法そのものを変更する方法がある。それをメタクラスという。

メタクラス

メタクラスは、クラスを生成するためのクラスである。

def ham(self, arg):
  print(arg)

class MetaSpam(type): #組込み型typeを基に
  @classmethod
  def __prepare__(metacls, name, bases):
    print(name)
    print(bases)
    return {'ham':ham}

class Hoge(metaclass=MetaSpam):
  pass
メタクラスのメンバ関数
関数説明
__prepare__(metacls, name, bases)classブロックの実行前に呼び出されるクラスメソッド。ブロックに含まれる変数やメソッドの名前とオブジェクトの辞書を返す。
__init__(cls, bases, classdict)クラスオブジェクトの初期化
__new__(metacls, bases, classdict)クラスオブジェクトの生成
変数名説明
nameクラス名
bases基底クラスを格納したタプル
clsクラス
metaclsメタクラス
classdictクラスのメンバを格納した辞書
メタクラスは次のように指定する。
  • class クラス名(metaclass=メタクラス)
  • class クラス名(親クラス, metaclass=メタクラス)
  • class クラス名(metaclass=メタクラス, 引数名=引数)

用意されたメタクラスには次のようなものがある。

abc.ABCMeta仮想サブクラス実際には継承関係にないクラスの基底クラスとなれる


ライブラリ

Pythonには、標準や外部を含め、実にさまざまなライブラリがある。以下にいくつか紹介する。

モジュールサンプルコード
sys
import sys
print(sys.argv)
os
import sys
import os

r, w = os.pipe()
pid = os.fork()
if pid:
  os.close(w)
  out = os.read(r, 10)
  while True:
    buf = os.read(r, 10)
    if buf:
      out += buf
    else:
      break
  os.write(sys.stdout.fileno(), out)
  os.close(r)
else:
  os.close(r)
  os.dup2(w, sys.stdout.fileno())
  os.close(w)
  os.execlp("ls", "ls", "-l")
re
import re
m = re.match("^a(.*?)o", "aiueo")
print(m.group(1)) # iueを抽出
gtk
import gtk

win = gtk.Window()
win.show_all()
webkit
import gtk
import webkit

win = gtk.Window()
web = webkit.WebView()

web.load_uri("http://www.google.co.jp")
win.add(web)
win.show_all()
GTKとWebKitはPython2で行なっている。なお各ライブラリ(モジュール)の使い方は、help関数を使って調べることができる。

Pythonの基本

投稿日:
タグ:

本稿は私のPython学習のメモやまとめ、特にPythonの基本をまとめたものである。学習には主に次の2つの情報源を使用した。


単純文

単純文とは、単一の論理行内に収められる文のことである。

代入文

いくつかの言語では、代入や複合代入は演算の1つであり、式文として記述される。しかしPythonでは、それらは文として独立している。とはいえ、以下のような単純な代入ではその違いは感じないだろう。

v = 5
しかし、代入演算のように代入の演算結果を利用しようとすれば、エラーとなる。
v = (w = 5) 
とはいえ次のように代入した変数の値を別の変数に代入するのは、当然可能である。
v = w = 5
また、Pythonでは次のようにカンマで区切って複数の変数を1文で代入することが可能である。
v, w = 5, 10
この文では、vに5を、wに10を代入している。代入文は項数に限らず、まず右辺の式のリストを評価し、その後ターゲットのリストの左から右へ順番に代入していく。すなわち次の式はvにwの値を、wに元のvの値を代入する。
v, w = w, v

代入とは名前(識別子)をオブジェクトに束縛、または再束縛することである。代入文では既にその名前が束縛されている場合、オブジェクトの参照カウントを1つ減らす。もしオブジェクトの参照カウントが0になった場合、オブジェクトは解放され、そのデストラクタが呼び出される。

>>> class Hoge:
...     def __del__(self): # デストラクタ
...             print("release")
... 
>>> v = Hoge()
>>> v = 0
release
>>> x = y = Hoge()
>>> x = 1
>>> y = 2
release

del文

del文は指定した名前の束縛を解除し、オブジェクトの参照カウントを1つ減らす。もしオブジェクトの参照カウントが0になった場合、オブジェクトは解放され、そのデストラクタが呼び出される。

del x
もし名前が未束縛ならば、NameError例外が送出される。

また、del文はカンマで区切って複数の名前を指定できる。その際、ターゲットは左から右に順に再帰的に削除される。

式文

式文とは演算を行う文のことである。Pythonの演算子の種類と計算順序は以下を参照されたし。

演算子の優先順位

演算子の優先順位は表の上に行くほど高く、下に行くほど低い。同じ優先順位を持つ場合、結合/連鎖に従って評価順が決まる。

演算子機能結合/連鎖
  • (expressions...)
  • [expressions...]
  • {key:value...}
  • {expressions...}
  • x[y]
  • x[y:z]
  • x.y
  • func([arg ...])
→結合
  • x ** y
べき数←結合
  • +x
  • -x
  • ~x
単項演算子
  • x * y
  • x / y
  • x // y
  • x % y
/は除算演算で、//は切り捨て除算演算である。除算演算は小数まで計算する。モジュロ演算の結果は、0か符号が常に除数(この場合y)と同じになる。モジュロ演算の結果の絶対値は、常に除数以下になる。また、Pythonでは、切り捨て除算演算結果と除数の積に剰余を加えた値は、元の値と常に等しい。 →結合
  • x + y
  • x - y
  • x << y
  • x >> y
算術シフト演算
  • x & y
ビット単位AND
  • x ^ y
ビット単位XOR
  • x | y
ビット単位OR
  • x in S
  • x not in S
  • x is y
  • x is not y
  • x < y
  • x <= y
  • x == y
  • x != y
  • x >= y
  • >
比較演算。"is"や"is not"は同一性の比較で、"in"や"not in"はデータ構造の帰属のチェックの演算である。また、比較演算はオーバーロードされている。以下にいくつかの型の場合を紹介する。
機能
数値数学的に大小を比較。
bytes辞書順に大小を比較。
文字列各文字の文字コードの大小を順に比較。
リスト各要素を順に比較し要素の大小を比較。
setスーパセットやサブセットの判断。
→連鎖
  • not x
論理否定
  • x and y
論理積→連鎖
  • x or y
論理和
  • x if C else y
条件演算(3項演算)
lambda [x, ...] : expression ラムダ式。
v = lambda x, y : x + y
v(1, 2)


break文

break文はwhile文やfor文などのループを終了させる。もしelse節があってもそれは無視される。

continue文

continue文はwhile文やfor文などのループの次の周期の処理へ移動させる。


return文

return文は関数定義内で現れ、制御を関数呼び出し側に戻して指定した値を、式を指定した場合はその評価結果の値を返す。

def func():
  return 5
返り値は省略可能で省略した場合はNoneが返される。また、return文がなく関数の最後まで行った場合も同様である。return文はジェネレータ関数の中では記述できない。

yield文

ジェネレータ関数では、return文の代わりにyield文を使用する。というよりもyield文を使用した関数定義はジェネレータ関数となる。ジェネレータ関数でreturn文を使用するとエラーとなる。ジェネレータ関数はジェネレータオブジェクトを生成する。例えばこのようなジェネレータ関数を定義したとする。

def myGenerator():
  i = 0
  while i < 5:
    yield i
    i += 1
このコードはジェネレータオブジェクトの__next__関数で呼び出され、yield文までが処理される。そして次に__next__関数が呼び出されると、yield文の次の文から処理され、関数定義の末尾か次のyield文まで実行される。
>>> for x in myGenerator():
...   print(x)
... 
0
1
2
3
4
ジェネレータ関数の詳細は「ジェネレータ関数」で述べる。


global文

global文は指定した名前(識別子)をグローバル変数として解釈するようにする文である。global文にはカンマで区切って複数指定できる。

global文なしglobal文あり
str = "global"
class Cls:
  str = "instance"
  def func1(self):
    pass
    str = "func"
    print(str)
  def func2(self):
    print(str)
  def func3(self):
    print(self.str)
str = "global"
class Cls:
  str = "instance"
  def func1(self):
    global str
    str = "func"
    print(str)
  def func2(self):
    print(str)
  def func3(self):
    print(self.str)
>>> c = Cls()
>>> c.func1()
func
>>> c.func2()
global
>>> c.func3()
instance
>>> c = Cls()
>>> c.func1()
func
>>> c.func2()
func
>>> c.func3()
instance

nonlocal文

関数内の名前(識別子)のスコープのことをローカルスコープという。Pythonでは、関数内で別の関数を定義できるため、内側と外側の関数で名前の競合が発生する。nonlocal文は指定した名前(識別子)が最も近傍のローカルスコープで以前に束縛された変数を参照するようにする。

nonlocal文なしnonlocal文あり
def exFunc():
  str = "ex"
  def inFunc():
    pass
    str = "in"
    print(str)
  inFunc()
  print(str)
def exFunc():
  str = "ex"
  def inFunc():
    nonlocal str
    str = "in"
    print(str)
  inFunc()
  print(str)
>>> exFunc()
in
ex
>>> exFunc()
in
in


raise文

指定した例外を送出する。

def div(x, y):
  if y==0:
    raise ZeroDivisionError
  return x // y
何も指定しなかった場合、現在のスコープで最終的に有効になっている例外を再送出する。もしもそのような例外がない場合TypeError例外が送出される。

例外はtry文で受け取り処理を行うことができる。例外については「try文」で詳述する。

assert文

条件が偽だった場合にAssertionErrorを送出する文である。 例えばこのような関数を定義したとする。

def test(left, right):
  assert left < right
条件が真の場合と偽の場合の結果は以下のようになる。
>>> test(1, 3)
>>> test(3, 1)
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in test
AssertionError


pass文

pass文は意味のない文であり、構文上何か必要な場合に記述する。例えば、関数定義で処理内容を記述しない場合はこのように書く。

def func(): pass


import文

import文はモジュールのロードに使用する文である。モジュールの読み込み先ディレクトリは、sysモジュールのpathで定義されている。

import文には、asやfromキーワードの組合せでいくつかのパターンがある。以下にいくつか例を示す。

  • import sys
    sys.path
  • import sys as hoge
    hoge.path
  • from sys import path
    path
  • from sys import *
    path
*を指定した場合、_を接頭辞とする名前を除く全てのメンバをロードする。ただし、モジュールに__all__という名前のメンバがあれば、__all__に含まれる名前のメンバのみがロードされる。

import文では、ロードするモジュールは、カンマで区切って複数記述できる。また、指定したモジュールがなかった場合、ImportError例外が送出される。

モジュール

Pythonスクリプトを記述し、ライブラリとして利用できるようにしたファイルをモジュールという。モジュールとモジュールを利用したコードのサンプルを以下に示す。 なおhoge.pyで記述したドキュメントを記述した文字列については、「ドキュメンテーション文字列」で後述する。

hoge.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"サンプルモジュールを定義"
class Hoge:
  "サンプルモジュールのクラス"
  def add(self, addee:"被加数", adder:"加数") -> "和":
    "サンプルモジュールのメンバ関数"
    return addee + adder
fuga.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import hoge
h = Hoge()
print(h.add(1, 2))
hoge.pyについて記述したドキュメントは、import後にhelp(hoge)と指定することで閲覧できる。

パッケージ

全ての機能を1つのモジュールに集約するのではなく、複数のモジュールを記述し、それを一括にロードする方法がある。それがパッケージである。パッケージはモジュールと同様にimport文でロードできる。パッケージとは普通のディレクトリであり、必ず__init__.pyというファイルが格納されている。__init__.pyは存在していれば中身が空でも構わない。パッケージの内容は__init__.pyの中身となる。すなわち、"hoge/"というディレクトリのパッケージがあるとする。この時、"import hoge"と行うとロード対象は"hoge/__init__.py"の中身となる。


複合文

複合文とは、2行以上の複数の論理行に収められる文のことである。

if文

if文は分岐文である。if文には次の3つのキーワードがある。

  • if
  • elif
  • else
Cではifとelseしかなく、複数の条件を書く場合はelseの中にifを書いていたが、Pythonではelif節というものが存在する。if文は1個のif節と、1個か0個のelse節、0個以上のelif節からなる。文法的に、はじめにif節、次にelif節、最後にelse節を書く。 elifはifが偽の時に処理され、複数のelifがある場合は上の方が先に評価される。
def func(i):
  if i < 10:
    print("10未満である")
  else:
    print("10以上である")

while文

while文は繰り返し文の1つである。

while 条件式:
  処理1
[else:
  処理2]
はじめに条件式が評価され、その結果が真であれば、処理を実行する。その後、処理が終了する度に条件式が評価され、偽になるまで処理を続ける。

また、Pythonのwhile文にはelse節がある。

for x in 1, 2, 3, 4:
  print(x)
else:
  print("loop end")
もしループの条件式の評価結果が偽となった場合、ループが終了した後に実行される。ただしbreak文で終了した場合、else節はスキップされる。

for文

for文は繰り返し文の1つである。Pythonでは、イテレータを使用し各要素に何らかの処理を行うような場合にfor文を使用する。

for ターゲットリスト in 式リスト :  
  処理1
[else:
 処理2]
ターゲットリストや式リストは次のように記述する。
>>> for x in 0,1,2,3:
  print(x)
また、以下のようにターゲットリストには複数の変数を指定できる。
>>> for x, y in [0,10], [5,20], [10,30]:
...     print(str(x) + "," + str(y))
... 
0,10
5,20
10,30
各式は最初に1度だけ評価され、イテレータが生成される。例えば式リストに組み込み関数rangeを使用し、"range(1, 5)"と記述した場合、"[1, 2, 3, 4]"となり、各要素が順に代入される。
>>> def func():
...     print("hoge")
...     return 1
... 
>>> for x in func(), func():
...     print("fuga")
... 
hoge
hoge
fuga
fuga

Pythonのfor文にはelse節がある。もしループの条件式の評価結果が偽となった場合、ループが終了した後に実行される。break文で終了した場合、else節はスキップされる。


with文

with文を使用すると、開始処理と終了処理があるような場合に、それを明示的に表現した簡潔なコードを記述できる。

with open("./write.txt", "w") as f:
  f.write("Hello\n")
  f.write("ハロー\n")
  f.write("はろー\n")
with文では、処理の最初に__enter__関数が、最後に__exit__関数が呼び出される。with文で__enter__関数の処理が正常に実行されたならば、__exit__関数が呼び出されることが保証される。 もしwithのスイート内で例外が送出したら、型と値、トレースバックが__exit__関数の引数に与えられる。それ以外の場合、各変数にはNoneが代入される。また、__exit__関数がTrueを返さなかった場合、with文は例外を送出する。__enter__関数と__exit__関数をオーバーライドする例を以下に示す。
class Cls:
  def __enter__(self):
    print("begin")
    return self
  def __exit__(self, type, value, traceback):
    print("end")
    return True
  def func(self, str):
    print(str)
実行結果は次の通りである。
>>> with Cls() as c:
...     c.func()
... 
begin
end
また、次のように複数の束縛を行う場合、カンマで区切って簡潔に記述できる。
with open("./write.txt", "w") as w
  with open("./read.txt", "r") as r:
    print(r.read(), file=w)
with open("./write.txt", "w") as w, open("./read.txt", "r") as r:
  print(r.read(), file=w)


関数定義

関数定義はdefキーワードを使用する。

def add(x, y):
  return x + y
定義した関数は関数呼び出し演算で呼び出すことができる。

引数
デフォルト引数
関数定義では、引数を省略した際に代入されるオブジェクトを指定できる。
>>> def func(str = "default"):
...     print(str)
... 
>>> func("hoge")
hoge
>>> func()
default
可変引数
Pythonでは、引数の数が任意個数の関数を定義できる。
*arg
タプル型で順に格納される。
>>> def func(arg1, *args):
...     print(args)
...
>>> func(0,1,2,3,4,5)
(1, 2, 3, 4, 5)
**arg
辞書型で格納される。
>>> def func(arg1, **args):
...     print(args)
... 
>>> func(0)
{}
>>> func(0, v=1, w=2)
{'w': 2, 'v': 1}
引数名指定
関数呼び出しで引数を渡す際、引数の名前を指定して渡すことができる。
>>> def add(addee, adder):
...     return addee + adder
... 
>>> add(adder=10,addee=5)
15
関数デコレータ

関数デコレータとは、関数に機能を明示的に追加または変更するための機能である。関数定義は1つ以上の関数デコレータでラップできる。

def decorator_called(f):
  def wrapper():
    print("called ", f.__name__)
    return f()
  return wrapper

@decorator_called
def hello():
  print("Hello, World")
hello関数を呼び出した結果を以下に示す。
called  hello
Hello, World
このように関数デコレータは、関数の生成の際に関数を受け取りそれに何らかの処理を加えて関数を呼び出す。

ジェネレータ関数

ジェネレータ関数はイテレータの一種で、ジェネレータオブジェクトを作成する関数である。Pythonでは、関数定義でreturn文の代わりにyield文を記述することでジェネレータ関数を定義できる。

def fib():
  x, y = 0, 1
  while True:
    yield x
    x, y = y, x + y
ジェネレータのコードは、はじめに関数のコードの頭からyield文まで処理し、次に呼び出した際はyieldの次の文からyield文まで処理する。ジェネレータのコードは、__next__関数を呼び出すことで処理される。
>>> f = fib()
>>> f.__next__()
0
>>> f.__next__()
1
>>> f.__next__()
1
>>> f.__next__()
2
>>> f.__next__()
3
>>> f.__next__()
5
このジェネレータオブジェクトをfor文で指定すると、無限に処理され続ける。これを改良したコードを以下に示す。
def fib(max):
  x, y = 0, 1
  while x < max:
    yield x
    x, y = y, x + y
これを実行すると次のようになる。
>>> f = fib(10)
>>> for x in f:
...     print(x)
... 
0
1
1
2
3
5
8


クラス定義

クラスは次のようにして定義する。

class Cls:
  def __init__(self):     # <コンストラクタ>
    self.str = "instance" # インスタンス変数
    print("called constructor")
  def __del__(self):      # <デストラクタ>
    print("called destructor")
  def func(self, arg0, arg1):
    str = "local"         # ローカル変数
    print(self.str)
    print(str)
    print(arg0)
    print(arg1)
コンストラクタやデストラクタ、インスタンス変数の定義もご覧の通りである。以下に実行例を示す。
>>> c = Cls()
called constructor
>>> c.func(0, 1)
instance
local
0
1
>>> del c
called destructor
また、Pythonにはコンストラクタ(__init__)とは別にインスタンスアロケータ(__new__)というものがある。 __new__は静的メソッドで、新しいインスタンスを生成する際に自動的に呼び出される。__init__の第1引数がインスタンスであるのに対し、__new__にはクラスが与えられる。__new__()がclsのインスタンスを返さない限り、インスタンスの__init__は呼び出されない。なお__init__と__new__の第2引数以降は同じものが与えられる。
class Hoge:
  def __new__(cls):
    print("new Parent")
    return super().__new__(cls)
  def __init__(self):
    print("init Parent")
このクラスを利用した例は次の通りとなる。
>>> h = Hoge()
new Parent
init Parent
__new__は変更不能な型 (int, str, tuple など) のサブクラスでインスタンス生成をカスタマイズするために使用される。それゆえ、基本的に__new__をオーバーライドする必要はない。

継承
継承は次のように記述する。
class Sub(Parent):
  pass
また、Pythonは多重継承をサポートする。多重継承では、基底クラスをカンマで区切って記述する。
class Sub(Parent1, Parent2):
  pass
オブジェクトの型を取得する場合はtype関数を使用する。また、オブジェクトの型が指定したクラスか、そのサブクラスであるかを調べたい場合は、isinstanceを使用する。
>>> class Parent: pass
... 
>>> class Child(Parent): pass
... 
>>> p, c = Parent(), Child()
>>> isinstance(p, Parent)
True
>>> isinstance(c, Parent)
True
カプセル化
Pythonでは、メンバへのアクセス制御の種類はあまり多くない。
  • 非公開(private)な名前を設定する場合、名前の接頭辞に__を付ける。
  • 前述以外の名前は全て公開(public)な名前となる。
なおPythonでは、非公開な名前はPythonによって名前を変更されるだけで、アクセスは可能である。
ポリモフィズム(多態化)
Pythonでは、メンバ関数は標準でオーバーライド可能である。
演算子の多重定義
Pythonでは、いくつかの特殊関数をオーバーロードすることで演算子の多重定義を実装できる。以下に例をいくつか紹介する。
関数名演算子サンプル
__add__(self, other) +
__sub__(self, other) -
__mul__(self, other) *
__truediv__(self, other) /
__floordiv__(self, other) //
__mod__(self, other) %
__pow__(self, other) **
__lshift__(self, other) <<
__rshift__(self, other) >>
__or__(self, other) |
__and__(self, other) &
__xor__(self, other) ^
__lt__(self, other) <
__le__(self, other) <=
__eq__(self, other) ==
__ne__(self, other) !=
__gt__(self, other) >
__ge__(self, other) >=
__neg__(self) -
__pos__(self) +
__call__(self, [args]) ()
この他にも累積代入文や型チェックなどをオーバーライドするために、さまざまな特殊関数が用意されている。
クラス関数
クラス変数
クラス関数やクラス変数は次のように関数デコレータで定義できる。
class Cls:
  @classmethod
  def set(cls, v):
    cls.v = v
  @classmethod
  def p(cls):
    print(cls.v)
以下に実行例を示す。
>>> o1, o2 = Cls(), Cls()
>>> o1.set("hoge")
>>> o2.p()
hoge

クラスデコレータ

クラスデコレータとは、クラス定義に処理を加える機能のことである。

import sys
def py_major_version(major):
  def wrap(cls):
    if sys.version_info[0] < major:
      raise RuntimeError("version error")
    return cls
  return wrap

@py_major_version(3)
class Hoge:
  pass
このコードは、Pythonのメジャーバージョンが2以下の場合に例外を発生させる。

メタクラス

メタクラスは、クラスを生成するためのクラスである。

def ham(self, arg):
  print(arg)

class MetaSpam(type): #組込み型typeを基に
  @classmethod
  def __prepare__(metacls, name, bases):
    print(name)
    print(bases)
    return {'ham':ham}

class Hoge(metaclass=MetaSpam):
  pass
メタクラスは次のように指定する。
  • class クラス名(metaclass=メタクラス)
  • class クラス名(親クラス, metaclass=メタクラス)
  • class クラス名(metaclass=メタクラス, 引数名=引数)


try文

try文は例外処理やクリーンアップ処理を行う文である。いくつかの言語では、エラー発生を通知するための手段として例外処理機構を持つ。例外処理機構は、呼び出し側へのエラー通知機能や、エラー処理とエラー通知の分離などさまざまな特徴を持つが、本稿ではそれらの詳細については言及しない。

try文は、以下のように例外が送出し得る文をtry節に記述し、送出するとexcept節で受け取ることができる。else節を記述した場合、制御がtry節の末尾までいった場合に実行される。これに対し、finally節を記述した場合、どの節を処理したかに関わらず必ず最後に呼び出される。

def div(x, y):
  try:
    result = x // y
  except ZeroDivisionError:
    result = "Error"
  finally:
    print(result)
except節とelse節、finally節は省略可能であり、except節は複数記述でいる。ただし、except節とfinally節の両方を省略することはできない。

また、except節は送出された例外オブジェクトをasで指定した名前に束縛することができる。

class myError(Exception):
  msg = ""

class Cls:
  def func(self):
    e = myError()
    e.msg = "error"
    raise e

c = Cls()
try:
  c.func()
except myError as my:
  print(my.msg) # 画面に"error"を出力
例外に使用するクラスは、BaseExceptionを例外していなければならない。しかし通常独自の例外を定義する場合、ExceptionというBaseExceptionのサブクラスを継承する。

コメント

Pythonには、コメントは#から行末までの1つしかない。

func() # 関数funcを呼び出す。

ドキュメンテーション文字列

Pythonでは、コメントとは別にドキュメントを読み書きする仕組みがある。関数のドキュメントはhelp関数で閲覧できる。

関数アノテーション
関数の引数と返り値を説明するドキュメント(関数アノテーション)は次のように記述できる。
def sum(addee:"被加数", adder:"加数") -> "和":
  return addee + adder
ドックストリング
関数やクラス、モジュールの説明(ドックストリング)は、スイート内の(Pythonの)文が始まる前に文字列リテラルを置くことで記述できる。
def sum(addee:"被加数", adder:"加数") -> "和":
  """
  2つの値を受け取ってその加算結果を返す
  """
  return addee + adder

組込み型

Pythonには、組み込みの型がいくつかある。以下にいくつか紹介する。

論理型(bool)
論理型はTrueかFalseの2つのいずれかの値を持つ。リテラルの書き方もまたTrueかFalseである。
数値型
数値型には次のようなものがある。
説明リテラルの例
整数型(int)メモリサイズの制限があるだけで無限の定義域を持つ。負の数は2の補数で表しており符号ビットが左に無限に続くような値となる。10, 0x1a, 017, 0b1011
浮動小数点型(float) 他の言語同様2進数で保持されるため、10進数との誤差が生じる。例えば"0.1+0.1+0.1"は"0.30000000000000004"となるため、"0.1+0.1+0.1==0.3"は偽となる。 3.14, 1e3
複素数型(complex)3j
数値型のための関数には、絶対値を求める関数absやべき数を求める関数pow、文字列の文字コードを取得する関数ordなどがある。
NotImplemented
Ellipsis
Python独特の型で、それぞれ未実装と省略を表す型。値はそれぞれ1種類しかなく、それぞれ型と同じ名前のリテラルである。評価結果は必ず真となる。
None
Cのvoidに該当する型として、Pythonには値が存在しないことを表すNone型がある。Cのvoid型がオブジェクトも値も持っていないのに対し、None型のオブジェクトは1つだけあり、値も1つだけある。NoneはCのnilにも該当し、Noneの評価結果は常に偽となる。また、Pythonでは関数の返り値を省略した場合はこのリテラルが返される。

データ構造

Pythonのデータ構造には次の3種類がある。

シーケンス型
シーケンス型はシーケンシャルに処理するためのデータ構造である。シーケンス型には以下のようなものがある。
説明リテラル例
tupleイミュレータブルな配列(0, 1, 2)
listミュータブルな配列[0, 1, 2]
string文字列"aiueo"
シーケンス型の詳細は「シーケンス型」で説明する。
集合型
集合型は非シーケンスなデータ構造である。
説明リテラル例
set格納順が不定なデータ構造{1, 2, 3}
辞書型
辞書型はキーでデータにアクセスするデータ構造である。
説明リテラル例
dictハッシュ{"key1":1, "key2":"hello"}

シーケンス型

シーケンス型はシーケンシャルに処理するためのデータ構造である。Pythonのシーケンス型には次の3種類のものがある。

  • コンテンナ
  • イテレータ
  • ジェネレータ
シーケンス型には次のような演算子や組み込み関数がある。
演算説明実行例
x in s帰属であることをチェック。
>>> "Hello" in "Hello, World"
True
x not in s帰属していないことをチェック。
>>> "Hello" not in "Hello, World"
False
s1 + s22つのシーケンスを結合。
>>> [0,1,2,3] + [4,5,6]
[0, 1, 2, 3, 4, 5, 6]
s * nsをn個分結合。
>>> [1,2,3]*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
n * s
s[i]指定した番号の要素にアクセス。
>>>"Hello"[1]
e
s[i:j]指定した範囲を抽出したものを生成。
>>> (0,1,2,3,4,5,6,7,8)[1:-2]
(1, 2, 3, 4, 5, 6, 7)
s[i:j:k]指定した範囲でk毎に取り出したシーケンスを生成。
>>> [0,1,2,3,4,5,6,7,8][1:-2:2]
[1, 3, 5]
len(s) 要素数を返す。
>>> len([0,1,2,3])
4
min(s) 要素のうち最小のものを返す。
>>> min([0,1,2,3])
0
max(s) 要素のうち最大のものを返す。
>>> max([0,1,2,3])
3
s.index(x[, y[, z]]) xと最初に一致した要素の添字番号を返す。yは検索の開始位置を、zは検索の終了位置を表す。ValueError例外を送出する。
>>> [4,3,2,1,0].index(3)
1
s.count(x) 指定した値がいくつあるかを返す。
>>> [1,2,3,1,4,1].count(1)
3

CプログラマのPythonの落とし穴

投稿日:
タグ:

本稿は私のPython学習のメモやまとめ、特にPythonを学ぶ上でCプログラマから見た視点で気をつけなければいけないことや特徴をまとめたものである。学習には主に次の2つの情報源を使用した。


文法

Cでは、空白文字(スペースや改行、タブ)に字句の区切り以外の意味はない。そして、文は;(セミコロン)までを1文として、ブロックは{と}を使って表す。それゆえ"Hello, World"を画面に出力するためのプログラムは次のように記述できる。

int printf(const char *, ...);int func(){int i=0;while(i<3){printf("Hello, World\n");i += 1;}return 0;}
しかし多くのユーザは、次のような工夫によってコードの可読性を挙げる。
  • 1文を1行に記述して文の区切りを分かりやすくする。
  • 同じブロックの文を同じサイズのインデントにしてブロック階層を分かりやすくする。
これを適用すると、前述のコードは次のように記述できる(改行の位置はユーザのスタイルによって異なる)。
int printf(const char *, ...);
int func()
{
  int i=0;
  while(i<3){
    puts("Hello, World");
    i += 1;
  }
  return 0;
}
Pythonでは、言語仕様によって改行やインデントで文やブロックの区切りを表すように定められている。それゆえ、自然と可読性の高いコードとなる。以下に前述のコードをPythonで記述したものを紹介する。
def func():
  i = 0
  while(i<3):
    print("Hello, World")
    i += 1
  return 0
文の区切りはともかく、ブロックの終端字句がない仕様は、慣れないと違和感があるかもしれないが、デタラメなインデントのコードを読むよりは遥かに読み易いだろう。


命名規則

Pythonの名前(識別子)に使用できる文字は、次のいずれかである。

  • 大文字アルファベット
  • 小文字アルファベット
  • アンダースコア(_)
  • 数字
  • ASCII以外の文字(詳しくはPEP-3131を参照されたし)
Cでは、ASCII文字以外の文字を使用できないが、Pythonでは、日本語名の変数や関数などが定義できる。なおCと同様に先頭文字に数字は使用できない。

また、Cでは次の名前はいくつかのライブラリや言語処理系で予約されている。

  • _が接頭辞のグローバルな名前
  • _が接頭辞でそれに大文字の名前
  • __が接頭辞の名前
これは言語的な制約ではなく、名前の競合を防ぐための注意やマナーである。

他にも、Cでは、ユーザが定数を全て大文字にしたり、グローバル変数の接頭辞をg_にしたりすることで、定義した場所以外でもそれらの意図を分かりやすくなるような工夫がある。これはコードの可読性を上げ、コードリーディングを助ける。Pythonには言語仕様で特別な意味を持つ名前がある。

  • _で始まる名前は、モジュールから*(ワイルドカード)でインポートする場合に除外される。
  • クラス内の__で始まるメンバの名前はクラス内でだけ有効である。
それゆえ前述の名前をその意味に反する意図で使用することはできない。なお2つ目のルールは、実際には呼び出せない訳ではなく、Pythonによって名前が変更され、オリジナルの名前でアクセスできない状態となる(それゆえdir関数で名前を調べられる)。


代入文

Pythonでは代入は演算ではなく文である。Cの代入は演算であり、かつ代入した値を返すため、このように複合式で一時変数に代入するような記述ができた(後述の通りそもそもPythonではこのような一時変数は不要だが)。

if (1 < (tmp = func()) &&  tmp <  5) ) printf("hoge");
しかしPythonでは代入は式文ではなく1つの文であり、このような記述はできない。とはいえ、代入文の=の右辺に式を書くことは可能であるため、次のような記述は問題ない。
a = 1 + 2
なおCにあった+=や-=のような複合代入演算もPythonでは1つの文である。このような文は累算代入文(augmented assignement statement)という。


真偽

Cでは、0や0に変換される値(0.0や'\0'、NULLなど)が偽で、それ以外の全ての値は真である。これに対して、Pythonで偽とみなされる値は次のいずれかである。

  • False
  • None
  • 空文字列
  • 空のコンテナ
  • 全ての型の値の0
真はこれ以外である。ちなみにbool型はint型の部分型であり、Falseをint型に変換すると0となる。ただし整数型と異なり、文字列変換すると"True"や"False"になる。


None

Cのvoidに該当する型として、Pythonには値が存在しないことを表すNone型がある。Cのvoid型がオブジェクトも値も持っていないのに対し、None型のオブジェクトは1つだけあり、値も1つ(None)だけある。それゆえ、引数としてNoneを指定でき、返り値もなにも返さない訳ではなくNoneを返す。Pythonの関数がreturn文に到達しなかった場合、その関数はNoneの値を返す。

def func():
  pass

print(func())
Cでは、返り値を持たない関数が存在する。それらはサブルーチンのような意図で記述されるものだが、定義上それは関数である。しかし、Pythonには値がないというコンセプトのデータを返すことで、全ての関数が返り値を持つ。

Noneの値はCのNULLポインタに該当し、評価結果は常に偽となる。


演算

  • 条件演算(3項演算)
  • 除算演算とモジュロ演算
  • シフト演算
  • 比較演算
  • ブール演算

条件演算(3項演算子)
Pythonも条件演算をサポートするが、Cとは書き方が異なる。Cでは3項演算子を次のように記述する。
a<10? a : 0
これに対し、Pythonでは同様の式を次のように記述する。
a if a<10 else 0
ブール演算
PythonとCのブール演算では演算子の字句が異なる。字句はそれぞれこのように対応する。
PythonC
not!
and&&
or||
また、ANDブール演算やORブール演算は、Cと同様に左辺から右辺に向けて順に評価される。そして、andは偽になった時点で、orは真になった時点で評価を終了する。ただし、CとPythonでは返り値が異なる。
言語真偽返り値
C1
0
Python最後に評価した値
真偽については「真偽」を参照されたし。
除算演算(//と/)
モジュロ演算

/が除算演算、//が切り捨て除算という。除算演算が小数まで計算するのに対し、切り捨て除算演算が剰余を切り捨てる。除数が0の場合、ZeroDivisionError例外が発生する。除算演算は、Python2と3で異なる処理を行う。Python2では、除算演算や切り捨て除算演算に関わらず、項が2つとも整数型または長整数型であれば、整数型や長整数型の除算結果を返す。しかしPython3では、除算演算の場合は浮動小数点型を返し、切り捨て除算の場合は2つの項が整数型か長整数型であれば、整数型を返す。

x % y
符号付き除算及びモジュロの演算結果は言語処理系に依存する。Pythonの場合、モジュロ演算の結果は、0か符号が常に除数(この場合y)と同じになる。モジュロ演算の結果の絶対値は、常に除数以下になる。また、Pythonでは、切り捨て除算演算結果と除数の積に剰余を加えた値は、元の値と常に等しい。
x == (x // y)*y + (x % y)
すなわち、このような被除数と除数の絶対値が5と2の除算やモジュロ演算の結果は次のようになる。
切り捨て除算演算除算結果モジュロ演算剰余
5//225%21
-5//-22-5%-2-1
-5//2-3-5%21
5//-2-35%-2-1
ちなみにJavaの場合、除算結果は0方向に切り捨てられ、かつ"x == (x / y)*y + (x % y)"はtrueとなるポリシーである。

なおPythonの%演算子は、標準で文字列オブジェクト用にオーバーロードされている。

シフト演算
シフト演算には、論理シフトや算術シフトなどの種類があり、Cのシフト演算がどれであるかは、曖昧である。これに対し、Pythonのシフト演算は算術シフトである。すなわち演算結果は次の式と同値となる。
x >> nx // pow(2,n)
x << nx * pow(2,n)
右辺の項は、負の値を指定するとValueError例外が、sys.maxsizeより大きいとOverflowError例外が発生する。
比較演算

Cと異なり比較演算子は全て同じ優先順位である。比較演算には次の種類がある。

  • <
  • <=
  • ==
  • !=
  • >=
  • >
  • is
  • is not
  • in
  • not in
Pythonでは、比較演算子はCとはやや異なる振る舞いをする。Pythonの比較では2つ以上の項を記述できる。これは可読性に優れているだけでなく、いくつかの場合に性能(効率)的にも優れている。

例えばCでこのような関数があったとする。

int func(){
  int retval = 1;
  retval += 1;
  return retval;
}
この時、func()の値の範囲を評価するコードを書くには、数学っぽくこのように書きたくなるかもしれない。
3 > func() > 1
しかし、Cでは>演算子は2項演算子であり、これは別の意味となる。この式では、はじめに3>func()を評価し、>演算子が1か0を、この例では1を返す。そしてその値(1)と1を比較し最終的にこの式文は0を返す。それゆえ、範囲を表すにはこのように記述する。
3 > func() && func() > 1
これと同じ意味のコードをPythonで書くとすれば、次のように記述できる。
3 > func() and func() > 1
しかしながらこのようなコードはfunc()が2回呼び出されるため冗長である。また、関数の結果が呼び出し毎に変わる場合(例えばretvalがstaticなローカル変数の場合)、ユーザの意図したコードと異なる場合がある。これを防ぐため、Cではこのような一時変数を使用することで回避してきた。
3 > (tmp=func()) && tmp > 1
これに対してPythonの比較演算子はこのような記述だけで良い。
3 > func() > 1
Pythonの比較演算子はANDブール演算のように各項を左から右へ評価していき、Falseの式より右辺を評価しない。とはいえ、機械語的に3項の比較など考え難いため、恐らくコンピュータ内部では2項の比較を何度も行っているはずである。


繰り返し文

Cでは繰り返し文を次のように記述する。

for文while文
for (初期化式;条件式;更新式)
  処理
while (条件式)
  処理
Cのfor文は次のような流れで繰り返され、いずれかの条件式の評価で偽の結果となった際に終了する。
  1. 初期化式
  2. 条件式
  3. 処理
  4. 更新式
  5. 条件式
  6. 処理
  7. 更新式
  8. 条件式
  9. ……

これに対してPythonのfor文は次のように記述する。

for ターゲットリスト in 式リスト :  
  処理1
[else:
 処理2]
while 条件式:
  処理1
[else:
  処理2]
ターゲットリストや式リストは次のように記述する。
>>> for x, y in [0,10], [5,20], [10,30]:
...     print(str(x) + "," + str(y))
... 
0,10
5,20
10,30
式リストは1度だけ評価される。例えば式リストに組み込み関数rangeを使用し、"range(1, 5)"と記述した場合、"[1, 2, 3, 4]"となり、各要素が順に代入される。

Pythonのfor文やwhile文にはelse節がある。もしループの条件式の評価結果が偽となった場合、ループが終了した後に実行される。break文で終了した場合、else節はスキップされる。


整数

Cの整数型の詳細(サイズや表現可能な範囲など)は、言語処理系に依存する傾向が強く、かつ符号の有無や精度などの組合せでさまざまな種類が存在する。これに対して、Pythonの整数型はシンプルで、メモリサイズの制限があるだけで無限の定義域を持つ。また、負の数は2の補数で表しており、符号ビットが左に無限に続くような値となる。

Pythonの整数リテラルは、次の通りである。

表記接頭辞
16進数0x, 0X
10進数
8進数0
2進数0b, 0B

Cでは10と8,16進数をサポートしていたが、Pythonでは更に2進数もサポートする。

文字列

Cには、文字列型という組み込み型は存在せず、文字型配列を用いて文字列を表現する。これに対してPythonでは、str型という組み込み型を使用する。str型に関する詳細は、help関数を用いれば知ることができる。

Pythonでは、全ての型の基となるobject型に__str__や__repr__という関数が定義されており、それを上書きすることでstr型への変換の振る舞いを設定できる。

Cの文字列リテラルは、引用符に二重引用符を用いて表す。これに対し、Pythonではさまざまな表現方法がある。Pythonで使用される文字列リテラルの引用符は次の通りである。

文字列引用符説明
'string'一重引用符
"string"二重引用符
'''string'''三連一重引用符エスケープなしで改行や引用符を書くことが可能。
"""string""" 三連二重引用符

データ構造

複数のデータをまとめて扱う方法として、Cでは派生型の配列型やポインタ型を使用する。これに対し、C以降に登場した多くの言語では、そのためのさまざまな型がある。Pythonの場合、以下の3系統のデータ構造がある。

名前説明リテラル
シーケンス型listミュータブルな可変サイズの配列[0, 1, 2]
tupleイミュータブルな可変サイズの配列(0, 1, 2)
str文字列"abcd"
集合型set集合{0, 1, 2}
frozenset
辞書型dictハッシュ{"apple":1, "banana":3}
ここで紹介する型は、組込み型の一例である。

これらのデータ構造にはさまざまな演算子や関数が用意されている。


その他

変数
Cの変数が特定の型を持ちそのオブジェクトだけを格納だけたのに対し、Pythonの変数はどんな変数でも代入できる。
定数
Cではマクロを使って定数のように扱う記述やconst指定子による定数がある。これに対し、Pythonには定数がない。ただし、一部のユーザは、定数の意図で使用する変数を命名規則で全て大文字にしている。
コメント
  • Cではコード中に記述するユーザのための文字列はコメントだけだったが、Pythonにはドキュメントを表すドキュメンテーション文字列とコメントがある。ドキュメンテーション文字列はユーザのために記述するが、コード的に意味を持つ。
  • Cでは/*から*/までのブロックコメントと、//から行末までの2種類のコメントがある。これに対し、Pythonでは#から行末までのコメントしかない。
if文
Cではif節とelse節しかなく、複数の条件を書く場合はelse節の中にif節を書いていたが、Pythonではelif節というものが存在する。

C++プログラマのためのPython

投稿日:
修正日:
タグ:

クラス定義

Pythonはクラス定義や継承、多重定義をサポートする。クラス定義の文法は、大雑把に説明すると次の通りである。

C++
class クラス名 {
  メンバの定義
};
Python
class クラス名:
  メンバの定義

なおPythonではインデントでブロックを表すため、空のクラスや関数を定義する場合、pass文を使用する。

class Hoge: pass
pass文とは何もしない。


メンバ関数

メンバ関数はクラスに属する関数である。メンバ関数の定義はC++の演算子の定義と似ている。C++は演算子の多重定義をメンバで行う際次のように行う。

class T
{
public:
  void operator+(int arg2){ printf("%d\n", arg2); }
};
これは一見すると1つの引数しか取らないが、2つの引数を受け取る2項演算子である。Pythonのメンバ関数の定義はこれとよく似ている。Pythonでは、メンバ関数を定義する場合、第一引数にオブジェクトを受け取る変数を明示的に記述しなければならない。そして呼び出しの際は第二引数以降が1つずつずれる。
class Cls:
  def setAdd(self, addee, adder):
    self.ans = addee + adder

c = Cls()
c.set(1, 3)
第一引数の変数名は言語的な制約はない。
>>> class Hoge:
...     def func1(hogefugapiyo):
...             hogefugapiyo.v = 20
...     def func2(hahaha):
...             print(hahaha.v)
しかしselfという名前を用いることが多いようである。

インスタンス変数にアクセスする場合、例のように第1引数を使用してアクセスする。


コンストラクタとデストラクタ

Pythonではコンストラクタとデストラクタは次のように定義する。

class Hoge:
  def __init__(self):  # コンストラクタ
    pass
  def __del__(self):   # デストラクタ
    pass
コンストラクタとデストラクタは共に省略可能である。

C++ではdelete文で、Pythonではdel文でオブジェクトの削除を行うが、その振る舞いは異なる。C++のdelete文は、指定したアドレスに格納されたオブジェクトを削除し、そのデストラクタを呼び出す。これに対し、Pythonのdel文は参照カウントを1減らし、参照カウントが0になった時に同様の処理が行われる。

class Hoge {
public:
        Hoge(){std::cout << "Hello\n";}
        ~Hoge(){std::cout << "Bye\n";}
        void func(){std::cout << "test\n";}
};

int main()
{
        Hoge *h = new Hoge();
        Hoge *i = h;
        delete h;  // デストラクタが呼び出される

        return 0;
}

class Hoge:
  def __init__(self): print("Hello")
  def __del__(self): print("Bye")
  def func(self): print("test")




h = Hoge()
i = h;
del h  
del i # デストラクタが呼び出される


Pythonでは、基底クラスのコンストラクタ(__init__)は自動で呼び出されない。

インスタンスアロケータ

Pythonには__init__とは別にインスタンスを生成する際に呼び出される関数がある。それが__new__である。__new__は静的メソッドで、新しいインスタンスを生成する際に自動的に呼び出される。__init__の第1引数がインスタンスであるのに対し、__new__にはクラスが与えられる。__new__()がclsのインスタンスを返さない限り、インスタンスの__init__は呼び出されない。なお__init__と__new__の第2引数以降は同じものが与えられる。

class Hoge:
  def __new__(cls):
    print("new Parent")
    return super().__new__(cls)
  def __init__(self):
    print("init Parent")
このクラスを利用した例は次の通りとなる。
>>> h = Hoge()
new Parent
init Parent
__new__は変更不能な型 (int, str, tuple など) のサブクラスでインスタンス生成をカスタマイズするために使用される。それゆえ、基本的に__new__をオーバーライドする必要はない。


クラス関数

C++ではクラス変数とクラス関数はそれぞれ次のようにstaticキーワードを使って表現する。この時、クラス関数の宣言と定義を分ける場合、定義ではstaticを記述しない。また、C++ではクラス変数はグローバル変数の一種であり、外部にstaticなしの定義を記述しなければならない。

#include 

class Hoge {
private:
	static int i;  // クラス変数
	static int get();  // (1) 宣言だけ記述し、定義は外で記述
public:
	static void set(int v) // (2) まとめて書く
	{
		i = v;
	}
};

int Hoge::i; // 必須
int Hoge::get()
{
	return i;
}

int main()
{
	Hoge v1, v2;
	v1.set(10);
	std::cout << v2.get() << std::endl;
	return 0;
}
これに対し、Pythonでは、特殊な関数やクラスの定義にはデコレータという機能を使用する。デコレータは定義するクラスや関数に機能の追加や変更を施す。クラス関数を定義する場合、関数デコレータのclassmethodを使用する。
class Hoge:
  @classmethod
  def set(cls, v):
    cls.__v = v
  @classmethod
  def get(self):
    return cls.__v
以下に実行例を示す。
>>> o1, o2 = Hoge(), Hoge()
>>> o1.set(1)
>>> o2.get()
1
なおデコレータの定義については本稿では言及しない。以前の記事の『Pythonの特徴』を参照されたし。


抽象クラス

編集中


多態化

C++で多態化を実装するには、virtualキーワードを使用して関数をオーバーライドにする宣言が必要だった。これに対してPythonのメンバ関数は、標準ではメンバ関数が全てC++のpublicとvirtualな関数である。それゆえ、継承クラスで定義した同名の関数は自動的にオーバーライドされる。


継承

Pythonでは継承は次のように記述する。

class クラス名[(基底クラス [, 基底クラス, ...])]:
以下に実際の例を示す。
class Parent:
  def __func(self):
    print("Hello, World")

class Child(Parent):
  def func(self):
    super().func()
PythonではC++と異なり、継承の際にアクセス指定を指定しない。また、基底クラスのコンストラクタ(__init__)は自動で呼び出されない。

静的な型チェックを行うC++では、コンパイル時に継承関係を考慮した型チェックが行われる。これに対し、Pythonではisinstanceという組み込み関数を使用して型チェックを行う。

>>> class Parent: pass
... 
>>> class Child(Parent): pass
... 
>>> p, c = Parent(), Child()
>>> isinstance(p, Parent)
True
>>> isinstance(c, Parent)
True

多重継承

PythonはC++と同様多重継承が可能な仕様である。文法は以下の通りである。

C++
class クラス名 : [アクセス指定子] 基底クラス名 [, ...] {
  メンバの定義
};
アクセス指定子と基底クラスが1つのセットで「,」で区切っていくつも記述できる。アクセス指定子は省略可能で、その場合はprivateである。
Python
class クラス名(基底クラス [, ...]):
  メンバの定義
しかしいくつかの振る舞いが異なる。例えば、継承の際C++にはアクセス指定子を指定してアクセス制御を行うが、Pythonにはそのような機能はない(publicな状態)。
コード出力結果説明
C++
class A{
public:
  A(){printf("I am A\n");}
};

class B : public A {
public:
  B(){printf("I am B\n");}
};

class C : public A{
public:
  C(){printf("I am C\n");}
};

class D : public B, public C{
public:
  D(){printf("I am D\n");}
};
I am A.
I am B.
I am A.
I am C.
I am D.
C++では標準で全ての基底クラスのコンストラクタが自動的に呼び出される。
C++(仮想基底クラス)
class A{
public:
  A(){printf("I am A\n");}
};

class B : virtual public A {
public:
  B(){printf("I am B\n");}
};

class C : virtual public A{
public:
  C(){printf("I am C\n");}
};

class D : public B, public C{
public:
  D(){printf("I am D\n");}
};
I am A.
I am B.
I am C.
I am D.
仮想基底クラスの場合、基底クラスの情報は共有され、同じクラスのコンストラクタは1度しか呼び出されない。
Python(オーバーライド)
class A:
  def __init__(self):
    print("I am A.")

class B(A):
  def __init__(self):
    print("I am B.")

class C(A):
  def __init__(self):
    print("I am C.")

class D(B, C):
  def __init__(self):
    print("I am D.")
I am D.
Pythonでは、__init__をオーバーライドした場合、明示的に呼び出さない限り、基底クラスのコンストラクタは呼び出されない。
Python(非オーバーライド)
class A:
  def __init__(self):
    print("I am A.")

class B(A):
  def __init__(self):
    super().__init__()
    print("I am B.")

class C(A):
  def __init__(self):
    super().__init__()
    print("I am C.")

class D(B, C): pass
I am A.
I am C.
I am B.
Python
class A:
  def __init__(self):
    print("I am A.")

class B(A):
  def __init__(self):
    super().__init__()
    print("I am B.")

class C(A):
  def __init__(self):
    super().__init__()
    print("I am C.")

class D(B, C):
  def __init__(self):
    super().__init__()
    print("I am D.")
I am A.
I am C.
I am B.
I am D.


カプセル化

C++やJava、C#などの多くの言語では、文法は違えどpublic、private、protectedというキーワードでメンバのアクセス制御を行う。

class Hoge:
  v1 = 10            # クラス変数
  _v2 = 100          # プライベートで使用する意図のクラス変数
  __v3 = 1000        # プライベートクラス変数
  def func1(self):   # メンバ関数
    print(self.v4)   # インスタンス(オブジェクト)変数
    print(self.__v5) # プライベートインスタンス変数
  def __func2(self): # プライベートメンバ関数
    pass
  @classmethod
  def func3(cls):    # クラス関数
    print(cls.v1)    # クラス変数
C++ではメンバ関数の標準のアクセス状態は"private"であるが、Pythonでは"virtual public"である。

Pythonでメンバをプライベートとする場合、以下のように接頭辞が__から始まる名前にする。

class Hoge:
  def __func(self):
    print("Hello")
このプライベートメンバにアクセスしようとすると次のようにAttributeErrorが送出される。
>>> Hoge().__func()
AttributeError: Hoge instance has no attribute '__func'

Pythonでは、プライベートメンバの名前は、外部から参照できなくなっている訳ではなく、自動的に名前を変更される。これにより継承クラスで名前の競合を防いでいる。なおプライベートメンバの変更後の名前は、プライベートメンバの名前の接頭に「_クラス名」を追加したものである。前述のサンプルコードのHogeの名前空間を閲覧した結果を以下に示す。

>>> dir(Hoge)
['_Hoge__func', '__class__', '__delattr__', '__dict__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', '__weakref__']
このように名前が変更されただけであるため、実はこのようにアクセスすることが可能である。
>>> h = Hoge()
>>> h._Hoge__func()
Hello

多様性 検索順

  1. D
  2. B
  3. C
  4. A
class A:
  def func(self):
    print("I am A\n")

class B(A):
  def func(self):
    print("I am B\n")

class C(A):
  def func(self):
    print("I am C\n")

class D(B, C): pass


変数

C++の変数は、スコープやライフタイム、ストレージクラス、アクセス制御、修飾子などの組合せによって非常にさまざまなものがある。Pythonの変数はC++程の種類はないが、それでもいくつかの種類がある。以下にC++の定義と比較した場合のPythonの変数定義を紹介する。

種類C++Python
グローバル変数(プログラム内で共有される変数)
int v = 1;
class Cls {
  void func()
  {
  }
};
なし。
グローバル変数(ファイルスコープの変数)
static int v = 1;
class Cls {
  void func()
  {
  }
};
v = 1
class Cls:
  def func():
    pass
ローカル変数
class Cls {
  void func()
  {
    int v = 1;
  }
};
class Cls:
  def func():
    v = 1
静的ローカル変数
class Cls {
  void func()
  {
    static int v = 1; 
  }
};
なし。
インスタンス(オブジェクト)変数
class Cls {
private:
  int v = 1;
  void func()
  {
  }
};
class Cls:
  v = 1
  def func(self):
    self.w = 1
クラス変数
class Cls {
public:
  static int v;
};
int Cls::v = 1;
class Fuga:
  @classmethod
  def func(cls):
    cls.w = 1
名前空間
namespace nspace {
  int v = 1;
};
class Cls {
  void func()
  {
  }
}
fileA.py
x = 10
fileB.py
import fileA
fileA.x
定数
const int VAL = 1;
class Cls {
  void func()
  {
  }
};
言語仕様としてはないが、定数の意図で使用する場合に名前を大文字にするマナーがある。
公開メンバ変数
class Cls {
public:
  int v = 1;
  void func()
  {
  }
}
class Cls:
  def func(self):
    self.v = 1
非公開メンバ変数
class Cls {
private:
  int v = 1;
  void func()
  {
  }
}
class Cls:
  def func(self):
    self.__v = 1
限定公開メンバ変数
class Cls {
protected:
  int v = 1;
  void func()
  {
  }
}
なし。


型変換

編集中


特殊関数

編集中


例外

Pythonではtry文を次のように記述する。

try:
  // 例外が発生しうる処理
except Exception:
  // 例外取得と処理
else:
  // try節が末尾までいった場合の処理
finally:
  // 最後に必ず行われる処理
Pythonではcatch節の代わりにexcept節がある。except節は送出された例外オブジェクトをasで指定した名前に束縛することができる。except節には、BaseExceptionのサブクラスを指定できる。しかし通常独自の例外を定義する場合、ExceptionというBaseExceptionのサブクラスを継承する。

また、tryとexcept節以外にもelse節とfinally節がある。else節を記述した場合、制御がtry節の末尾までいった場合に実行される。これに対し、finally節を記述した場合、どの節を処理したかに関わらず必ず最後に呼び出される。except節とelse節、finally節は省略可能であり、except節は複数記述でいる。ただし、except節とfinally節の両方を省略することはできない。

Pythonの覚えておきたい関数やクラス、モジュール

投稿日:
タグ:

本稿はPython3の言語仕様とは別に覚えておきたい関数やモジュールについてのメモ。

組み込み関数

map(func, iterable, ...)
第二引数以降で指定したコンテナから同じ添字番号のものを順に抜き出し、それをfuncに引数として与え、その結果を返すジェネレータ。funcに与える引数は、mapの第2引数のコンテナに属するオブジェクトがfuncの第1引数に、mapの第3引数のコンテナに属するオブジェクトがfuncの第2引数といった感じで、mapの第n引数のコンテナに属するオブジェクトがfuncの第n-1引数に与えられる。
def func(x, y, z):
  return x * y * z

print(list(map(func, [1, 2, 3], [2, 4, 6], [3, 6, 9])))
mapはPython2ではジェネレータではなく、コンテナを返す関数である。
filter(func, iterable)
iterableが返すオブジェクト群を順にfuncに引数として与えて評価し、真となるオブジェクトを返すジェネレータ。これを利用すると例えば次のように10から50の範囲の素数を検索するコードを記述することができる。
def isPrime(x):
  for y in range(2, x-1):
    if x%y==0:
      return False
  return True

print(list(filter(isPrime, range(10, 50))))
このコードはこのような結果を標準出力に出力する。
[11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
filterもまたPython2ではジェネレータではなく、コンテナを返す関数である。
zip(*iterable)
行列の行と列を交換するような関数。複数のコンテナを受け取り、同じ添字を1つのタプルを順に返すジェネレータ。 例えばこのようなコードがあったとする。
print(list(zip([1,2,3], [4,5,6])))
これは次のように標準出力に出力される。
[(1, 4), (2, 5), (3, 6)]
isinstance(object, class-or-type-or-tuple)
指定したオブジェクトが指定したクラスかその継承クラスである場合にTrueを、それ以外の場合にFalseを返す。また、クラスはタプルの中に記述することで複数指定できる。
isinstance(False, bool)
isinstance(False, (int, str))
id(object)
オブジェクトの識別値(ID)を返す。
算術
abs(number)
絶対値を返す関数

モジュール

以下にいくつか便利なモジュールの使い方を説明する。詳細は情報はhelpコマンドによるドキュメントを参照されたし。

re
正規表現を扱うためのモジュール。
一致
import re
r = re.match("h.*o", "hello")
if r is None:
  print("Not match")
else:
  print("match")
抽出
>>> import re
>>> r = re.match("^\s*(.*?)\s*,\s*(.*?)\s*,\s*(.*?)\s*$", "apple, 100, 5")
>>> if r is not None:
...   r.group(0)
...   r.group(1)
...   r.group(2)
...   r.group(3)
... 
'apple, 100, 5'
'apple'
'100'
'5'
置き換え
>>> re.sub("([^ ,]+)", "hoge", "foo, bar")
'hoge, hoge'
sys
システム系のモジュール。
コマンドライン引数の取得
import sys
print("program name: " + sys.argv[0])
print(" argument 1 : " + sys.argv[1])
print(" argument 2 : " + sys.argv[2])
標準出力
標準エラー出力
import sys
sys.stderr.write("error message\n")
これを利用すると次のようにリダイレクトができる。
import sys
out = sys.stdout
f = open("/tmp/test.txt", "w")
sys.stdout = f
cnt = sys.stdout.write("fuga\n")
print("hoge")
f.close()
exit
import sys
sys.exit(0)
os
システムコールのモジュール。
ディレクトリの生成
import os
os.mkdir("/tmp/hoge", 755)
exec系関数
dup
pipe
fork
import sys
import os

r, w = os.pipe()
pid = os.fork()
if pid:
  os.close(w)
  out = os.read(r, 10)
  while True:
    buf = os.read(r, 10)
    if buf:
      out += buf
    else:
      break
  os.write(sys.stdout.fileno(), out)
  os.close(r)
else:
  os.close(r)
  os.dup2(w, sys.stdout.fileno())
  os.close(w)
  os.execlp("ls", "ls", "-l")


特殊関数

編集中

Python2と3

投稿日:
タグ:

本稿はPython3と2の差異に関するメモ。

編集中

apply
basestring
buffer
callable
dict
except
exec
print
Python2ではexecやprintは文だったが、Python3では関数である。それゆえ、printの文法が異なる。
execfile
exitfunc
filter
map
zip
filterやmap、zipはPython2ではコンテナを返す関数だが、Python3ではジェネレータである。
2
>>> zip([1,2,3], [4,5,6])
[(1, 4), (2, 5), (3, 6)]
3
>>> zip([1,2,3], [4,5,6])
<zip object at 0xb731964c>
funcattrs
future
getcwdu
has_key
idioms
import
imports
imports2
input
intern
isinstance
itertools_imports
itertools
long
metaclass
methodattrs
ne
next
nonlocal文
Python3ではnonlocal文という文が追加された。
nonzero
numliterals
paren
raise
raw_input
reduce
renames
repr
set_literal
standard_error
sys_exc
throw
tuple_params
types
unicode
urllib
ws_comma
xrange
xreadlines

除算
除算(division)または切り捨て除算(floor division)演算は、はじめに型変換によって2つの項の型を統一する。そしてPython2では、除算演算や切り捨て除算演算に関わらず、項が2つとも整数型または長整数型であれば、整数型や長整数型の除算結果を返す。しかしPython3では、除算演算の場合は浮動小数点型を返し、切り捨て除算の場合は2つの項が整数型か長整数型であれば、整数型を返す。

一覧