情報学部 菅沼ホーム 目次 索引

特殊なデータ型

  1. 二分法アルゴリズム

      bisect モジュールは,新しいデータをリストに挿入する度に,リストをソートされた順序に保つことを目的としています.C++ 標準ライブラリ内にある multiset クラスと似ていますが,multiset とは異なり,異なる型のオブジェクトを要素として持つことができます.タプル型リスト型集合型辞書型なども同様ですが,「異なる型のオブジェクトを要素として持つことができる」という仕様には疑問を感じます.誤りの原因となりやすく,避けた方が良いと思います.

    • bisect_left(a, x, lo=0, hi=len(a))

        基本的に bisect.bisect_right と同じだが,x が既に a に含まれていた場合,それらの最も前に位置する点を返す.

    • bisect.bisect_right(a, x, lo=0, hi=len(a))
      bisect.bisect(a, x, lo=0, hi=len(a))

        ソートされているリスト a の区間 [lo, hi] を探索し,ソートされた順序を保ったまま x を a に挿入できる点を返す.x が既に a に含まれていた場合,それらの最も後ろに位置する点を返す.
      >>> from bisect import *
      >>> a = [1, 3, 5]
      >>> bisect_right(a, 3)
      2
      >>> bisect_left(a, 3)
      1				

    • bisect.insort_left(a, x, lo=0, hi=len(a))

        基本的に insort_right と同じだが,x が既に a に含まれていた場合,それらの最も前に挿入する.

    • bisect.insort_right(a, x, lo=0, hi=len(a))
      bisect.insort(a, x, lo=0, hi=len(a))

        ソートされているリスト a の区間 [lo, hi] を探索し,その中のソート順を崩さない位置に x を挿入する.これは,a.insert(bisect_right(a, x, lo, hi), x) と等価である.x が既に a に含まれていた場合,それらの最も後ろに挿入する.
      >>> from bisect import *
      >>> a = []
      >>> insort_right(a, 5)
      >>> a
      [5]
      >>> insort_right(a, 1)
      >>> a
      [1, 5]
      >>> insort_right(a, 10)
      >>> a
      [1, 5, 10]
      >>> insort_right(a, 7)
      >>> a
      [1, 5, 7, 10]
      				

  2. 浅いコピーと深いコピー

    • copy.copy(x)

        x の浅いコピーを返す.次の例の 03 行目のように,x を y に代入した後,y の要素を変更した場合,対応する x の要素も変化する.これは,03 行目の方法で代入を実行した場合,オブジェクトに対する参照(アドレス)がコピーされ,同じオブジェクトを指すことになっているからである.C/C++ 風に言えば,同じオブジェクトに対するポインタがコピーされ代入されたことになる(下図参照).
      01	# -*- coding: UTF-8 -*-
      02	x = [1, 2, 3]
      03	y = x
      04	y[0] = 10
      05	print(x, y)   # [10, 2, 3] [10, 2, 3]				
        これを避けるためには,次の例の 04 行目に示すように,x の浅いコピー( x が参照しているオブジェクトのコピー)を新たに生成し,それに対する参照を y に代入する必要がある(下図参照).
      01	# -*- coding: UTF-8 -*-
      02	import copy
      03	x = [1, 2, 3]
      04	y = copy.copy(x)
      05	y[0] = 10
      06	print(x, y)   # [1, 2, 3] [10, 2, 3]				

    • copy.deepcopy(x)

        x の深いコピーを返す.浅いコピーにおいては,オブジェクト内に存在するオブジェクトに対しては,その参照(下図における ad11 と ad12 の部分,アドレス)をコピーしているだけであるので,以下に示す 2 次元のリスト(配列)のような場合は,上と同じ問題が発生する.
      01	# -*- coding: UTF-8 -*-
      02	import copy
      03	x = [[1, 2, 3], [4, 5, 6]]
      04	y = copy.copy(x)
      05	y[0][0] = 10
      06	print(x,y)   # [[10, 2, 3], [4, 5, 6]] [[10, 2, 3], [4, 5, 6]]				

        1 次元のリスト(配列)の場合であっても,各要素がクラスのオブジェクトである場合は,以下に示すように,同じような問題が発生する.クラスのオブジェクトを要素とした場合,各要素にはオブジェクトに対するアドレスが記憶されている.浅いコピーは,x の各要素の値(アドレス,参照)をコピーして新しい配列 y を生成する.その際,各要素に記憶されているアドレスが指すオブジェクト自身はコピーされない.そのため,x と y の各要素は,同じオブジェクトを指すことになる.y[1] のように,新しいオブジェクト(のアドレス)を代入した場合( 10 行目),x はその影響を受けないが,y[2] のような変更( 11 行目)は,x[2] と y[2] が同じオブジェクトを指しているため,x[2] の値も変化する.
      01	# -*- coding: UTF-8 -*-
      02	import copy
      03	
      04	class Example :
      05	    def __init__(self, x) :
      06	        self.x = x
      07	
      08	x      = [Example(1), Example(2), Example(3)]
      09	y      = copy.copy(x)
      10	y[1]   = Example(4)
      11	y[2].x = 5
      12	print(x[0].x, x[1].x, x[2].x)   # 1 2 5
      13	print(y[0].x, y[1].x, y[2].x)   # 1 4 5
      				
        以上の問題を避けるためには,オブジェクト内に存在するオブジェクトに対しても,浅いコピーと同じ処理を行ってやる必要がある.それが,深いコピーである.以下に示す図は,2 次元配列に対するイメージである.
      01	# -*- coding: UTF-8 -*-
      02	import copy
      03	
      04	class Example :
      05	    def __init__(self, x) :
      06	        self.x = x
      07	
      08	x = [[1, 2, 3], [4, 5, 6]]
      09	y = copy.deepcopy(x)
      10	y[0][0] = 10
      11	print(x, y)   # [[1, 2, 3], [4, 5, 6]] [[10, 2, 3], [4, 5, 6]]
      12	
      13	x      = [Example(1), Example(2), Example(3)]
      14	y      = copy.deepcopy(x)
      15	y[1]   = Example(4)
      16	y[2].x = 5
      17	print(x[0].x, x[1].x, x[2].x)   # 1 2 3
      18	print(y[0].x, y[1].x, y[2].x)   # 1 4 5
      				

  3. 日付と時間

    1. timedelta オブジェクト

      class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

        timedelta オブジェクトは,2 つの日付や時刻間の差を表し,オブジェクト同士または整数や実数との演算が可能です.例えば,下の例に示すように,10 日後は何日になるかを知りたいような場合に使用できます.全ての引数はオプションであり,デフォルト値は 0 です.なお,読み取り専用のインスタンス変数 days ( [-999999999, 999999999] ),seconds ( [0, 86399] ),microseconds ( [0, 999999 ] )を使用可能です.
      >>> from datetime import *
      >>> x = timedelta(days = 10)
      >>> x.days
      10
      >>> date.today() + x   # 今日から 10 日後は何日か?
      datetime.date(2016, 9, 1)				

    2. date オブジェクト

      class datetime.date(year, month, day)

        date オブジェクトは日付(年,月,日)を表し,timedelta オブジェクトとの加減,及び,date オブジェクト同士の減算が可能です.全ての引数が必須であり,MINYEAR <= year <= MAXYEAR を満たす必要があります.なお,読み取り専用のインスタンス変数 year,month,day を使用可能です.
      >>> from datetime import *
      >>> date(2020, 9, 1) - date(2016, 9, 1)
      datetime.timedelta(1461)   # 2020/9/1 は 2016/9/1 から 1461 日目				
        以下に示すようなクラスメソッド,及び,インスタンスメソッドを利用できます.

        • fromordinal : 西暦 1 年 1 月 1 日を 1 とした序数に対応する日付
        • today : 現在のローカルな日付
        • isocalendar : 3 要素のタプル( ISO 年,ISO 週番号,ISO 曜日)
        • isoformat : 'YYYY-MM-DD' の日付
        • isoweekday : 曜日を整数
        • replace : パラメータの値が置き換えられた date オブジェクト
        • toordinal : 与えられた date オブジェクトの日付序数
        • weekday : 曜日を整数

      • classmethod date.fromordinal(ordinal)

          西暦 1 年 1 月 1 日を 1 とした序数に対応する日付を返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x
        datetime.date(2016, 8, 22)   # 今日は,2016/8/22
        >>> x.toordinal()
        736198   # 1/1/1 から 736198 日目
        >>> date.fromordinal(736198)
        datetime.date(2016, 8, 22)   # 1/1/1 から 736198 日目は,2016/8/22					

      • classmethod date.today()

          現在のローカルな日付を返す.
        >>> from datetime import *
        >>> date.today()
        datetime.date(2016, 8, 22)   # 今日は,2016/8/22					

      • date.isocalendar()

          3 要素のタプル( ISO 年,ISO 週番号,ISO 曜日)を返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x.isocalendar()
        (2016, 34, 1)
        >>> x.isoformat()
        '2016-08-22'					

      • date.isoformat()

          ISO 8601 形式,'YYYY-MM-DD' の日付を表す文字列を返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x.isocalendar()
        (2016, 34, 1)
        >>> x.isoformat()
        '2016-08-22'					

      • date.isoweekday()

          月曜日を 1,日曜日を 7 として,曜日を整数で返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x.weekday()
        0
        >>> x.isoweekday()
        1					

      • date.replace(year, month, day)

          キーワード引数で指定されたパラメータの値が置き換えられた date オブジェクトを返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x
        datetime.date(2016, 8, 22)
        >>> x.replace(month = 9)
        datetime.date(2016, 9, 22)					

      • date.toordinal()

          西暦 1 年の 1 月 1 日を序数 1 とした時,与えられた date オブジェクトの日付序数を返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x
        datetime.date(2016, 8, 22)   # 今日は,2016/8/22
        >>> x.toordinal()
        736198   # 1/1/1 から 736198 日目
        >>> date.fromordinal(736198)
        datetime.date(2016, 8, 22)   # 1/1/1 から 736198 日目は,2016/8/22					

      • date.weekday()

          月曜日を 0,日曜日を 6 として,曜日を整数で返す.
        >>> from datetime import *
        >>> x = date.today()
        >>> x.weekday()
        0
        >>> x.isoweekday()
        1					

    3. time オブジェクト

      class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

        time オブジェクトは時刻を表現し,全ての引数はオプションです.time オブジェクト間の四則演算はサポートされていません.なお,読み取り専用のインスタンス変数 hour,minute,second,microsecond,tzinfo を使用可能です.
      >>> from datetime import *
      >>> x = time(minute = 10)
      >>> x
      datetime.time(0, 10)
      >>> x.minute
      10				
        以下に示すようなインスタンスメソッドを利用できます.

        • isoformat : HH:MM:SS.mmmmmm
        • replace : キーワード引数で指定した値だけを変更した time オブジェクト

      • time.isoformat()

          時刻を ISO 8601 形式,すなわち,HH:MM:SS.mmmmmm,または,microsecond が 0 の場合には HH:MM:SS で表した文字列を返す.
        >>> from datetime import *
        >>> time(hour = 12, minute = 25).isoformat()
        '12:25:00'					

      • time.replace(hour, minute, second, microsecond, tzinfo)

          キーワード引数で指定した値だけを変更した time オブジェクトを返す.
        >>> from datetime import *
        >>> x = time(hour = 12, minute = 25)
        >>> x.replace(minute = 20)
        datetime.time(12, 20)					

    4. datetime オブジェクト

      class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

        datetime オブジェクトは,date オブジェクト,および,time オブジェクトの全ての情報が入っている単一のオブジェクトです.timedelta オブジェクトとの加減,及び,datetime オブジェクト同士の減算が可能です.年月日に対する引数は必須であり,MINYEAR <= year <= MAXYEAR を満たす必要があります.なお,読み取り専用のインスタンス変数 year,month,day,hour,minute,second,microsecond,tzinfo を使用可能です.
      >>> from datetime import *
      >>> datetime(2020, 9, 1, 12) - datetime(2016, 9, 1, 9)   # 2020/9/1 12:00 - 2016/9/1 09:00
      datetime.timedelta(1461, 10800)   # 1461 日 10800 秒				
        以下に示すようなクラスメソッド,及び,インスタンスメソッドを利用でます.

        • combine : date オブジェクトと time オブジェクトとの合成
        • fromordinal : 西暦 1 年 1 月 1 日を 1 とした序数に対応する日付
        • now : 現在のローカルな日付
        • today : 現在のローカルな日付
        • date : datetime オブジェクトと同じ年,月,日の date オブジェクト
        • isocalendar : 3 要素のタプル( ISO 年,ISO 週番号,ISO 曜日)
        • isoformat : YYYY-MM-DDTHH:MM:SS.mmmmmm
        • isoweekday : 曜日を整数
        • replace : パラメータの値が置き換えられた datetime オブジェクト
        • time : datetime オブジェクトと同じ時,分,秒,マイクロ秒を持つ time オブジェクト
        • toordinal : datetime オブジェクトの日付序数
        • weekday : 曜日を整数

      • classmethod datetime.combine ( date, time )

          日付部分が date オブジェクトと等しく,時刻部分が tzinfo 属性が与えられた time オブジェクトと等しい,datetime オブジェクトを返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        >>> d = x.date()
        >>> d
        datetime.date(2016, 8, 22)
        >>> t = x.time()
        >>> t
        datetime.time(19, 36, 42, 936212)
        >>> datetime.combine(d, t)
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        					

      • classmethod datetime.fromordinal ( ordinal )

          西暦 1 年 1 月 1 日を 1 とした序数に対応する日付を返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 22, 19, 18, 28, 535617)   # 今日は,2016/8/22
        >>> x.toordinal()
        736198   # 1/1/1 から 736198 日目
        >>> datetime.fromordinal(736198)
        datetime.datetime(2016, 8, 22, 0, 0)   # 1/1/1 から 736198 日目は,2016/8/22					

      • classmethod datetime.now ( tz = None )

          現在のローカルな日付を返す.
        >>> from datetime import *
        >>> datetime.today()
        datetime.datetime(2016, 8, 22, 19, 6, 20, 160684)
        >>> datetime.now()
        datetime.datetime(2016, 8, 22, 19, 6, 37, 611325)   # 今日は,2016/8/22 19:06:37.611325					

      • classmethod datetime.today()

          現在のローカルな日付を返す.
        >>> from datetime import *
        >>> datetime.today()
        datetime.datetime(2016, 8, 22, 19, 6, 20, 160684)
        >>> datetime.now()
        datetime.datetime(2016, 8, 22, 19, 6, 37, 611325)   # 今日は,2016/8/22 19:06:37.611325					

      • datetime.date()

          datetime オブジェクトと同じ年,月,日の date オブジェクトを返す.
        >>> x = datetime.today()
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        >>> d = x.date()
        >>> d
        datetime.date(2016, 8, 22)
        >>> t = x.time()
        >>> t
        datetime.time(19, 36, 42, 936212)
        >>> datetime.combine(d, t)
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        					

      • datetime.isocalendar()

          3 要素のタプル( ISO 年,ISO 週番号,ISO 曜日)を返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x.isocalendar()
        (2016, 34, 1)
        >>> x.isoformat()
        '2016-08-23T06:43:29.308330'					

      • datetime.isoformat()

          日付と時刻を ISO 8601 形式,すなわち,YYYY-MM-DDTHH:MM:SS.mmmmmm か,または,microsecond が 0 の場合には YYYY-MM-DDTHH:MM:SS で表した文字列を返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x.isocalendar()
        (2016, 34, 1)
        >>> x.isoformat()
        '2016-08-23T06:43:29.308330'					

      • datetime.isoweekday()

          月曜日を 1,日曜日を 7 として,曜日を整数で返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x.weekday()
        0
        >>> x.isoweekday()
        1					

      • datetime.replace(year, month, day, hour, minute, second, microsecond, tzinfo)

          キーワード引数で指定されたパラメータの値が置き換えられた datetime オブジェクトを返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 23, 6, 43, 29, 308330)
        >>> x.replace(day = 1)
        datetime.datetime(2016, 8, 1, 6, 43, 29, 308330)					

      • datetime.time()

          datetime オブジェクトと同じ時,分,秒,マイクロ秒を持つ time オブジェクトを返す.
        >>> x = datetime.today()
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        >>> d = x.date()
        >>> d
        datetime.date(2016, 8, 22)
        >>> t = x.time()
        >>> t
        datetime.time(19, 36, 42, 936212)
        >>> datetime.combine(d, t)
        datetime.datetime(2016, 8, 22, 19, 36, 42, 936212)
        					

      • datetime.toordinal()

          西暦 1 年の 1 月 1 日を序数 1 とした時,与えられた datetime オブジェクトの日付序数を返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x
        datetime.datetime(2016, 8, 22, 19, 18, 28, 535617)   # 今日は,2016/8/22
        >>> x.toordinal()
        736198   # 1/1/1 から 736198 日目
        >>> datetime.fromordinal(736198)
        datetime.datetime(2016, 8, 22, 0, 0)   # 1/1/1 から 736198 日目は,2016/8/22					

      • datetime.weekday()

          月曜日を 0,日曜日を 6 として,曜日を整数で返す.
        >>> from datetime import *
        >>> x = datetime.today()
        >>> x.weekday()
        0
        >>> x.isoweekday()
        1					

  4. 数値配列

      array モジュールでは,基本的な値(文字( bytes 型),整数,浮動小数点数)の配列をコンパクトに表現できるオブジェクト型を定義しています.array はシーケンス型であり,要素の型に制限があることを除けば,リストとまったく同じように振る舞います.C++ 標準ライブラリ内にある array クラスと似ています(要素の型を,文字,整数,または,浮動小数点数とした場合).array クラスと同様,オブジェクト生成時に要素の型を指定します( 1 文字の型コードを使用).ただし,array モジュールでは,リストと同じように,要素の追加等を行えますが,array クラスでは,C/C++ における通常の配列と同様,宣言時に大きさが決まってしまいます.

      array オブジェクトは,次のメソッドによって生成できます.
    class array.array(typecode[, initializer])			
    ここで,typecode は要素のデータ型initializer初期値を表します.initializer は,リスト,bytes-like object,または,適当な型のイテレーション可能オブジェクトでなければなりません.また,
    array.typecodes   # クラス変数			
    によって,利用可能なすべてのタイプコードを知ることができます.
    >>> array("i", [1, 2, 3])
    array('i', [1, 2, 3])
    >>> typecodes
    'bBuhHiIlLqQfd'			
      また,以下に示すような方法において,多次元配列を生成することも可能です(下の例は,2 行 3 列).
    >>> A = [array("i", [1, 2, 3]), array("i", [4, 5, 6])]
    >>> A[0][2]
    3			
      以下,array 型において利用可能なメソッド等を示します.

      • append : 要素を追加
      • count : 出現回数
      • extend : 要素の追加
      • frombytes : bytes 型 s から要素を追加
      • fromfile : ファイルオブジェクト f から要素を追加
      • fromlist : リストから要素を追加
      • index : 探索
      • insert : 挿入
      • itemsize : 要素のバイト長
      • pop : 要素を取り出し,削除
      • remove : 要素の削除
      • reverse : 要素の順番を逆転
      • tobytes : bytes 型に変換
      • tofile : ファイルオブジェクト f に書き込む
      • tolist : リストに変換
      • typecode : 要素のデータ型

    • array.typecode : インスタンス変数

        要素のデータ型

    • array.itemsize : インスタンス変数

        要素のバイト長
      >>> from array import *
      >>> a = array("i", [1, 2, 3])
      >>> a.typecode
      'i'
      >>> a.itemsize
      4				

    • array.append(x)

        x を配列の末尾に追加
      >>> from array import *
      >>> a = array("i", [1, 2, 3])
      >>> a.append(0)
      >>> a
      array('i', [1, 2, 3, 0])				

    • array.count(x)

        要素 x の出現回数
      >>> from array import *
      >>> a = array("i", [1, 2, 1])
      >>> a.count(1)
      2				

    • array.extend(iterable)

        iterable から要素を取り出し,配列の末尾に要素を追加
      >>> from array import *
      >>> a = array("i", [1, 2, 3])
      >>> a.extend([4, 5, 6])
      >>> a
      array('i', [1, 2, 3, 4, 5, 6])				

    • array.frombytes(s)

        bytes 型 s から要素を追加

    • array.tobytes()

        bytes 型に変換
      >>> from array import *
      >>> a = array("b", b"abc")
      >>> a.frombytes(b"efg")
      >>> a
      array('b', [97, 98, 99, 101, 102, 103])
      >>> a.tobytes()
      b'abcefg'				

    • array.fromfile(f, n)

        ファイルオブジェクト f から n 個の要素を読み出し,配列の末尾にそれらの要素を追加

    • array.tofile(f)

        すべての要素をファイルオブジェクト f に書き込む
      >>> from array import *
      >>> a = array("d", [1.05, 2.25, 3.50])
      >>> f = open("test.txt", "bw")
      >>> a.tofile(f)
      >>> f.close()
      >>> f = open("test.txt", "br")
      >>> b = array("d", [10, 20])
      >>> b.fromfile(f, 3)
      >>> f.close()
      >>> b
      array('d', [10.0, 20.0, 1.05, 2.25, 3.5])
      				

    • array.fromlist(list)

        リストから要素を追加

    • array.tolist()

        配列と同じ要素を持つリストに変換
      >>> from array import *
      >>> a = array("i", [1, 2, 3])
      >>> a.fromlist([4, 5])
      >>> a
      array('i', [1, 2, 3, 4, 5])
      >>> a.tolist()
      [1, 2, 3, 4, 5]				

    • array.index(x)

        配列中に x が出現する添え字のうち最小の値を返す
      >>> from array import *
      >>> a = array("i", [1, 2, 3, 2, 5])
      >>> a.index(2)
      1				

    • array.insert(i, x)

        配列中の添え字 i の前に x を挿入.i の値が負の場合,配列の末尾からの相対位置として扱う.
      >>> from array import *
      >>> a = array("i", [1, 2, 3])
      >>> a.insert(1, 10)
      >>> a
      array('i', [1, 10, 2, 3])				

    • array.pop([i])

        配列から添え字が i の要素を取り除いて返す.i が省略された場合は,最後の要素を対象とする.
      >>> from array import *
      >>> a = array("i", [1, 2, 3, 2, 5])
      >>> k = a.pop(1)
      >>> k, a
      (2, array('i', [1, 3, 2, 5]))
      >>> k = a.pop()
      >>> k, a
      (5, array('i', [1, 3, 2]))				

    • array.remove(x)

        配列から,最初に現れた要素 x を削除.
      >>> from array import *
      >>> a = array("i", [1, 2, 3, 2, 5])
      >>> a.remove(2)
      >>> a
      array('i', [1, 3, 2, 5])				

    • array.reverse()

        要素の順番を逆転.
      >>> from array import *
      >>> a = array("i", [1, 2, 3, 4, 5])
      >>> a.reverse()
      >>> a
      array('i', [5, 4, 3, 2, 1])				

情報学部 菅沼ホーム 目次 索引