2015/04/10

Python言語の基本文法や型などに関する個人的まとめ

これはPythonの公式チュートリアル(慣れていない人を対象にした説明文書)などを参考に、個人的に一部をまとめたものとなる。

元の記事は2008年4月に書かれたが、Python 3関係も含めて内容を大幅に修正し、2つに分かれていた記事を統合した上で幾つかの内容を書き加えた。

当時Pythonに不慣れな自分用の覚え書きという位置付けで書いたもののため、高度な内容は含まれない。また、基本的なことといっても広いので、内容が偏っている可能性もある。

  1. Python言語について
  2. 基本的な文法・データ型など
  3. 文字列
    1. 文字列定数と改行
    2. 文字列どうしの連結
    3. 文字列のフォーマット操作
    4. 文字列型のメンバ関数
    5. シーケンス型としての操作
  4. del文とその使用例
  5. 条件分岐(if文)とその使用例
  6. 辞書の使用例
  7. タプル/例外/関数の使用例

Python言語について

  • 言語の種類としては “インタプリタ言語” に分類され、書いたコードは基本的にコンパイルせずに実行される[1]
  • 基本的に、Python言語のコードの動作はOSに依存しないが、コードの中で使用する機能(関数やクラス)によっては対応OSが限られるものがある[2]
  • 名前の由来は “Monty Python's Flying Circus (空飛ぶモンティ・パイソン)” だが、言語を示すアイコンとしては蛇の描かれたものが用いられる
  • 色々な機能の集まりである “標準ライブラリ” を用いることで追加の様々な機能が利用でき、更に、色々な言語バインディングなどの拡張のパッケージをインストールすることで、できることが増えていく
    • ライブラリや拡張の機能は対象の機能を含んだモジュールをimport文で指定して用いる
  • バージョン3(Python 3)では言語仕様が一部変わり、Python 2との(後方)互換性はない[3]

Pythonプログラムを動かすためのソフトウェア(Pythonの実装)については

を参照。

