情報学部 菅沼ホーム Python と C/C++ 目次

Python 概説

      1. Python の実行と基本構造
        1. Python の実行
          1. 対話モード
          2. ファイルの利用
        2. プログラム構造
          1. 行構造
          2. コメント
      2. 文法の基本
        1. データ型
          1. リテラル
            1. 文字列およびバイト列リテラル
            2. 数値リテラル
          2. 変数
          3. 識別子(名前)
        2. 演算子と式
          1. 代入文等
            1. 代入文
            2. import 文
          2. 数値演算
          3. 比較と論理演算
          4. ビット単位の演算
        3. 制御文
          1. 分岐
          2. 繰り返し
        4. 配列
          1. 1 次元配列
          2. 多次元配列
          3. 連想配列
        5. 関数
          1. 関数とその性質
            1. 定義とデフォルト引数
            2. 様々な引数
            3. 引数と関数名
            4. ローカル変数とグローバル変数
          2. ジェネレータ関数
        6. クラス
          1. クラスの定義
          2. 初期化
          3. 継承
          4. インスタントメソッド,クラスメソッド,スタティックメソッド
        7. 入出力
          1. 標準入出力
          2. ファイル入出力
        8. 変数の有効範囲(スコープ)
Ⅰ.Python の実行と基本構造
  1. Python の実行

    1. 対話モード

        最初に,対話モードで実行する方法について説明します.Window のコマンドプロンプトを起動し,
      > Python				
      と入力すると,Python のインタプリータが起動し,「 >>> 」というコマンドプロンプトが表示されるはずです(もちろん,この前に,Python をインストールし,適切な箇所に PATH を設定しておく必要があります).ただし,Python 3.3 とそれ以降のシステムワイドなインストールでは,ランチャが PATH に追加され,2 種類の Pythonがインストールされていても,
      > py -2  # Python 2.* の実行
      > py -3  # Python 3.* の実行				
      のいずれかを入力すれば,希望する Python インタプリータを起動することができます.以後の例においても同様ですが,上の例における # から行末まではコメントです.なお,インタプリータを終了させるには,ctrl-Z,または,quit() を入力します.

        以下の例に示すように,プロンプト「 >>> 」が表示されている状態で,式や関数を入力すれば,その結果が出力されます.なお,以後の例においても同様ですが,行番号は,説明のために付加してあります.

      01	>>> print(2 + 3)
      02	5
      03	>>> 3 + 4
      04	7
      05	>>> 10 + _
      06	17
      07	>>> a = 10
      08	>>> if a == 10:
      09	...     print(a)
      10	...
      11	10
      12	>>> 'abc'
      13	'abc'
      				

    2. ファイルの利用

        複雑な処理を行いたい場合,対話モードを利用して一連のコマンドを順に入力していくことは大変な作業になります.そこで,一連のコマンド(スクリプト)をファイル,例えば cal1.py (一般的に,ファイル名は「~.py」)に,
      # -*- coding: UTF-8 -*-
      a = 10
      b = 20
      print(a + b)				
      のような形で保存し,Window のコマンドプロンプト上において,
      py -3 cal1.py   # 一般形: python ファイル名 [arg] ... 				
      と入力することによって,結果を得ることができます.なお,ファイル内容の 1 行目は,文字コードを表しています.

        モジュールも,上に示したファイルと同様,Python の定義や文が入ったファイルです.大きなプログラムの一部や,他のプログラムにおいても使用可能な汎用的な処理部分を記述するために使用されます.例えば,以下に示すモジュール cal2.py は,加算または減算を実行し出力するためのものです.なお,def で始まる部分は,関数を表しています.
      # -*- coding: UTF-8 -*-
      
      def add(a, b):
      	c = a + b
      	print(c)
      
      def sub(a, b):
      	c = a - b
      	print(c)				
      このモジュールを使用することによって,例えば,以下に示すような処理を実行できます.
      >>> import cal2
      >>> cal2.add(2,3)
      5
      >>> cal2.sub(2,3)
      -1				
        「cal2.add(2,3)」の「cal2.」の部分を記述したくない場合は,上の 1 行目の代わりに,
      >>> from cal2 import add				
      を入力してやれば,「add(2,3)」の記述で正しく動作します.また,
      >>> from cal2 import *				
      という記述を利用すれば,モジュールで定義されている全ての名前(関数内で定義されているローカルな変数名は除く)を import できます.この例の場合は,関数 sub に対しても,「sub(2,3)」の記述で正しく動作するようになります.
  2. プログラム構造

    1. 行構造

        C/C++ のプログラムは,自然言語と同様,一つの文の開始や終了位置に特別な制限がなく,フリーフォーマットで記述できますが,Python のプログラムは行単位(行頭から改行まで)で処理されます.ただし,一つの文を 1 行で記述できない場合は,以下に示すように,バックスラッシュ文字「 \ 」を使って継続させることが可能です.また,\ で継続する行(下に示す文の 1,2 行目)の後ろには「 # 」記号を使用してコメントを記述することができません.
      a = abc + efg * xxx \
          + aaa - bbb / ccc \
          + yyy / 30 + hhh   # ~ に関する計算				
        C/C++ と同様,if 文while 文など,実行順序を制御するための文が Python にも存在します.しかし,その記述方法は C/C++ とはかなり異なっています.詳細については後ほど述べますが,ここでは,行単位の入力方法について説明します.例えば,if 文の場合,C/C++ では以下に示すように記述されます.
      01	if (条件) {
      02		a = 10;
      03		b = 20;
      04	}
      05	else {
      06		c = 30;
      07		d = 40;
      08	}				
        この文は,条件が真であれば 02,03 行目を実行し,偽であれば 06,07 行目を実行することを意味しています.プログラムの読みやすさのため,上の例に示すように,02,03,06,07 行目は,01,04,05,08 行目に対して,半角スペースまたは Tab を使用して字下げを行うべきですが,波括弧 { や } が正しく設定されていれば,字下げを行わなくても正しく動作します.また,条件が真または偽に対する処理が 1 文だけで記述できる場合,例えば,条件が真である場合は 02 行目だけとなる場合は,01 行目や 04 行目の波括弧も必要ありません.さらに,読みやすさの点を無視すれば,各行を複数行にわたって記述したり,すべてを同じ行に記述することも可能です.

        しかし,Python の場合は,条件が真や偽になる場合の処理が複数行となる場合であっても,波括弧を使用しません.以下に示すように,半角スペースまたは Tab を使用して字下げを行うことによって,その制御範囲を記述することになります.この点は,while 文等に対しても同様です.つまり,Python においては,制御構造を正しく理解し,適切な字下げを行わないと,目的とする結果が得られません.場合によっては,コンパイルさえ行ってくれません.適切な字下げが行われていない C/C++ などで記述された汚いプログラムを見ると,他の言語に対しても,Python の考え方を導入して欲しいと思います.ただし,プログラムが長くなると,波括弧があった方が見やすく感じます.インデントの強制的な使用は重要ですが,見やすさの点からいって,波括弧を付けさせた方が良いのではないでしょうか.
      01	if 条件 :
      02		a = 10
      03		b = 20
      04	else :
      05		c = 30
      06		d = 40				

    2. コメント

        以下に示すように, # から改行まではコメントとみなされます.
      a = 10   # 変数 a に 10 を代入 				
        また,以下に示すように,Python スクリプト中の 1 行目か 2 行目にあるコメントが正規表現 coding[=:]\s*([-\w.]+) にマッチする場合,コメントはエンコード宣言(プログラムを記述する文字コードの宣言)として処理されます.
      # -*- coding: UTF-8 -*-				
        Python には,C/C++ における /* と */ のように,複数行にわたるコメントを記述する記号は存在しません.しかし,Python では,代入などの演算を行わず,単に文字列だけを記述した場合,その文字列に対する処理は行われません.そこで,3 連引用符(引用符を 3 つ続ける) ''',または, """ を使用した複数行に亘る文字列を利用することにより,以下に示すように,複数行にわたるコメント(的な文字列)を記述することが可能です.
      """
         コメント・・・
         コメント・・・
      """				
Ⅱ.文法の基本
  1. データ型

    1. リテラル

      1. 文字列およびバイト列リテラル

          文字列リテラルおよびバイト列リテラルbytes 型リテラル)は,対応する一重引用符「 ' 」,または,二重引用符「 " 」で囲まれます.Python においては,二つの引用符は同じ意味になります.また,バイト列リテラルに対しては,常に b や B が接頭します.
        >>> "文字列"
        '文字列'
        >>> '文字列'
        '文字列'
        >>> b"abc"
        b'abc'
        >>> b"文字列"   # エラー( ASCII 文字だけ可能)					
          文字列は,+ 演算子を使用して連結させることができ,* 演算子で反復(このような機能,必要?)させることができます.また,文字列リテラルをスペースで区切って並べると,それらは自動的に連結されます.
        >>> 2 * "abc" + "efg" + "hij"
        'abcabcefghij'
        >>> 2 * "abc" "efg" "hij"
        'abcefghijabcefghij'					
          複数行に亘る文字列は,対応する 3 連の引用符 ''',または,""" によって可能です.
        >>> """
        ... abc
        ... def
        ... ghi
        ... """
        '\nabc\ndef\nghi\n'					

      2. 数値リテラル

          数値リテラルには 3 種類あります.整数( integer )浮動小数点数( floating point number ),及び,虚数( imaginary number )です.複素数リテラルは存在しませんが,複素数は実数と虚数の和として作れます.また,数値リテラルには符号が含まれていないことに注意してください.-10 のような数値は,実際には単項演算子 (unary operator) - とリテラル 10 を組み合わせたものとして処理されます.

          整数リテラルは,10 進数,8 進数 0ohhhh,16 進数 0xhhhh,または,2 進数 0bhhhh を使用して表現できます( o,x,b は大文字でも良い).なお,値がメモリ上に収まるかどうかという問題を除けば,整数リテラルには長さの制限がありません.
        >>> 15
        15
        >>> 0xf
        15
        >>> 0o17
        15
        >>> 0b1111
        15					
          真偽値も整数リテラルの一種であり,FalseTrue の値をとります.真偽値を表すブール型は整数型の派生型であり,ほとんどの状況でそれぞれ 0 と 1 のように振る舞います.
        >>> True
        True
        >>> False
        False
        >>> 10 + True
        11
        >>> 10 + False
        10					
          浮動小数点数リテラルの取りうる値の範囲は実装に依存します.なお,数値はすべて 10 進数であり,仮数部と指数部を使用して表現する場合,その基数は常に 10 となります.
        >>> 12345.01
        12345.01
        >>> 1234501e-2
        12345.01					
          虚数リテラルは,aj ( aJ )のように表現し,実数部が 0.0 の複素数を表します.実数部がゼロでない複素数を生成するには,( 3 + 4j ) のように虚数リテラルに浮動小数点数を加算するか,または,組み込み関数 complex() を使用します.
        >>> 3.14j   # 3.14J でも良い
        3.14j
        >>> 2.5 + 3.14j
        (2.5+3.14j)
        >>> complex(2.5, 3.14)
        (2.5+3.14j)
        >>> complex(2.5, 3.14).real   # 実数部の参照(参照だけ可能)
        2.5
        >>> complex(2.5, 3.14).imag   # 虚数部の参照(参照だけ可能)
        3.14					

    2. 変数

        Python においては,代入または入力したデータによって,その変数の型が決まります.ただし,Python の場合は,変数が示す場所(アドレス)にデータ自身が記憶されているわけではなく,変数はデータ(オブジェクト)が記憶されている場所への参照(場所のアドレス)を表しています.従って,C/C++ のように,変数の型という表現は不適切ですが,今後,混乱が生じない範囲で使用していきます.例えば,下の例において,a は整数リテラル 10 への参照(整数型の変数),また,c は複素数リテラルへの参照(複素数型の変数)を表す変数となります.このように,Python における変数は,a は整数リテラル 10 のアドレス,また,c は複素数リテラル 1 + 2j のアドレスを表しているように見えますので,C/C++ におけるポインタと似ています.また,3 行目のように,変数 a に,先に代入した値と異なる型(文字列)の値を記憶することも可能であり,この時点で,変数 a は文字列型の変数となります.
      >>> a = 10
      >>> c = complex(1, 2)
      >>> a = "abc"				

    3. 識別子(名前)

        識別子とは,変数,関数,クラス等の名前に相当します.ASCII 範囲では,C/C++ と同様,アルファベット,下線 _,及び,数字(先頭の文字を除く)を利用できます.ただし,下線 _ から始まる識別子には,以下に示すように,特別な意味がある場合があります( * の部分は,任意の文字列).

      • _*  from module import * で import されません.また,対話インタプリタでは,直前に行われた評価の結果を記憶するために識別子「 _ 」が使われます.

      • __*__  システムで定義された (system-defined) 名前です.

      • __*  そのクラスのプライベートな名前とみなされ,コードが生成される前により長い形式に変換されます.

  2. 演算子と式

    1. 代入文等

      1. 代入文

          代入は,基本的に C/C++ と同じような形で行いますが,複数同時の代入multiple assignment )が可能な点が大きく異なっています(このような機能,必要?).例えば,以下に示す代入文によって,変数 x には 10,変数 y には 12 が代入されます.プログラムを読みにくくする原因ともなりかねません.特別な場合を除き,使用しない方が良いと思います
        >>> x, y = 10, 3 * 4
        >>> print(x, y)
        10 12					
          Python のほとんどのデータは,オブジェクトです.変数が示す場所(アドレス)にデータ自身が記憶されているわけではなく,変数はデータ(オブジェクト)が記憶されている場所への参照(場所のアドレス)を表しています.代入においては,データをコピー(新しく生成)してそのデータに対する参照を代入しているのか,または,データそのものはすでに存在するものを使用し,そのデータに対する参照を代入しているのかといった違いに注意する必要があります.

      2. import 文

          モジュールを取り込みます.以下の例においては,math モジュールをいくつかの方法で取り込み,math モジュール内のメソッドを呼ぶ方法の変化を表しています.
        >>> import math   # math モジュールの取り込み
        >>> math.sqrt(2)
        1.4142135623730951
        >>> import math as ma   # math モジュールを ma というモジュール名として取り込む
        >>> ma.sqrt(2)
        1.4142135623730951
        >>> from math import sqrt, fabs   # math モジュールからメソッド sqrt,fabs を取り込む
        >>> sqrt(2)
        1.4142135623730951
        >>> fabs(-10)
        10.0
        >>> from math import *   # math モジュールからすべてのメソッドを取り込む
        >>> sqrt(2)
        1.4142135623730951
        >>> pow(2, 10)
        1024.0
        					

    2. 数値演算

        Python には以下に示すような数値演算を行うための演算子が存在します.なお,C/C++ と同様,代入と加算を同時に行う演算子 += など,-=,*=,・・・ も可能です.ただし,C/C++ とは異なり,インクリメント演算子 ++,デクリメント演算子 --条件演算子 = ? : が存在しないことに注意してください.
      +  : 加算(複素数に対しても可能),文字列の結合  x + y
      -  : 減算(複素数に対しても可能),符号の変更  x - y, -x
      *  : 乗算(複素数に対しても可能),繰り返し  x * y, *x
      ** : 冪乗(複素数に対しても可能,C/C++ では,pow / pow を利用)  x ** y
      /  : 除算(結果は浮動小数点数,複素数に対しても可能)  x / y
      // : 除算(小数点以下を切り捨て,C/C++ では,コメントを表す)  x // y
      %  : 剰余(浮動小数点数に対しても可能)  x % y				
        C/C++ においては,/ 演算子による除算の結果は,除数及び被乗数の型によって決まります.両者とも整数型であれば小数点以下が切り捨てられます.また,% 演算子は,除数,被乗数,共に整数の場合に対してだけ使用可能です.浮動小数点数演算における剰余を計算するためには,fmod / fmod を使用します.
      >>> a = 10
      >>> a += 5   # a = a + 5 と同じ
      >>> a
      15
      >>> a / 2
      7.5
      >>> a // 2
      7				

    3. 比較と論理演算

        Python には以下に示すような比較演算子が存在します.これらの演算子は,オブジェクト(データ)の値同士を比較します.
      <  : より小さい  a < b
      >  : より大きい  a > b
      <= : 以下  a <= b
      >= : 以上  a >= b
      == : 等しい      a == b
      != : 等しくない  a != b				
      また,以下に示すような比較演算も可能です.
      is     : 同じオブジェクト  a is b
      is not : 同じオブジェクトではない  a is not b				
        以上述べた演算子を利用して,以下に示すような論理演算が可能です.
      式1 or 式2  : 論理和(式1 または 式2 が True であれば True,そうでなければ False)
      式1 and 式2 : 論理積(式1 及び 式2 が True であれば True,そうでなければ False)
      not 式      : 否定(式 が False であれば True,そうでなければ False)				

    4. ビット単位の演算

        Python には,整数に対して,以下に示すようなビット単位の演算を行う演算子が存在します.なお,C/C++ と同様,>>=,・・・等の演算も可能です.
      << : 左にビットシフト  a << 3
      >> : 右にビットシフト  a >> 3
      &  : ビットごとの論理積  x & y
      |  : ビットごとの論理和  x | y
      ^  : ビットごとの排他的論理和  x ^ y
      ~1 の補数( 0 と 1 の逆転)  ~x				

  3. 制御文

    1. 分岐

      1. if 文

        if 式1 : 
            文1
        [elif 式2 : 
            文2]
        ・・・・・
        [elif 式n : 
            文n]
        [else  : 
            文]					

    2. 繰り返し

      1. while 文

        while : 
            文1
        [else  : 
            文2]					

      2. for 文

        for 変数 in イテラブルオブジェクト : 
            文1
        [else  : 
            文2]					

          for 文は,イテラブルオブジェクト内の要素が順に変数に代入され,要素が空になるまで,文1 が繰り返し実行されます.

  4. 配列

    1. 1 次元配列

        以下に示すのは,リスト型list ),array モジュール数値配列),及び,numpy.ndarray モジュールによる 1 次元配列の生成や処理の基本を示したプログラム例です.いずれの方法においても,問題なく,1 次元配列が生成されています.
      01	#****************************/
      02	#* 1 次元配列               */
      03	#*      coded by Y.Suganuma */
      04	#****************************/
      05	# -*- coding: UTF-8 -*-
      06	from array import *
      07	import numpy as np
      08				# リスト
      09	print ("リスト")
      10	a1 = []
      11	a2 = list()
      12	print("   空のリスト a1: " + str(a1) + ",a2: " + str(a2))
      13	
      14	a3 = [1, 2, 3]
      15	print("   角括弧とカンマの使用 a3: " + str(a3))
      16	
      17	a4 = list("abcd")
      18	a5 = list(("a", "b", "c", "d"))
      19	print("   list(iterable) の使用 a4: " + str(a4) + ",a5: " + str(a5))
      20	
      21	a6 = [x for x in "abcd"]
      22	print("   リスト内包表記の使用 a6: " + str(a6))
      23	
      24	a6.append('e')
      25	del a6[1:3]   # a6[1],a6[2] を削除
      26	print("   追加と削除 a6: " + str(a6))
      27				# array モジュール
      28	print("array モジュール")
      29	print("   タイプコード " + typecodes)
      30	b1 = array("i", [1, 2, 3])
      31	print("   b1: " + str(b1))
      32	b1.append(4)
      33	b1.remove(2)   # 値が 2 である要素を削除
      34	print("   追加と削除 b1: " + str(b1))
      35				# numpy.ndarray モジュール
      36	print("numpy.ndarray モジュール")
      37	c1 = np.array([1, 2, 3])
      38	print("   c1: " + str(c1))
      39	c2 = np.array([1.5, 2, 3])   # np.array([1, 2, 3]], np.float) と同じ
      40	print("   c2: " + str(c2))
      				
      (出力)
      リスト
         空のリスト a1: [],a2: []
         角括弧とカンマの使用 a3: [1, 2, 3]
         list(iterable) の使用 a4: ['a', 'b', 'c', 'd'],a5: ['a', 'b', 'c', 'd']
         リスト内包表記の使用 a6: ['a', 'b', 'c', 'd']
         追加と削除 a6: ['a', 'd', 'e']
      array モジュール
         タイプコード bBuhHiIlLqQfd
         b1: array('i', [1, 2, 3])
         追加と削除 b1: array('i', [1, 3, 4])
      numpy.ndarray モジュール
         c1: [1 2 3]
         c2: [ 1.5  2.   3. ]
      				

    2. 多次元配列

        以下に示すのは,リスト,array モジュール(数値配列),及び,numpy.ndarray モジュールによる 2 次元配列の生成やその性質を調べたプログラムです.15,18 行目( 28,31 行目,38,41 行目)において,2 次元配列の 1 行目及び 2 行目を変数 a2 及び a3(b2 及び b3,c2 及び c3)に代入しています.いずれの変数も,3 要素の 1 次元配列としてみなせますが,2 次元配列と独立した 1 次元配列ではありません.C++ 風に言えば,2 次元配列における各行のアドレスを各変数に代入しているとみなせます.従って,2 次元配列の各行と対応する各変数は同じ場所を指していることになります.そこで,1 次元配列の値を変更すれば,出力結果からも明らかなように,対応する 2 次元配列の値も変化します(逆も同様).
      01	#****************************/
      02	#* 2 次元配列               */
      03	#*      coded by Y.Suganuma */
      04	#****************************/
      05	# -*- coding: UTF-8 -*-
      06	from array import *
      07	import numpy as np
      08				# リスト
      09	print ("リスト")
      10	#a1    = [[], []]
      11	#a1[0] = [1, 2, 3]
      12	#a1[1] = [4, 5, 6]
      13	a1       = [[1, 2, 3], [4, 5, 6]]   # 上の 3 行でも可
      14	a1[1][0] = 10;
      15	a2       = a1[0]   # 要素数 3 の 1 次元配列
      16	a2[1]    = 100
      17	#a2[3]    = 1000   # error(index out of range)
      18	a3       = a1[1]   # 要素数 3 の 1 次元配列
      19	print("   2 次元配列 a1: " + str(a1))
      20	print("   1 次元配列  a2: " + str(a2) + ",a3: " + str(a3))
      21				# array モジュール
      22	print("array モジュール")
      23	#b1    = [array("i", []), array("i", [])]
      24	#b1[0] = [1, 2, 3]
      25	#b1[1] = [4, 5, 6]
      26	b1 =  [array("i", [1, 2, 3]), array("i", [4, 5, 6])]   # 上の 3 行でも可
      27	b1[1][0] = 10;
      28	b2       = b1[0]   # 要素数 3 の 1 次元配列
      29	b2[1]    = 100
      30	#b2[3]    = 1000   # error(index out of range)
      31	b3       = b1[1]   # 要素数 3 の 1 次元配列
      32	print("   2 次元配列 b1: " + str(b1))
      33	print("   1 次元配列 b2: " + str(b2) + ",b3: " + str(b3))
      34				# numpy.ndarray モジュール
      35	print("numpy.ndarray モジュール")
      36	c1       = np.array([[1, 2, 3], [4, 5, 6]])
      37	c1[1][0] = 10;
      38	c2       = c1[0]   # 要素数 3 の 1 次元配列
      39	c2[1]    = 100
      40	#c2[3]    = 1000   # error(index out of range)
      41	c3       = c1[1]   # 要素数 3 の 1 次元配列
      42	print("2 次元配列 c1: ")
      43	print(str(c1))
      44	print("1 次元配列 c2: " + str(c2) + ", c3: " + str(c3))
      				
      (出力)
      リスト
         2 次元配列 a1: [[1, 100, 3], [10, 5, 6]]
         1 次元配列  a2: [1, 100, 3],a3: [10, 5, 6]
      array モジュール
         2 次元配列 b1: [array('i', [1, 100, 3]), array('i', [10, 5, 6])]
         1 次元配列 b2: array('i', [1, 100, 3]),b3: array('i', [10, 5, 6])
      numpy.ndarray モジュール
      2 次元配列 c1:
      [[  1 100   3]
       [ 10   5   6]]
      1 次元配列 c2: [  1 100   3], c3: [10  5  6]
      				

    3. 連想配列

        キーとそれに結びついた値のペアで構成される配列を連想配列と呼びます.Python におけるマッピング型辞書型mapping 型)は.ハッシュ可能な値であるキーと任意のオブジェクトのペアから構成されます.キーは,ほぼ,任意の値ですが,ハッシュ可能でない値,つまり,リストや辞書など変更可能な型はキーとして使用できません.C++ の C++ 標準ライブラリ内の map クラスunordered_map クラスと似ていますが,map や unordered_map とは異なり,異なる型のオブジェクトを要素として持つことができます.以下に示すのは,辞書型の基本的な使用法です.
      #****************************/
      #* 連想配列                 */
      #*      coded by Y.Suganuma */
      #****************************/
      # -*- coding: UTF-8 -*-
      			# 生成
      #x = {"aaa" : 10, "ddd" : 20, "ccc" : 30}
      x = dict(aaa = 10, ddd = 20, ccc = 30)
      print(x)
      			# 参照
      print("  キー ccc に対する値: " + str(x['ccc']))
      			# 追加
      x['bbb'] = 1
      print("  キー bbb に対する値 1 を追加: " + str(x))
      			# 削除
      del x['aaa']
      print("  キー aaa に対する値を削除: " + str(x))
      				
      (出力)
      {'ccc': 30, 'aaa': 10, 'ddd': 20}
        キー ccc に対する値: 30
        キー bbb に対する値 1 を追加: {'bbb': 1, 'ccc': 30, 'aaa': 10, 'ddd': 20}
        キー aaa に対する値を削除: {'bbb': 1, 'ccc': 30, 'ddd': 20}				

  5. 関数

    1. 関数とその性質

      1. 定義とデフォルト引数

          ここでは,関数の定義方法について,例を使用しながら説明していきます.まず,最初は,最も基本的な関数です.3 つのデータを受け取り,それらの和を返す関数です.以下に示すような内容のファイル test.py を作成し,Window のコマンドプロンプト上で,
        py -3 test.py [data]   # [ ] 内はオプション					
        と入力すれば結果が得られるはずです.関数は,本来,独立したプログラムです.しかし,関数を test.py 内に記述すると,関数内からその外側の(メインプログラム内の)変数を参照できてしまいます.そのため,関数は,別のファイル function.py 内に記述し,import 文で組み込んでいます( 08 行目).
        01	# -*- coding: UTF-8 -*-
        02	def func(s1, s2 = 20, s3 = 30) :
        03		"""example of function"""
        04		s  = s1 + s2 + s3
        05		s1 = 100
        06		return s
        ----------------------------------
        07	# -*- coding: UTF-8 -*-
        08	from function import func
        09	import sys
        10	print(func.__doc__)
        11	p1 = 10
        12	print("sum = ", func(p1))   # func(s1 = 10) or func(10) でも可
        13	print("p1 = ", p1)
        14	print("sum = ", func(p1, s2 = 50))   # func(10, 50) でも可
        15	print(len(sys.argv), sys.argv[0])
        16	#print(len(sys.argv), sys.argv[0], sys.argv[1])   # オプションを付加した場合
        					
        02 行目

          関数の定義は,キーワード def で始まり,関数名 func の後ろの括弧の中に仮引数のリスト(この例では,s1,s2,s3 )が並びます.これらの仮引数は,関数を呼び出す際にも,実引数として,同じ位置,同じ順番で記述する必要がありますので,位置指定引数と呼ばれます.なお,変数名は異なっても構いません( 12,14 行目において,p1 が s1 に対応).

          引数に対しては,それらが省略されたときの値,つまり,デフォルト値を設定することができます(デフォルト引数,C++ にも,同様の機能).この例では,引数 s2 及び s3 に対して設定しています.その結果,12 行目では s2 及び s3 を省略,また,14 行目では s3 を省略していますが,正しく計算されています.なお,最初または中間にある位置指定引数,例えば,s1 または s2 に対してだけデフォルト値を設定することはできません.なお,Python には,関数名の多重定義機能はありません.

        03 行目

          関数の本体を記述する文の最初の行は文字列リテラルにすることもできます.その場合,この文字列は関数のドキュメンテーション文字列と呼ばれ,変数 __doc__ によって参照できます( 10 行目参照).

        05 行目

          先に述べたように,関数は,本来,独立したプログラムです.しかし,関数における処理をする際に何らかの情報が欲しい場合があります.その情報を引き渡す手段が引数です(外部からの情報を必要としない場合は引数を記述しなくて良い).基本的に,実引数の値がコピーされて,仮引数に渡されます.従って,実引数と仮引数は全く独立した変数(値)ですので,この例の場合,変数 s1 の値を変更しても,変数 p1 の値は変化しません( 13 行目に対する出力結果参照).この点は,実引数と仮引数の変数名が同じである場合も同様です.

        06 行目

          return 文は,関数を呼び出した先に結果を返すための文です.この例の場合は,s1,s2,s3 の和が戻され,12,14 行目の結果となります.なお,結果を戻さない場合は必要ありません.

        08 行目

          function モジュール内にある関数 func を取り込んでいます.

        09 行目

          15,16 行目のために必要です.

        12,14 行目

          Python では,引数の渡し方として,「 s1 = 10 」「 s2 = 50 」のような形をとることができますが,関数は独立したプログラムであるべきなのに,関数の仮引数の名前を使用するといった仕様はいかがなものでしょうか.

        15,16 行目

          変数 sys.argv には,C/C++ 風に言えば,main 関数の引数に対する情報が入っています.プログラムを実行する際,何らかの付加的情報を必要とする場合があります.そのようなとき,上に示した使用方法における [ ] 内の data のように,その情報を記述可能です.これらの情報は,変数 sys.argv に入れられて渡されます.オプションを記述しなかった場合( 15 行目)は,実行したファイル名だけが入っています.test.py の実行時に,
        	py -3 test.py data						
        のように,data というオプションを付加すると,変数 sys.argv のサイズは 2 となり,そのオプションも渡されます( 16 行目と一番最後の出力).
        (出力)
        example of function
        sum =  60
        p1 =  10
        sum =  90
        1 test.py
        #2 test.py data					

      2. 様々な引数

        プログラム例 5.1] 様々な引数

          上で述べたように,引数として渡した変数の値を関数内で変化させても,その影響は関数を呼んだ側には現れません.しかし,場合によっては,そのようなことをしたい場合があります.C/C++ には,アドレス渡し参照渡しなどの方法がありますが,Python では,どのようにしたら良いのでしょうか.

          C/C++ において配列を引数とするとそのアドレスが渡るため,関数内で配列の要素の値を変更すると,関数を呼んだ側においても対応する値が変化します.Python においても,デフォルト引数の例で示したプログラム例からも明らかなように,リストを引数とすると,関数内での変更が関数を呼んだ側にも反映されます.次に示すプログラム例においては,整数型int 型),浮動小数点数型float 型),複素数型complex 型),リスト型,及び,numpy.ndarray モジュールによる配列を引数としています.関数内では,いずれの引数に対しても変更を加えています.関数内( 09 行目),及び,関数を呼んだ後( 19 行目)の出力結果は,
        a: 10 b: 3.13 c: (5+6j) x:[10, 2, 3] y:[ 1 10  3]
        a: 1 b: 1.5 c: (1+2j) x:[10, 2, 3] y:[ 1 10  3]					
        のようになります.関数内では全ての変数の値が変化しているのに,関数を呼んだ後のメインプログラム内では,整数型,浮動小数点数型,及び,複素数型の基本型変数は変化していませんが,他の二つの変数は,関数内で修正したように変化しています.この点は,後に述べるクラスのオブジェクトを引数にした場合も同様です.
        01	# -*- coding: UTF-8 -*-
        02	import numpy as np
        03	def func(a, b, c, x, y) :
        04		a = 10
        05		b = 3.13
        06		c = complex(5, 6)
        07		x[0] = a
        08		y[1] = a
        09		print("a: " + str(a) + " b: " + str(b) + " c: " + str(c) + " x:" + str(x) + " y:" + str(y))
        ----------------------------------
        10	# -*- coding: UTF-8 -*-
        11	import numpy as np
        12	from function import func
        13	a = 1
        14	b = 1.5
        15	c = complex(1, 2)
        16	x = [1, 2, 3]
        17	y = np.array([1, 2, 3])
        18	func(a, b, c, x, y)
        19	print("a: " + str(a) + " b: " + str(b) + " c: " + str(c) + " x:" + str(x) + " y:" + str(y))
        					

      3. 引数と関数名

        プログラム例 5.2] 引数と関数名

          Python においては,関数も一つのオブジェクトです.従って,関数(のアドレス)を他の変数に代入すれば,その変数は関数と同じように使用できます( 14,15 行目).また,関数(のアドレス)を関数の引数としても使用可能です( 16,17 行目).
        01	# -*- coding: UTF-8 -*-
        02	def add(s1, s2) :
        03		s = s1 + s2
        04		return s
        05	def sub(s1, s2) :
        06		s = s1 - s2
        07		return s
        08	def add_sub(fun, s1, s2) :
        09		s = fun(s1, s2)
        10		return s
        ----------------------------------
        11	# -*- coding: UTF-8 -*-
        12	from function import add, sub, add_sub
        13	print(add(2, 3))   # 5
        14	kasan = add
        15	print(kasan(2, 3))   # 5
        16	print(add_sub(add, 2, 3))   # 5
        17	print(add_sub(sub, 2, 3))   # -1
        					

      4. ローカル変数とグローバル変数

          一般に,関数内で定義された変数は,関数内だけで有効です.しかし,場合によっては,複数の関数内で特定の変数を参照したい場合があります.この様な変数をグローバル変数global variable ),また,関数内だけで有効な変数をローカル変数local variable )と呼びます.基本的に,関数外で変数を定義すれば,その変数はグローバル変数となり,関数内からもその変数を参照・変更可能となります.下の例における 13 行目の変数 a が相当します.

          ただし,関数内においてグローバル変数を修正する場合は十分注意する必要があります.04 行目が存在しなければ,03,05 行目は,グローバル変数 a の値を出力します.しかし,04 行目によって,グローバル変数と同じ名前の新しいローカル変数が定義されたとみなされます.従って,03 行目は,未定義の変数 a の出力とみなされエラーになります.

          関数 func1 のような形で,関数内でグローバル変数の値を修正しようとすれば,新しいローカル変数の定義とみなされ,グローバル変数の値は変更されません.関数内においてグロ-バル変数の値を修正するためには,08 行目のような宣言が必要です.もしこの宣言がなければ,a は新しいローカル変数とみなされ,関数 func1 の場合と同様,09 行目でエラーになってしまいます.
        01	# -*- coding: UTF-8 -*-
        02	def func1() :
        03	#	print(str(a) + " in func1")   エラー
        04		a = 20
        05		print(str(a) + " in func1")
        06	
        07	def func2() :
        08		global a   # 記述しないとエラー
        09		print(str(a) + " in func2")
        10		a *= 10
        11		print(str(a) + " in func2")
        12	
        13	a = 10
        14	print(a)
        15	func1()
        16	print(a)
        17	func2()
        18	print(a)
        					
          上のプログラムを実行すると以下のような出力が得られます.
        10
        20 in func1
        10
        10 in func2
        100 in func2
        100					

    2. ジェネレータ関数

        ジェネレータは,イテレータ(順番にオブジェクトの要素を取り出すための演算子)を作成するための簡潔なツールです.簡単にジェネレータを生成したいときは,ジェネレータ式を利用できます.ジェネレータ式は,丸括弧を使用し,以下のような形になります.なお,引数が一つである関数の引数とする場合は,丸括弧を省略できます.
      (式 for 式 in イテラブルオブジェクト)   # for を多重に使用しても良い				

  6. クラス

    1. クラスの定義

        C++ の用語で言えば,通常のクラスclass )のメンバー(変数及び関数)は public であり,どこからでも参照可能です.メンバー関数(クラス内で定義された関数であり,メソッドと呼ぶ)はすべて仮想関数です.メソッドの宣言では,生成されたインスタンス自身を表す第一引数 self を明示しなければなりません.この引数は,メソッド呼び出しの際に暗黙の引数として渡されます.一般的に,「 self.var 」の形でメソッドの内側で定義される変数 var は,インスタンス変数と呼ばれ,各インスタンス固有の値を持つことが可能です.また,メソッドの外側で宣言され,かつ,self がつかないクラス変数は,そのクラスのすべてのインスタンスで同じ値を持ちます.
      01	# -*- coding: UTF-8 -*-
      02	class Example :
      03	    """A simple example of class"""   # クラスの説明
      04	    c_var = 12345   # クラス変数
      05	    def func(self, a) :
      06	        self.i_var = a   # インスタンス変数
      ----------------------------------
      07	# -*- coding: UTF-8 -*-
      08	from function import Example
      09	print(Example.__doc__)   # クラスの説明の表示
      10	x = Example()   # Example クラスのインスタンス(オブジェクト)の生成
      11	x.func(10)   # Example.func(x, 10) と等価
      12	y = Example()
      13	y.func(20)
      14	z = Example()
      15	z.func(30)
      16	print("最初の状態  x,y,z")
      17	print(Example.c_var, x.c_var, x.i_var)
      18	print(Example.c_var, y.c_var, y.i_var)
      19	print(Example.c_var, z.c_var, z.i_var)
      20	print("***w に x を代入***")
      21	w = x
      22	print("w の値変更  x,y,z,w")
      23	w.c_var = 100
      24	w.i_var = 40
      25	print(Example.c_var, x.c_var, x.i_var)
      26	print(Example.c_var, y.c_var, y.i_var)
      27	print(Example.c_var, z.c_var, z.i_var)
      28	print(Example.c_var, w.c_var, w.i_var)
      29	print("x の値変更  x,y,z,w")
      30	xf = x.func   # 関数に対するポインタ,普通の関数でもOK
      31	xf(50)
      32	x.c_var = 1000
      33	print(Example.c_var, x.c_var, x.i_var)
      34	print(Example.c_var, y.c_var, y.i_var)
      35	print(Example.c_var, z.c_var, z.i_var)
      36	print(Example.c_var, w.c_var, w.i_var)
      37	print("クラス変数値の変更  x,y,z")
      38	Example.c_var = 123
      39	print(Example.c_var, x.c_var, x.i_var)
      40	print(Example.c_var, y.c_var, y.i_var)
      41	print(Example.c_var, z.c_var, z.i_var)
      42	print(Example.c_var, w.c_var, w.i_var)
      				
      02 行目~ 06 行目

        クラス Example の定義です.クラス変数 c_var( 04 行目),インスタンス変数 i_var( 06 行目),及び,メソッド func( 05 行目~ 06 行目)を定義しています.

      03 行目

        クラス本体を記述する文の最初の行は文字列リテラルにすることもできます.その場合,この文字列はクラスのドキュメンテーション文字列と呼ばれ,変数 __doc__ によって参照できます( 09 行目).

      10 行目~ 19 行目

        Example クラスのオブジェクト x,y,z を生成しています.インスタンス変数の値は異なりますが,クラス変数の値はすべて同じです.

      20 行目~ 28 行目

        x を w に代入後,w のクラス変数及びインスタンス変数の値を変更しています.当然,w の値は変化しますが,x の値も変化しています.これは,x と w が同じオブジェクトを指していることも意味します.つまり,Python におけるオブジェクトは,C/C++ におけるポインタに似た性質を持つことになります.従って,関数に対する説明において述べたリストを引数とした場合と同様,クラスのインスタンスを引数とした場合は,関数内でその値を変更すれば,関数を呼んだ側の値も変化します.

      29 行目~ 36 行目

        x と w は同じインスタンスを指していますので,x の値を変化させても,上と同様なことが起こります.また,関数自体もポインタ(関数を指すアドレス)ですので,30,31 行目のようなことが可能です.

      37 行目~ 42 行目

        クラス変数の値を変更すると( 38 行目),そのクラスのすべてのインスタンスのクラス変数の値も変化します( 40,41 行目).ただし,23,32 行目のように,インスタンスのクラス変数の値を直接変更した場合は,その影響を受けません( 39,42 行目).
      (出力)
      A simple example of class
      最初の状態  x,y,z
      12345 12345 10
      12345 12345 20
      12345 12345 30
      ***w に x を代入***
      w の値変更  x,y,z,w
      12345 100 40
      12345 12345 20
      12345 12345 30
      12345 100 40
      x の値変更  x,y,z,w
      12345 1000 50
      12345 12345 20
      12345 12345 30
      12345 1000 50
      クラス変数値の変更  x,y,z
      123 1000 50
      123 123 20
      123 123 30
      123 1000 50
      				

    2. 初期化

        クラスに __init__() メソッドが定義されている場合,クラスのインスタンスを生成すると最初にこのメソッドが呼ばれます.C++ におけるコンストラクタに対応するメソッドです.
      # -*- coding: UTF-8 -*-
      class Complex() :
      	def __init__(self, re, im = 0.0) :
      		self.re = re
      		self.im = im
      	def add(self, v) :
      		x = Complex(self.re + v.re, self.im + v.im)
      		return x
      ----------------------------------
      # -*- coding: UTF-8 -*-
      from function import Complex
      x = Complex(1, 2)
      y = Complex(3)
      z = x.add(y)
      print((z.re, z.im))   # (4, 2.0)
      				

    3. 継承

        派生クラスを定義する方法は簡単です.以下に示すように,基底クラスとなるクラス名を括弧内に並べるだけです(多重継承が可能).
      class DerivedClassName ( BaseClassName1, BaseClassName2, ・・・ ):				
       また,
      BaseClassName.methodname ( self, arguments ) 				
      という形で,基底クラスのメソッドも簡単に呼び出すことができます.

        下の例では,Num を基底クラスとした 2 つの派生クラス,Int 及び Complex を定義しています.
      # -*- coding: UTF-8 -*-
      class Num :
      	name = "数値"
      	def __init__(self, v) :
      		self.v = v
      	def add(self, v) :
      		x = Num(self.v + v)
      		return x
      class Int(Num) :
      	name = "整数"
      class Complex(Num) :
      	name = "複素数"
      		# 親クラスのコンストラクタを呼びたい場合は Num.__init__(self, 値)
      	def __init__(self, re, im = 0.0) :
      		self.re = re
      		self.im = im
      	def add(self, v) :
      		x = Complex(self.re + v.re, self.im + v.im)
      		return x
      ----------------------------------
      # -*- coding: UTF-8 -*-
      from function import *
      x = Int(10)   # 基底クラス Num のコンストラクタ __init__ の継承により,変数 v に値が設定される
      print(x.v)   # 10
      y = x.add(20)   # 親クラス Num のメソッド add の継承
      print(y.v)   # 30
      u = Complex(1, 2)   # クラス Complex のコンストラクタ __init__ の利用
      print((u.re, u.im))   # (1, 2)
      v = Complex(3)
      print((v.re, v.im))   # (3, 0.0)
      w = u.add(v)   # クラス Complex のメソッド add の利用
      print((w.re, w.im))   # (4, 2.0)
      u.re = (Num.add(Num(u.re), 10)).v   # 基底クラスのメソッド add の利用
      print((u.re, u.im))   # (11, 2)
      print(u.name)   # クラス Complex のクラス変数 name の値(複素数)
      print(Num.name)   # 基底クラス Num のクラス変数 name の値(数値)
      				

    4. インスタントメソッド,クラスメソッド,スタティックメソッド

        今まで使用してきたメソッドはインスタントメソッドと呼ばれ,クラスのインスタント(オブジェクト)固有の処理を行うためのメソッドです.これ以外に,Python には,クラスメソッド,及び,スタティックメソッドが存在します.クラスメソッド,スタティックメソッドともに,インスタンス変数にはアクセスできません.

        クラスメソッドは,「 @classmethod 」を付与して関数を定義します.インスタンスメソッドの場合は,第一引数にオブジェクト自身 self が渡されますが,クラスメソッドの場合は,第一引数にクラスが渡されます.従って,クラスメソッドは渡ってきたクラスを使ってクラス変数にアクセスすることができます.継承時には,第一引数に子クラスが渡されるため,クラス変数は子クラスのクラス変数の値となります.

        スタティックメソッドは,「 @staticmethod 」を付与して関数を定義します.スタティックメソッドは,クラスが渡されないため,クラス変数にアクセスするためには,クラスを記述する必要があります.クラスを記述することによってクラス変数にアクセスするため,継承時においても,記述したクラスが親クラスか子クラスかによって参照先が変わります.

  7. 入出力

    1. 標準入出力

        コマンドプロンプト上でデータを変数に入力するためには(標準入力sys.stdin からの入力),組み込み関数 input を使用します.引数を記述すると,それが末尾の改行を除いて標準出力に書き出され,入力された 1 行を読み込み,文字列に変換して返します(末尾の改行を除去).また,変数の値などを標準出力sys.stdout )に表示するためには,組み込み関数 print を使用します.print は,与えられたオブジェクトを,スペースで区切り,標準出力に表示し,最後に改行します.
      01	# -*- coding: UTF-8 -*-
      02	a = input("data? ")
      03	b = a.split()
      04	print(b)
      05	x = int(b[0])
      06	y = float(b[1])
      07	z = b[2]
      08	print(x, y, z)
      09	print("x = " + str(x) + ", y = " + str(y) + ", z = " + str(z))
      10	#print("x = " + x + ", y = " + y + ", z = " + z)   # error
      11	form = "x = {0:2d}, y = {1:.2f}, z = {2:s}".format(x, y, z)
      12	print(form)
      				
      02 行目

        「 data? 」というメッセージが出力されます.例えば,「 10 3.141592654 abc 」を入力し改行を行うと,入力した結果が文字列として変数 a に代入されます.

      03,04 行目

        入力された文字列には,3 つのデータが含まれていますので,文字列型に対するメソッド split を使用して分離します.分離されたデータは,リストとして返されます( 03 行目).04 行目では,その結果を,組み込み関数 print を使用して,出力しています.05 行目~ 07 行目に示すように,リスト内の i 番目のデータを添え字 [i-1] で参照することができます.

      05 行目~ 07 行目

        数値データは,文字列のままでは演算等に使用できませんので,組み込み関数 intfloat を使用して,整数や浮動小数点数に変換します.ただし,変数 z に対しては,文字列のまま代入しています.

      08 行目

        組み込み関数 print を使用して,3 つの変数の値を出力しています.

      09 行目

        例えば,
      	x = ..., y = ..., z = ...					
      のような形式で出力したい場合,10 行目のような記述では,x 等を自動的に文字列に変換してくれず,エラーになってしまいます.そのため,変数 x 等を,組み込み関数 str によって,文字列に変換して,他の文字列と結合しています.

      11,12 行目

        データを書式化して出力したい場合は,文字列型に対するメソッド format を使用します.format は,C/C++ の printf に似た方法によって書式化を実行します.この例では,整数は 2 桁で,また,浮動小数点数は小数点以下 2 桁で出力します.
      (出力)
      data? 10 3.141592654 abc
      ['10', '3.141592654', 'abc']
      10 3.141592654 abc
      x = 10, y = 3.141592654, z = abc
      x = 10, y = 3.14, z = abc				

    2. ファイル入出力

        ここでは,ファイル入出力の際必要となる基本的な関数やメソッドについて説明します.

      • open('file_name', 'w')ファイルオブジェクト f を返す.通常,2 つの引数を伴って呼び出される.最初の引数はファイル名の入った文字列である.2 つ目の引数,mode 引数も文字列であり,ファイルをどのように使用するかを示す数個の文字が入っている.ファイルが読み出し専用なら 'r',書き込み専用なら 'w' とする.'a' はファイルを追記用に開き,ファイルに書き込まれた内容は自動的にファイルの終端に追加される.'r+' はファイルを読み書き両用に開く.mode 引数を省略すると,'r' であると見なされる.通常,ファイルはテキストモードで開かれるが,JPEG ファイルや EXE ファイルのようなバイナリデータの場合は,mode に 'b' を付け,バイナリモードで開く必要がある.

      • f.close() : ファイルオブジェクト f を閉じる.

      • f.closed : ファイルオブジェクト f が閉じられていれば True に設定される.

      • f.read([size]) : 最大 size バイトのデータを読み出し,文字列(テキストモードの場合),または,bytes オブジェクト(バイナリーモードの場合)として返す.size が省略されたり負の数であった場合,ファイルの内容全てを読み出して返す.また,ファイルの終端に達していた場合,空の文字列( '' )を返す.

      • f.readline() : ファイルから 1 行だけ読み取る.なお,改行文字( \n )は読み出された文字列の終端に残る.

      • f.write(object) : object の内容をファイルに書き込み,書き込まれた文字数を返す.オブジェクトの型は,書き込む前に,文字列(テキストモード),または,bytes オブジェクト(バイナリーモード)に変換しなければならない.

      • f.seek(offset[, from_what]) : ファイルオブジェクトの位置を変更する.位置は from_what によって指定された値に offset を加えて計算される.from_what の値が 0 ならばファイルの 先頭から,1 ならば現在のファイル位置,2 ならばファイルの終端を基準点とする.from_what のデフォルトは 0 である.

        以下に示すのは,上で述べた関数やメソッドの簡単な使用例です.
      # -*- coding: UTF-8 -*-
      			# 出力
      f = open("test.txt", "w")   # 出力のためにオープン
      f.write("10 3.1492654 abc\nテスト データ\n")
      f.close()
      			# 全てのデータを入力
      f = open("test.txt", "r")   # 入力のためにオープン
      a = f.read()
      print(a)   # "10 3.1492654 abc\nテスト データ\n"
      			# ファイルの先頭に移動
      f.seek(0)
      			# 1 行ずつ入力
      b = f.readline()
      print(b)   # "10 3.1492654 abc\n"
      b = f.readline()
      print(b)   # "テスト データ\n"
      b = f.readline()
      print(b)   # ""
      
      f.close()
      				

  8. 変数の有効範囲(スコープ)

    01	# -*- coding: UTF-8 -*-
    02	
    03	#***************************/
    04	# 変数の有効範囲(スコープ) */
    05	#      coded by Y.Suganuma */
    06	#***************************/
    07	
    08	#******************/
    09	# クラス Example1 */
    10	#******************/
    11	class Example1 :
    12		c_var = 1000
    13	
    14		def __init__(self) :
    15			self.i_var = 2000
    16	
    17		def sub1(self) :
    18			print("sub1 c_var", self.c_var, "i_var", self.i_var)
    19	
    20	#******************/
    21	# クラス Example2 */
    22	#******************/
    23	class Example2(Example1) :
    24		def sub2(self) :
    25			print("sub2 c_var", self.c_var, "i_var", self.i_var)
    26	
    27	#***********/
    28	# 関数 sub */
    29	#***********/
    30	def sub() :   # この位置で定義する必要がある
    31		x = 40
    32		print("   sub x", x)
    33		print("   sub z", z)
    34	
    35	#***************/
    36	# main program */
    37	#***************/
    38			# ブロック
    39	x = 10
    40	z = 30
    41	if x > 5 :
    42		print("block x", x)
    43		x = 15
    44		y = 20
    45		print("block x", x)
    46		print("block y", y)
    47	else :
    48		print("block x", x)
    49		x = -15
    50		print("block x", x)
    51	sub()
    52	print("x", x)
    53	print("y", y)   # 最初の x が 1 の時は,y が未定義のためエラー
    54			# クラス
    55	ex = Example2()
    56	ex.sub1()
    57	ex.sub2()
    58	print("member( c_var )", Example2.c_var)
    59	print("member( i_var )", ex.i_var)
    			
      まず,39 行目において,変数 x が定義され(変数 x に値が代入され),10 で初期設定されています.この変数 x は,この位置から main プログラムが終わる 59 行目まで有効になります.42 ~ 46 行目の if ブロック内の 42 行目において,変数 x の値が出力されていますが,当然,その結果は,39 行目で宣言されたときの値になります.しかし,43 行目において,再び,変数 x が宣言されていますが,Python の場合は,C++ の場合とは異なり,39 行目で宣言された変数 x に置き換わることになります.従って,ここで宣言された変数 x の有効範囲は,main プログラムの終わりである 59 行目までになります.実際,52 行目における出力文では,43 行目において宣言された変数 x の値が出力されます.同様に,44 行目で宣言された変数 y の有効範囲も 59 行目までとなります.この例では,問題がありませんが,39 行目における変数 x の初期値を 5 以下に設定すると,48 ~ 50 行目が実行されることになります.そのブロック内では,変数 y が使用されていませんので,53 行目の出力文はエラーになってしまいます.変数が定義されているか否か(変数に値が代入されているか否か)の見極めが困難である場合も多いと思いますので,十分注意してください.

      51 行目において関数 sub を呼んでいます.31 行目では,変数 x を宣言(変数 x に値を代入)し,32 行目において,その値を出力しています.31 行目の宣言を行わなければ,変数 z と同様,main プログラム内の変数 x の値が出力されます.main プログラム内の変数 x ( 39 行目)の値を変更したい場合は,31 行目の前に,
    global x				
    という宣言をしておく必要があります.

      一般に,Python では,main プログラム内の変数は,33 行目に示すように,どの関数からも参照することができます(非常に危険だと思いますが).ただし,関数内で main プログラムと同じ変数を定義(変数に代入を行うことを意味する)したり,あるいは,新しい変数を定義した場合,それらの変数を main プログラムから参照することはできません( 52 行目に対応する出力結果参照).また,ある関数から,異なる関数内の変数を参照することも不可能です.このように,どの関数からも参照可能な変数をグローバル変数と呼びます.逆に,ある関数内だけで有効な変数を,ローカル変数と呼びます.以上,40 ~ 54 行目内の出力文(関数 sub 内の出力文を含む)によって,以下に示すような出力が得られます.
    block x 10
    block x 15
    block y 20
       sub x 40
       sub z 30
    x 15
    y 20				
      次に,クラスに付いて考えてみます.11 ~ 18 行目においてクラス Example1 が定義され,23 ~ 25 行目では,クラス Example1 を継承する形で,クラス Example2 が定義されています.なお,Python においては,すべての変数をクラス外から参照可能です( C++ において,public 指定してる状況).

      55 行目において,Example2 のインスタンス ex を生成し,56 行目では,クラス Example1 から継承した関数 sub1 を通して,2 つの変数を出力しています.また,57 行目では,クラス Example2 に追加された関数 sub2 を通して各変数を出力しています.いずれも,同じように出力されます.Python において,12 行目のような形で宣言された変数はクラス変数と呼ばれ,すべてのクラスのインスタンスで同じ値を持ち,クラス外部からでも,58 行目のような形で参照できます.また,15 行目のように,self を付加して宣言した変数は,インスタンス変数と呼ばれ,インスタンス毎に異なる値をとることが可能です.インスタンス変数は,59 行目のような形で,クラスの外部からも参照することができます.以上,55 ~ 69 行目内の出力文によって,以下に示すような出力が得られます.
    sub1 c_var 1000 i_var 2000
    sub2 c_var 1000 i_var 2000
    member( c_var ) 1000
    member( i_var ) 2000				

情報学部 菅沼ホーム Python と C/C++ 目次