基本的な文法・データ型など

  • 文法
    • 行中に “#” があると、その後ろの行末までがコメントとして扱われ、動作上無視される[4]
    • 行末にセミコロン(“;”)は必要ない
    • 制御文や関数定義などでは、波括弧(“{” と “}”)を使用せずに字下げ(インデント)で構造を表現する
    • 文法上何か書かなくてはならないが何もすることのないところではpass文を記述
  • 標準出力への文字列出力はPython 2ではprint文・Python 3ではprint()関数を用いる
    • Python 2でもバージョン2.6系以上であれば “from __future__ import print_function[5]をスクリプトのはじめ(“#!” や “coding” の行よりは後)に記述することによりprint()関数も利用可
  • 変数
    • 変数名の先頭には “$” などの記号は付かない
    • 変数は宣言しなくても(代入して)使うことができる
  • 関数定義は “def [関数名]([仮引数...]):[6]で開始して、次の行から字下げして内容を書き、終わりを表す記述はしないで、字下げの段階を下げる(戻す)
  • データ型
    • データの型(タイプ)はその内容によって自動的に決められるが、int()などの関数による強制的な変換もできる
    • タプル(tuple)というデータ型はコンマで区切られたデータ組を丸括弧(“(” と “)”)で囲んだもので、入れ子にもできるが、それぞれの要素は直接変更できない
    • “異なる種類のデータをにする” という用途のタプル型に対し、角括弧(“[” と “]”)で囲んだ形のリスト型は “順番を持った一覧” としての用途で用いる
    • 辞書型は他の言語での連想配列(連想記憶)に相当し、 “キー” の文字列を指定して、対応した “値” を出し入れするもの
    • 真偽値の型は “True(真)” “False(偽)” のいずれかの値をとる(先頭は大文字)
    • オブジェクトの型[7]は “[オブジェクト].[メンバ関数名](引数...)” の形でそのデータに対する操作を行うことができる
    • 型はisinstance()で判別できる[8]
  • 環境変数は “import os” を一度実行した後 “os.environ['[環境変数名]']” で読み書きできる

文字列

  • シングルクォートかダブルクォートで囲んだ文字列は固定文字列(文字列定数・文字列リテラル)となる
  • “u'test'” のように、先頭に “u” を付けたものはUnicode文字列となり、Python 2で日本語を表示するには “u'日本語'.encode('utf-8')” のように変換したいエンコーディング名を記述する(スクリプトでは “#!” の次の行あたりに “# -*- coding: utf-8 -*-” のようにスクリプトで使用されているエンコーディング名を書いておく)
    • Python 3の文字列型は内部でUnicode文字列として扱われており、先頭に “u” を付けても、付けないのと同じ動作になる[9]
  • 変数に入れた文字列はそれ自体を直接変更することはできないため、何文字目かを別の文字に置き換えるといった操作はできないが、一部を変更した新しい文字列を作ることで実現できる
  • 同じ文字列を繰り返したものが “[文字列] * [反復数]” で得られる(“'abc' * 2” は “abcabc”)
  • 文字列の検索処理は、簡単なパターンの場合はfind()などのメンバ関数や “[検索したい文字列] in [対象文字列]” の戻り値を使用し、正規表現による高度なパターン指定は “re” モジュールを用いる

文字列定数と改行

  • 他の言語のように、文字列中の “\n” が改行を表す
  • 文字列定数の中で改行すると文法エラーになるため、複数行にわたって文字列を記述する場合、改行の直前に “\” を付ける(格納された文字列内では改行されない)か、途中の改行が改行文字として処理される三重(さんじゅう)のシングルクォートかダブルクォートで囲む

文字列どうしの連結

  • “+” の演算子で文字列どうしが連結できる(“[文字列1] + [文字列2] + ...”)
  • 内容を末尾へ追加するのに “[文字列] += [追加文字列]” と書くこともできる
  • 数値の定数や、数値の入った変数とこの方法で連結しようとすると “TypeError: Can't convert 'int' object to str implicitly” (Python 3) や “TypeError: cannot concatenate 'str' and 'int' objects” (Python 2) のようにして例外が発生し、うまくいかない

文字列のフォーマット操作

  • 他の言語のprintf()系関数のように、フォーマット変換をして文字列にすることができる
  • フォーマット操作を用いると、文字列と数値を文字列として連結することもできる
  • Python 3とバージョン2.6系以上のPython 2ではフォーマット文字列のメンバ関数format()を用いる: format()の細かい指定について
  • Python 2では[フォーマット文字列] % ([値1], [値2], ...)” を用いる: 細かい指定について
文字列連結とフォーマット操作のテスト例
#! /usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

str1 = 'foo'
str2 = 'bar'
num = 9999

print (str1 + str2)

# 例外発生
#  Python 2: TypeError: cannot concatenate 'str' and 'int' objects
#  Python 3: TypeError: Can't convert 'int' object to str implicitly
#print (str1 + str2 + num)

# これはOK
print ('{0}{1}{2}'.format (str1, str2, num))
実行結果
foobar
foobar9999

逆に、数値が文字列型に格納されていて[10]、数値として扱いたい場合はint()などにより型変換を行う。内容によっては例外が出るので対処が必要。

文字列型のメンバ関数

  • [文字列].[メンバ関数名]([引数...])” で、その文字列に対して様々な操作が行える
  • 一覧はリファレンスの “文字列メソッド” にある

シーケンス型としての操作

文字列に対して以下のような操作(一部内容の取り出しや色々な情報の取得)が行える。どのような操作になるかは実行結果を参照。

シーケンス型としての操作のテスト例
#! /usr/bin/python

from __future__ import print_function

str = 'abcdefghij'
print ('''str[0]: {0}
str[1:3]: {1}
str[3:]: {2}
str[:5]: {3}
str[0:9:2]: {4}
str[-3]: {5}
str[-3:]: {6}
str[:-4]: {7}
len(str): {8}
min(str): {9}
max(str): {10}
"efg" in str: {11}
"efg" not in str: {12}'''.format (str[0], str[1:3], str[3:], str[:5], str[0:9:2],
                                  str[-3], str[-3:], str[:-4],
                                  len(str), min(str), max(str),
                                  'efg' in str, 'efg' not in str))
実行結果
str[0]: a
str[1:3]: bc
str[3:]: defghij
str[:5]: abcde
str[0:9:2]: acegi
str[-3]: h
str[-3:]: hij
str[:-4]: abcdef
len(str): 10
min(str): a
max(str): j
"efg" in str: True
"efg" not in str: False

文字列以外でもシーケンス型に属する型に対しては同様の操作が行える。

del文とその使用例

del文を用いると、一度内容を入れた変数を未定義状態にできる。

del文の使用例
#! /usr/bin/python

from __future__ import print_function

a = 1
print (a)  # 1
del a
print (a)  # NameError: name 'a' is not defined
実行結果
1
Traceback (most recent call last):
  File "[スクリプトの場所]", line 8, in 
    print (a)  # NameError: name 'a' is not defined
NameError: name 'a' is not defined

条件分岐(if文)とその使用例

  • if/elif/elseというキーワードはシェルスクリプトに近いが、行末に “:” を付ける点に注意
  • 条件の “AND(かつ)” / “OR(もしくは)” はそれぞれ “and” と “or” と記述
  • if a < b == c:は、 "a < b” かつ “b == c”
  • 複数の条件で分岐する場合、ひとまとめにしたい条件を丸括弧で囲むことで優先順位と読みやすさを上げることができる
if文の使用例
#! /usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

a = b = 1

if a == b:  # 最後にコロンを付ける(セミコロンではない)
  print ('a == b')
if not a != b:  # 否定は「if not」(この例は「等しくない」の否定で「等しい」)
  print ('not a != b')
if a == 0 or b == 0:  # 偽
  print ('a == 0 or b == 0')
if a == 0 or b == 1:  # 真
  print ('a == 0 or b == 1')
if a == 0 and b == 1:  # 偽
  print ('a == 0 and b == 1')
if a == 1 and b == 1:  # 真
  print ('a == 1 and b == 1')

if a == 0:
  pass
elif a == 1:  # シェルスクリプト同様「if - elif - elif - ... - else」
  print ('a == 1')

if b == 0:
  pass
elif b == 2:
  pass
else:  # elseの後ろにもコロンは忘れずに
  print ('else')

if a == b < 2:  # aとbが等しく、その値が2未満
  print ('a == b < 2')
実行結果
a == b
not a != b
a == 0 or b == 1
a == 1 and b == 1
a == 1
else
a == b < 2

辞書の使用例

  • 辞書型のメンバ関数items()をfor文で使用すると、それぞれのキー/値に対して処理が行える
  • このfor文の書式はシェルスクリプトのものに近い
  • iteritems()はPython 3では使えない
辞書の使用例
#! /usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

dic = { 'pen'     : 'ペン',
        'pencil'  : '鉛筆',
      }

# 個別に直接取り出す
print ('pen -> {0}\npencil -> {1}'.format (dic['pen'], dic['pencil']))

# それぞれのキー/値を全て処理して取り出す
for en, ja in dic.items ():
  print ('{0} <- {1}'.format (ja, en))
実行結果
pen -> ペン
pencil -> 鉛筆
鉛筆 <- pencil
ペン <- pen

ループのテクニックとして、他の高度な扱い方もチュートリアルの “ループのテクニック” で紹介されている。

タプル/例外/関数の使用例

関数の戻り値に複数の値を含める場合の例。このコードは関数や例外処理の使用例も兼ねる。

タプル/例外/関数の使用例
#! /usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function

def devide (a, b):
  """
  aをbで割り、0で割ったときにステータス部分にFalseが返る
  """
  try:
    value = float (a) / float (b)
    status = True
  except ZeroDivisionError:  # 0で割ったときに出る例外
    value = None
    status = False
  return (status, value)  # 戻り値部分がタプル型

ret = devide (7, 2)  # retはタプル型で、ret[0], ret[1]のように要素を取り出す
if ret[0]:  # 除算成功(ステータスがTrue)
  print ('devide(7, 2): OK({0})'.format (ret[1]))  # 計算結果
else:
  print ('devide(7, 2): FAILED')

(stat, val) = devide (1, 0)  # 戻り値を分けて代入することもできる
if stat:
  print ('devide(1, 0): OK({0})'.format (val))
else:  # 除算失敗
  print ('devide(1, 0): FAILED')
実行結果
devide(7, 2): OK(3.5)
devide(1, 0): FAILED
使用したバージョン:
  • Python 2.7.8, 3.4.2
[1]: 実行前に実行形式への変換をする必要がなく、内部で解析などの処理が行われて実行される
[2]: そのようなものはリファレンスに対応OSが記述されていたり、動作しない環境が存在することが書かれている
[3]: Python 2向けに書いたプログラムはそのままではPython 3で動かないことがある
[4]: シングル/ダブルクォートで囲まれた文字列にこの記号が含まれる場合は除く
[5]: この記述のあるスクリプトをPython 3で実行しても正常に動作する
[6]: 仮引数は “[仮引数] = [既定値]” 形式で記述することで既定値の指定もできる
[7]: 実際には数値や文字列など基本的な型は全てオブジェクトとなっている
[8]: “isinstance('abc', int)” は “False” を返し、 “isinstance('abc', str)” は “True” を返す
[9]: 条件 “u'日本語' == '日本語'” が “True” となる
[10]: 内部的に数値としての意味がなく、文字の羅列として存在している状態