【Python】【book】「みんなのPython第4版」の学習記録

下記の「みんなのPython 第4版」を使った学習記録のページです。
本ページのプログラムは「みんなのPython 第4版」をもとにして作成したものも多数あります。
なお、私による「みんなのPython 第4版」の書評はこちらです。

みんなのPython 第4版

みんなのPython 第4版


みんなのPython 第4版 目次

Chapter 01 プログラミング言語Python
  01 Pythonの魅力
  02 Python(Anaconda)の入手とインストール
  03 インタラクティブシェル(対話型シェル)を使う
  04 ファイルにPythonのプログラムを書く
  05 Jupyter Notebookを使う
Chapter 02 Pythonでプログラミングをはじめよう
  01 数値を使う
  02 変数を使う
  03 文字列を使う
  04 リストを使う
   convert_number.py
  05 for文でループを使う
   month_tuple.py
   JanKenPon.py
  06 if文で条件分岐をする
  07 関数を使う
  08 モジュールを使う
   ramdom_1.py
   ramdom_2.py
Chapter 03 Pythonの基礎をマスターする
  01 ディクショナリ(辞書)を使う
   purple_dict.py
   convert_number.py
   int2str_str2int.py
  02 set(集合)を使う
   logical_operation_by_set.py
  03 タプルを使う
   month_tuple.py
   tuple_dict.py
  04 if文の応用
   lt_le_gt_ge.py
  05 ループの応用
  06 関数の応用
   int2str_str2int.py
Chapter 04 組み込み型を使いこなす
  01 オブジェクトとしての組み込み型
  02 数値型を操作する
   int2str_str2int.py
  03 文字列型を使いこなす
   s_split.py
   s_join.py
   format_1.py
   format_2.py
   format_3.py
  04 リスト型,タプル型を使いこなす
   list_sort.py
   slice_1.py
   dict_update.py
  05 set型を使いこなす
  06 ディクショナリ型を使いこなす
  07 if文と組み込み型
  08 for文と組み込み型
   zip.py
  09 関数と組み込み型
   args.py
   kwargs.py
  10 Pythonの文字列と日本語
  11 Pythonのファイル処理
Chapter 05 関数型プログラミング
  01 関数型プログラミングとは何か
   purple_dict.py
  02 内包表記(コンプリヘンション)
   s_split_comprehension.py
   s_swapping_comprehension.py
   list_sort_lambda.py
  03 イテレータを使う
  04 ジェネレータを使う
  05 高階関数とデコレータ
   callback.py
Chapter 06 クラスとオブジェクト指向開発
  01 Pythonでクラスを使う
  02 クラスを作る
   callback.py
   Prism.py
Chapter 07 クラスの継承と高度なオブジェクト指向機能
  01 クラスを継承する
   Cube.py
   Cube_super.py
   Klass_slots.py
   Prop.py
  02 特殊メソッドを利用する
   strdict.py
  03 組み込み型を継承する
Chapter 8 モジュール
  01 モジュールファイルを作る
   invoke_module_1.py
   invoke_module_2.py
  02 モジュールの階層構造(パッケージ)
  03 モジュールを利用する際の注意点
  04 サードパーティーのモジュールを使う
Chapter 9 スコープとオブジェクト
  01 名前空間,スコープ
  02 純粋オブジェクト指向言語としてのPython
   dir.py
   type_instance.py
   getattr.py
Chapter 10 例外処理
  01 Pythonの例外処理
   purple_dict.py
   filelen.py
   with_cat_n.py
   dir.py
  02 良く起こるエラーや例外と対策
   purple_dict.py
   raise.py
   OrderedDict.py
Chapter 11 標準ライブラリを使う
  01 標準ライブラリのインポート
   dir.py
  02 データ構造
   OrderedDict.py
   tuple2dict_1.py
   tuple2dict_2.py
   tuple2dict_3.py
  03 日時データの扱い「datetime,calendar」
   OrderedDict.py
  04 正規表現「re」
  05 システムパラメータを取得,操作する「sys」
   filelen.py
   with_cat_n.py
  06 ファイル,プロセスなどOS依存の情報を取得,操作する「os」
   OrderedDict.py
  07 数学関数を利用する「math」「random」
  08 インターネット上のデータを取得する「urllib」
  09 文字列ベースのバーチャルなファイルを作る「io.StringIO」
  10 CSV(カンマ区切り)ファイルの操作「csv」
  11 オブジェクトの永続化とシリアライズ「shelve」「pickle」
  12 JSONデータを扱う「json」
Chapter 12 Pythonとデータサイエンス
  01 NumPyとmatplotlib
  02 NumPyを使う
  03 matplotlibを使う
  04 日本の人口を可視化する
  05 Pythonと機械学習
Chapter 13 Python2
  01 Python3とPython2の違い
  02 Python2から3への移行方法
  03 おわりに

 

作成したプログラムについて

以下、書籍のプログラムをマネしつつ、少しアレンジを加えて作成してみた。

purple_dict.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""

import  traceback

# 辞書の定義
purple = {"ニックネーム"     : "れにちゃん",
          "出身地"           : "神奈川県",
          "キャッチフレーズ" : "感電少女" }

# キーを使って要素を取り出す(P115)
print(purple["出身地"]) #=> 神奈川県

# 辞書の中身を全表示
#=> {'出身地': '神奈川県', 'キャッチフレーズ': '感電少女', 'ニックネーム': 'れにちゃん'}
print(purple)

# 値の変更
#=> {'キャッチフレーズ': '鋼少女', 'ニックネーム': 'れにちゃん', '出身地': '神奈川県'}
purple["キャッチフレーズ"] = "鋼少女"
print(purple)

# 要素の追加
#=> {'ニックネーム': 'れにちゃん', '出身地': '神奈川県', 'キャッチフレーズ': '鋼少女', '生年月日': '1993年6月21日'}
purple["生年月日"] = "1993年6月21日"
print(purple)

# 要素の削除
#=> {'生年月日': '1993年6月21日', 'キャッチフレーズ': '鋼少女', '出身地': '神奈川県'}
del purple["ニックネーム"]
print(purple)

# 存在しないキーでアクセスする
#=> KeyError: '性別' が発生する
try:
    print(purple["性別"])
except:
    ex = traceback.print_exc()
    print('エラー原因は{e}です'.format(e=ex))
finally:
    pass


# キーの存在確認をする
def is_key_exist( keyword ):
    for key in purple:
        if keyword == key:
            return purple[key]
    return  "見つかりませんでした"

# 存在確認したいキーの一覧は読み取り専用にする
keys = ( "性別", "生年月日" )

for key in keys:
    ret = is_key_exist(key)
    print('キーワード"{k}"に対応する値 => {r}'.format(k=key, r=ret))

 

convert_number.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
def convert_number(num):
    # アラビア数字とローマ数字の対応表を辞書に定義する
    roman_nums = {1:"Ⅰ", 2:"Ⅱ", 3:"Ⅲ", 4:"Ⅳ", 5:"Ⅴ",
                  6:"Ⅵ", 7:"Ⅶ", 8:"Ⅷ", 9:"Ⅸ"}
    # キーが存在するかを in で調べる
    if num in roman_nums:
        return roman_nums[num]
    else:
        return "変換不可です"
        

nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]

if __name__ == '__main__':
    for i in nums:
        print(i, convert_number(i))

 

logical_operation_by_set.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版 (P126)
set には数値や文字列を要素として設定することが可能である。
一方で要素が変化するリストや辞書は設定することができない。
"""
def set_union( a: "set型の引数",
               b: "set型の引数" ) -> "戻り値: 和集合≒ORの結果" :
    return ( a | b )

def set_differ( a: "set型の引数",
                b: "set型の引数" ) -> "戻り値: 差集合" :
    return ( a - b )

def set_and( a: "set型の引数",
             b: "set型の引数" ) -> "戻り値: 交わり≒ ANDの結果" :
    return ( a & b )

def set_xor( a: "set型の引数",
             b: "set型の引数" ) -> "戻り値: 対象差=排他論理和=XOR の結果" :
    return ( a ^ b )

def conv_list_2_set( codon: "リスト" ) -> "戻り値: set(集合)" :
    return set(codon)

if __name__ == '__main__':

    # 和集合を得る
    prime = { 2, 3, 5, 7, 13, 17 }   # 素数
    fib   = { 1, 1, 2, 3, 5, 8, 13 } # フィボナッチ数
    print(set_union( prime, fib ))
    print( set_union.__annotations__ )
    #=> {1, 2, 3, 5, 7, 8, 13, 17}

    # 差集合を得る
    dice = { 1, 2, 3, 4, 5, 6 } # サイコロの目
    even = { 2, 4, 6, 8, 10 }   # 偶数
    print(set_differ( dice, even ))
    print( set_differ.__annotations__ )
    #=> {1, 3, 5}

    # 論理和を得る
    prefs = { "北海道", "青森", "秋田", "岩手" }    # 都道府県
    capital = { "札幌", "青森", "秋田", "盛岡" }    # 県庁所在地
    print(set_and( prefs, capital ))
    print( set_and.__annotations__ )
    #=> {'秋田', '青森'}

    # 対象差を得る
    print(set_xor( prefs, capital ))
    print( set_xor.__annotations__ )
    #=> {'北海道', '岩手', '盛岡', '札幌'}

    # リストを set に変換する
    codon = [ 'ATG', 'GGC', 'TCC', 'AAG', 'TTC', 'TGG', 'GAC', 'TCC' ]
    s_codon = conv_list_2_set( codon )
    print( s_codon ) #=> {'TTC', 'TGG', 'GAC', 'ATG', 'AAG', 'GGC', 'TCC'}
    print( len(codon), len(s_codon) ) #=> 8 7

    # 要素の検索と set の比較
    prime_fib = set_and(prime, fib) # 2つの交わり(AND)を得る
    values    = { 2, 3, 4, 5, 6, 7, 8, 9, 10,
                    11, 12, 13, 14, 15, 16, 17, 18 }
    normal    = set_differ(set_differ( values, prime ), fib) # 非素数・非フィボナッチ
    for value in values:
        if value in prime_fib:
            print("{0}は素数であり、かつフィボナッチ数でもある".format(value))
        elif value in prime:
            print("{0}は素数である".format(value))
        elif value in normal:
            print("{0}".format(value))

 

month_tuple.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
- タプルは要素の変更ができない (リストと異なる点)
-- month_names[0] = "hoge" が不可ということ
- 要素の重複は許される (set と異なる点)
"""

def print_tuple( t, start:int=1 ):
    for i, val in enumerate( t, start ):
        print( i, val )

month_names = ( "January", "February", "March", "April",
                "May", "June", "July" )

if __name__ == '__main__':
    print_tuple( month_names )

    # タプルの連結は可能
    month_names = month_names + ("August", "September", "October",
                                    "November", "December" )
    print_tuple( month_names )

 

tuple_dict.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
- タプルを辞書のキーとして使うプログラム
-- 緯度と経度をキーにしている。
"""

def search_capitals( loc        : "調べたい緯度・軽度のタプル",
                     isNearMode : "近い所在地を調べるモードか否か" =False ) -> "戻り値 該当する所在地名" :
    capital  = "該当する県庁所在地がありません"
    pref_capitals = {(43.06417, 141.34694) : "北海道(札幌)  ",
                     (40.82444, 140.74   ) : "青森県(青森市)",
                     (39.70361, 141.1525 ) : "岩手県(盛岡市)" }
    if( isNearMode != True ):
        for key in pref_capitals:
            if loc == key:
                capital = (pref_capitals[key])
                break
    else:
        nearest_dist = 10000
        for key in pref_capitals:
            dist = (loc[0]-key[0])**2 + (loc[1]-key[1])**2
        if nearest_dist > dist:
            nearest_dist = dist
            capital      = pref_capitals[key]

    return capital

if __name__ == '__main__':
    locs = [ (39.70361,  141.1525 ) , (41.768793, 140.72881) ]
    print(search_capitals(locs[0]))         #=> 岩手県(盛岡市)
    print(search_capitals(locs[1], True))   #=> 北海道(札幌)
    print(search_capitals.__annotations__)

 

lt_le_gt_ge.py

  • 「0 <= val < 5」 といった書き方ができる。
    • わざわざ 「 0<= val and val < 5 」といった書き方をしなくて良い。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
values = [ 0, 6, 10, 100 ]

for i, val in enumerate( values, start=0 ):
    if    0 <= val < 5:
        print("values[{i}]={v} ... [ 0 <= val <   5]".format(i=i, v=val))
    elif  5 <= val < 10:
        print("values[{i}]={v} ... [ 5 <= val <  10]".format(i=i, v=val))
    elif 10 <= val < 100:
        print("values[{i}]={v} ... [10 <= val < 100]".format(i=i, v=val))
    else:
        print("values[{i}]={v} ... [ else ]".format(i=i, v=val))

 

JanKenPon.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
from random import randint

hands = { 0:"グー", 1:"チョキ", 2:"パー" }
rules = {
        (0,0):"あいこ", (0,1):"勝ち",   (0,2):"負け",
        (1,0):"負け",   (1,1):"あいこ", (1,2):"勝ち",
        (2,0):"勝ち",   (2,1):"負け",   (2,2):"あいこ"
        }

while True:
    pc_hand = randint(0, 2) # 0<= x <=2 の値を得る
    user_hand_str = input("0:グー, 1:チョキ, 2:パー, 3:終了")
    if user_hand_str == "3":
        break
    if user_hand_str not in ("0", "1", "2"):    # 不正な数値が入力された場合
        continue
    user_hand = int(user_hand_str)
    print("(あなた, COM) = ( "+ hands[user_hand] + ", "+ hands[pc_hand] + " )" )
    print(rules[(user_hand, pc_hand)])

 

random_1.py

  • 「import モジュール名」による random モジュール取り込みパターン。
  • 「from モジュール名 import 関数名」については random_2.py を参照。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
import random

print(random.random())      # 0 < x < 1 の乱数を得る
print(random.randint(0,6))  # 0 <= x <= 6 の乱数を得る

a_list = [0, 1, 2, 3, 4, 5]
random.shuffle(a_list)      # リストをランダムに並び替える
print(a_list)
print(random.choice(a_list))# リストの要素を1つランダムに選ぶ

 

random_2.py

  • random_1.py とは異なり、「from モジュール名 import 関数名」による random モジュール取り込みパターン。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
from random import random
from random import randint
from random import shuffle
from random import choice

print(random())      # 0 < x < 1 の乱数を得る
print(randint(0,6))  # 0 <= x <= 6 の乱数を得る

a_list = [0, 1, 2, 3, 4, 5]
shuffle(a_list)      # リストをランダムに並び替える
print(a_list)
print(choice(a_list))# リストの要素を1つランダムに選ぶ

 

int2str_str2int.py

  • 文字列→ 数値 へは int() を使う
2進数文字列の場合 int("0b111", 2)
8進数文字列の場合 int("0o123", 8)
10進数文字列の場合 int("123", 10)
16進数文字列の場合 int("0x10", 16)
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""

# 2進数、8進数、10進数、16進数の各値を文字列で保持した辞書
strval_list = { "bin":"0b1111111111", "oct":"0o1777", "dec":"1023", "hex":"0x3ff" }

# 2進数、8進数、10進数、16進数の各値を整数値で保持した辞書
intval_list = { "bin":0b1111111111, "oct":0o1777, "dec":1023, "hex":0x3fff }

def int2str( value: "値", base: "基底" ) -> "戻り値: 文字列" :
    if   base in { 'b', 'bin' }:
        func=bin
    elif base in { 'o', 'oct' }:
        func=oct
    elif base in { 'd', 'dec' }:
        func=int
    elif base in { 'h', 'hex' }:
        func=hex
    else:
        func=None

    if func != None:
        return func(value)
    else:
        print('Error: invalid base("{0}")'.format(base))
        return 0

def str2int( val_str: "文字列", base: "基底" ) -> "戻り値: 整数値" :
    if   base in { 'b', 'bin' }:
        base = 2
    elif base in { 'o', 'oct' }:
        base = 8
    elif base in { 'd', 'dec' }:
        base = 10
    elif base in { 'h', 'hex' }:
        base = 16
    else:
        base = -1

    if base != -1:
        return int(val_str, base)
    else:
        print('Error: invalid base("{0}")'.format(base))
        return 0


if __name__ == '__main__':
    print("文字列から整数への変換を行います")
    for k, s in strval_list.items():
        retval = 0
        #print(str2int.__annotations__)
        retval = str2int( val_str=s, base=k )
        print("{s} ==> str => int ==> 10進数 {ret}".format(s=s, ret=retval))

    print("整数から文字列への変換を行います")
    for k, v in intval_list.items():
        retstr = ""
        retstr = int2str( value=v, base=k )
        print("{val} ==> int => str ==> '{ret}'".format(val=v, ret=retval))

 

s_split_join.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
# -*- coding: utf-8 -*- 
"""

str_names  = "IV号戦車 LT-38 八九式中戦車 III号突撃砲 M3中戦車" # 戦車名
str_speeds = "38 42 20 40 39"   # 戦車の速度(km/h) ...連続した文字列
str_armor = "80 50 17 50 51"    # 戦車の装甲厚(mm) ...連続した文字列

# まずは戦車の名称を空白単位で分割する。文字列型へのポインタ配列となる。
names = str_names.split(" ")
# 次に戦車の名称をカンマ区切りにする。
chunk_name = ",".join(names)
print("戦車名: ", chunk_name)

# 戦車の速度をカンマ区切りにする。文字列型へのポインタ配列となる。
speeds = str_speeds.split(" ") 
chunk_speeds = ",".join(speeds)
print("走行速度km/h: ", chunk_speeds)

## 装甲厚をカンマ区切りにする。文字列型へのポインタ配列となる。
armors = str_armor.split(" ")   
chunk_armor = ",".join(armors)
print("装甲厚mm: ", chunk_armor)

 

s_split_comprehension.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
str_speeds = "38 42 20 40 39"   # 戦車の速度(km/h) ...連続した文字列

# 戦車の速度をスペースで分割する。文字列型へのポインタ配列となる。
# 内包表記:speeds = str_speeds.split(" ") と同じことをしている↓
speeds = [int(s) for s in str_speeds.split()]
print(speeds)

 

s_swapping_comprehension.py

  • 辞書の内包表記 { キー:値 for 繰り返し変数 in シーケンス (if 条件式) }
  • 辞書の内包表記パターン
  • リストから辞書型を取り出し、小文字に変換するプログラム
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
d = {
        "A-1":"B-1",
        "A-2":"B-2",
        "A-3":"B-3",
        "A-4":"B-4"
    }

swapped = { v:k for k, v in d.items() }
print(swapped)

"""
以下のような結果になる。
        'B-2': 'A-2',
        'B-3': 'A-3',
        'B-4': 'A-4',
        'B-1': 'A-1'
"""


# リスト →  辞書型を行う
names = ["BOB", "burton", "dave", "bob"]    # リストを用意する
unames = {x.lower() for x in names}         # 小文字に変換し、かつ、set として扱う
print(unames)                               # set の結果を表示する
#=> {'burton', 'bob', 'dave'}

 

list_sort.py

  • sortメソッドには引数 key の指定が必須である。
    • ここでは値をそのまま返す key (関数) を設定している。
    • 単純な関数の場合は lambda で済ますことも可能。具体例は list_sort_lambda.py を参照。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
def faster( spd ):
    return spd

str_speeds = "38 42 20 ?? 40 ?? 39" 
speeds = [ int(s) for s in str_speeds.split() if s.isdigit() ]
print(speeds) #=> [38, 42, 20, 40, 39]

speeds.sort(key=faster, reverse=False)
print(speeds) #=> [20, 38, 39, 40, 42]

 

list_sort_lambda.py

  • sort() に関数を使うパターンは list_sort.py を参照
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
単純な式なら関数を作る必要は無く、lambda で済ますことができる。
"""
# [Verbose] # def faster( spd ):
# [Verbose] #     return spd

str_speeds = "38 42 20 ?? 40 ?? 39" 
speeds = [ int(s) for s in str_speeds.split() if s.isdigit() ]
print(speeds) #=> [38, 42, 20, 40, 39]

# [Verbose] # speeds.sort(key=faster, reverse=False)
speeds.sort(key = lambda spd: spd, reverse = False )
print(speeds) #=> [20, 38, 39, 40, 42]

# 正の整数に対して -1 を掛けて、強引に降順ソートをする場合
speeds.sort(key = lambda spd: -spd, reverse = False )
print(speeds) #=> [42, 40, 39, 38, 20]

 

callback.py

  • Python では(?)高階関数と呼ぶらしいが、いわゆるコールバック。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""

class CB:
    def __init__(self):
        pass

    def set_callback(self, func):
        self.fn = func

    def invoke_notify(self):
        self.notify()
        
    def notify(self):
        self.fn( "Booooooooooooom" )


def wakeup( mesg:str ):
    print("Wake Up: {0}".format(mesg))


if __name__ == '__main__':

    obj = CB()

    # コールバックを登録する
    obj.set_callback( wakeup )

    # 再度コールバックを呼び出す
    obj.invoke_notify()

format_1.py

  • フォーマットに文字列を差し込む
  • 複数を同時に差し込む
  • 数値で差し込み位置を指定する
  • オブジェクトのアトリビュートを表示する
  • キーで差し込み位置を指定する
  • 辞書で差し込み位置を指定する
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
#--------------------------------------------
# フォーマットに文字列を差し込む
#--------------------------------------------
s = "{} loves Python !".format('Guido')
print(s)    #=> Guido loves Python !

#--------------------------------------------
# 複数を同時に差し込む
#--------------------------------------------
#=> <a href="http://python.org">python.org</a>
#   <a href="http://pypy.org">pypy.org</a>
#   <a href="http://cython.org">cython.org</a>
linkstr = '<a href="{}">{}</a>'
for i in [  'http://python.org',
            'http://pypy.org',
            'http://cython.org',]:
    print( linkstr.format(i, i.replace('http://' , '')) )

#--------------------------------------------
# 数値で差し込み位置を指定する
#--------------------------------------------
s = "{0} {1} {0}".format('Spam', 'Ham')
print(s)    #=> Spam Ham Spam

#--------------------------------------------
# キーで差し込み位置を指定する
#--------------------------------------------
s = "{food1} {food2} {food1}".format(food1='Spam', food2='Ham')
print(s)    #=> Spam Ham Spam

#--------------------------------------------
# 辞書で差し込み位置を指定する
#--------------------------------------------
d = { 'name':'Guido', 'birthyear':1964 }
s = "{0[birthyear]} is {0[name]}'s birthyear.".format(d)
print(s)    #=> 1964 is Guido's birthyear.

#--------------------------------------------
# オブジェクトのアトリビュートを表示する
#--------------------------------------------
#=> Python version: 3.5.3 (default, Nov 23 2017, 11:34:05) 
#   [GCC 6.3.0 20170406]
import sys
s = "Python version: {0.version}".format(sys).replace("\n", 'v(^-^)v ')
print(s)

 

format_2.py

  • 寄せ(左、右、中央)を指定して差し込む
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
#--------------------------------------------
# 寄せを指定して差し込む
# (1つ目=桁数10、2つ目=右寄せ, 3つ目=中央で表示する)
#--------------------------------------------
#=> Spam            300
#=> Ham             200
tmpl = "{0:10} {1:>8} {2:^}"
list = []
list.append(tmpl.format('Spam', 300, 324))
list.append(tmpl.format('Ham',  200, 216))
for s in list:
    print(s)

del list[:] #=> 全要素を削除する

# ============================================
#「:」を使うことで書式制御が可能になる
# ============================================
#--------------------------------------------
# 2015年末の日本の就業人口比率(%)=(就業者数÷ 総人口(万人)× 100 
#--------------------------------------------
s = "{:.2%}".format(6381/12708) #=> 50.21% (下二桁まで表示する) 
print(s)

#--------------------------------------------
# 2015年末の日本の総人口を「,」を付与して表示する
#--------------------------------------------
s = "{:,}".format(127080000)
print(s)    #=> 127,080,000

#--------------------------------------------
# 数値に符号を付ける
#--------------------------------------------
list = [ 10, -20 ]
for i in list:
    x = "{:>+4}".format(i)  # + と - の両方、かつ、右寄せで表示する
    y = "{:>-4}".format(i)  # - のみ、かつ、右寄せで表示する
    z = "{:>-8}".format(i)  # - のみ、かつ、右寄せ8桁で表示する
    print("(x, y, z) = ({X}, {Y}, {Z})".format(X=x, Y=y, Z=z))

 

format_3.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
#--------------------------------------------
# 整数値を16進数表示する
# 
#--------------------------------------------
list = [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1023, 1024 ]

for i, v in enumerate( list, start=0 ):
    print("list[{idx}] => ".format(idx=i), end=" ")
    print("0x{v:x}".format(v=v), end=", ")  # 0x4 と表示する
    print("0x{v:>04x}".format(v=v))         # 0x0004 と表示する

 

slice_1.py

  • list[ 開始 : 終点 : 加算値 ] ということ。(C言語の for と同じ)
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
def length(data):
    print("length=>{0}".format(len(data)))

a = [1, 2, 3, 4, 5]
print(a)        #=> [1, 2, 3, 4, 5]

# a[1], a[2], a[3] を表示する
print(a[1:4])   #=> [   2, 3, 4   ]

# エラーにはならない
print(a[2:100]) #=> [      3, 4, 5]

# 2インクリメントする
print(a[::2])   #=> [1,    3,    5] 

# a[1], a[2] を入れ替える
a[2:4] = ['Three', 'Four']          
print(a)        #=> [1, 2, 'Three', 'Four', 5]
length(a)

# a[3] 以降すべての要素を削除する。配列長も 5 から 2 になる。
del a[2:]
print(a)    #=> [1, 2]
length(a)   #=> 2

 

zip.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# zip 関数は目印無しで Linux の join コマンドを使う感覚に近い

# 2つのリスト(タプル)の要素数が同じ場合
A=(  1,   2,   3,   4  )
B=( 'a', 'b', 'c', 'd' )

for a, b in zip( A, B ):
    print(a, b)

#=> 1 a
#   2 b
#   3 c
#   4 d

# 要素数が少ない方に合わせられる
X=[ 1,  2,  3,  4     ]
Y=['A','B','C','D','E']

for x, y in zip( X , Y ):
    print(x, y)
#=> 1 A
#   2 B
#   3 C
#   4 D

 

Prism.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# 角柱(Prism)に関するクラス

class Prism:
    def __init__(self, width, height, depth):
        self.width = width
        self.height = height
        self.depth = depth

    # 体積を求める
    def content(self):
        return self.width * self.height * self.depth


if __name__ == '__main__':

    p1 = Prism(10, 20, 30)
    print(p1.content())     #=> 体積を求める 6000

    p2 = Prism(50, 60, 70)
    print(p2.content())     #=> 体積を求める 210000

    # アトリビュートへのアクセス(Read)
    print(p1.height)        #=> 高さを取り出す 20
    print(p2.height)        #=> 高さを取り出す 60

    # アトリビュートへのアクセス(Write)
    p1.height = 40          #=> 高さを書き換える
    print(p1.content())     #=> 体積を求める 12000

 

Cube.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# 立方体(Cube)クラスを作成する。
# - Cube は角柱(Prism)クラスを継承する
# - 本ファイルと同階層に Prism.py を配置しているものとする
from Prism import *

class Cube(Prism):
    def __init__(self, length):
        self.width = self.height = self.depth = length

    # 体積を求める content メソッドは基底(Prism)クラスの content を呼び出す

if __name__ == '__main__':

    p1 = Cube(10)
    print(p1.content())     #=> 体積を求める 1000

    p2 = Cube(50)
    print(p2.content())     #=> 体積を求める 125000

    # アトリビュートへのアクセス(Read)
    print(p1.height)        #=> 高さを取り出す 10
    print(p2.height)        #=> 高さを取り出す 50

    # アトリビュートへのアクセス(Write)
    p1.height = 30          #=> 高さを書き換える
    print(p1.content())     #=> 体積を求める 3000

 

Cube_super.py

  • Prism クラスを継承し、かつ、__init__ は Prism::__init__ を使う
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# 立方体(Cube)クラスを作成する。
# - Cube は角柱(Prism)クラスを継承する
# - __init__ は Prism::__init__ を呼び出すように super() 関数を使う
# - 本ファイルと同階層に Prism.py を配置しているものとする
from Prism import *

class Cube(Prism):
    def __init__(self, length):
        super().__init__(length, length, length)

    # 体積を求める content メソッドは基底(Prism)クラスの content を呼び出す

if __name__ == '__main__':

    p1 = Cube(10)
    print(p1.content())     #=> 体積を求める 1000

    p2 = Cube(50)
    print(p2.content())     #=> 体積を求める 125000

    # アトリビュートへのアクセス(Read)
    print(p1.height)        #=> 高さを取り出す 10
    print(p2.height)        #=> 高さを取り出す 50

    # アトリビュートへのアクセス(Write)
    p1.height = 30          #=> 高さを書き換える
    print(p1.content())     #=> 体積を求める 3000

 

Klass_slots.py

  • __slots__ = ['foo' , 'bar'] のようにインスタンスの追加を制限する
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# クラスに __slots__ というアトリビュートを持たせることで
# アトリビュートの追加を制限することができる。

class Klass:
    __slots__ = ['a', 'b']  #=> アトリビュートを制限する
    def __init__(self):
        self.a = 1

if __name__ == '__main__':

    i = Klass()
    print(i.a)  #=> 1

    i.b = 2
    print(i.b)  #=> 2

    i.c = 3
    print(i.c)  #=> 以下のエラーになる
                #   Traceback (most recent call last):
                #     File "./Klass_slots.py", line 22, in <module>
                #       i.c = 3
                #   AttributeError: 'Klass' object has no attribute 'c'

 

Prop.py

  • property() を使って、アトリビュートに対するセッタ/ゲッタを定義する。
  • アトリビュートに対して代入や参照を行うとセッタ/ゲッタが自動的に呼び出される
  • property( ゲッタ [, セッタ ] )
    • property() の引数にはセッタとゲッタのメソッド名を渡す
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# クラスに property() 関数を定義して、アトリビュートに
# 対する Setter と Getter を定義する

class Prop:
    def __init__(self):
        self.__x = 0

    def getx(self):
        print(__class__, "[getx]")
        return self.__x

    def setx(self, x):
        print(__class__, "[setx] __x <- x({0})".format(x))
        self.__x = x

    x = property( getx, setx )


if __name__ == '__main__':

    i = Prop()
    print(i.x)
    
    i.x = 10
    print(i.x)

    i._Prop__x  = 20    #=> 強引にアトリビュートにアクセスする ( setx は使われない)
    print(i.x)

 

strdict.py

  • 特殊メソッド
    • 演算子を使った操作や、スライスなどを実行すると呼び出されるメソッドのこと
    • C++ でいうオペレータ関数のようなものかと思う
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# 辞書型を継承する

class StrDict(dict):
    def __init__(self):
        pass

    # 特殊メソッドをオーバライドする
    # key が文字列型以外ならば例外を発生する
    def __setitem__(self, key, value):
        if not isinstance( key, str ):
            raise ValueError("Key must be str or unicode.")

        # スーパクラスの特殊メソッド __setitem__ を呼び出してキーと値を設定する
        dict.__setitem__(self, key, value)


if __name__ == '__main__':

    d = StrDict()
    d["spam"] = 1
    d["ham"] = 2

    for k,v in d.items():
        print("{0} => {1}".format(k,v))

 

invoke_module_1.py

  • 前述の int2str_str2int.py をモジュールとして使う
  • import int2str_str2int として取り込む
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# int2str_str2int.py をモジュールとして取り込む
import int2str_str2int

# 2進数、8進数、10進数、16進数の各値を文字列で保持した辞書
strval_list = { "bin":"0b1111111111", "oct":"0o1777", "dec":"1023", "hex":"0x3ff" }

# 2進数、8進数、10進数、16進数の各値を整数値で保持した辞書
intval_list = { "bin":0b1111111111, "oct":0o1777, "dec":1023, "hex":0x3fff }

# 以下、処理内容は int2str_str2int.py と同じである
if __name__ == '__main__':
    print("文字列から整数への変換を行います")
    for k, s in strval_list.items():
        retval = 0
        #print(str2int.__annotations__)
        retval = int2str_str2int.str2int( val_str=s, base=k )
        print("{s} ==> str => int ==> 10進数 {ret}".format(s=s, ret=retval))

    print("整数から文字列への変換を行います")
    for k, v in intval_list.items():
        retstr = ""
        retstr = int2str_str2int.int2str( value=v, base=k )
        print("{val} ==> int => str ==> '{ret}'".format(val=v, ret=retval))

 

invoke_module_2.py

  • 前述の int2str_str2int.py をモジュールとして使う
  • from int2str_str2int import * として取り込むので、該当モジュールの呼び出し書式が短くて済む
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
# int2str_str2int.py をモジュールとして取り込むが、import 〜 ではなく
# from 〜 import 形式に変えると、対象モジュールの呼び出し形式が短くできる
# import int2str_str2int
from int2str_str2int import *

# 2進数、8進数、10進数、16進数の各値を文字列で保持した辞書
strval_list = { "bin":"0b1111111111", "oct":"0o1777", "dec":"1023", "hex":"0x3ff" }

# 2進数、8進数、10進数、16進数の各値を整数値で保持した辞書
intval_list = { "bin":0b1111111111, "oct":0o1777, "dec":1023, "hex":0x3fff }

# 以下、処理内容は int2str_str2int.py と同じである
if __name__ == '__main__':
    print("文字列から整数への変換を行います")
    for k, s in strval_list.items():
        retval = 0
        #print(str2int.__annotations__)
        #retval = int2str_str2int.str2int( val_str=s, base=k )  # import〜 の場合
        retval = str2int( val_str=s, base=k )                   # from 〜 import * の場合
        print("{s} ==> str => int ==> 10進数 {ret}".format(s=s, ret=retval))

    print("整数から文字列への変換を行います")
    for k, v in intval_list.items():
        retstr = ""
        #retstr = int2str_str2int.int2str( value=v, base=k )    # import〜 の場合
        retstr = int2str( value=v, base=k )                     # from 〜 import * の場合
        print("{val} ==> int => str ==> '{ret}'".format(val=v, ret=retval))

 

dir.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
from pprint import pprint   # dir() の表示を見易くする

# 辞書型を継承する

class StrDict(dict):
    def __init__(self):
        pass

    # 特殊メソッドをオーバライドする
    # key が文字列型以外ならば例外を発生する
    def __setitem__(self, key, value):
        if not isinstance( key, str ):
            raise ValueError("Key must be str or unicode.")

        # スーパクラスの特殊メソッド __setitem__ を呼び出してキーと値を設定する
        dict.__setitem__(self, key, value)


if __name__ == '__main__':

    d = StrDict()
    d["spam"] = 1
    d["ham"] = 2

    pprint(dir(d))  # アトリビュートを表示する

    def  hoge():    # 独自関数 hoge() を定義する
        print("hoge hoge hoge")

    d.msg_hoge = hoge

    pprint(dir(d))  # StrDict クラスに hoge() を呼び出す msg_hoge メソッドが追加される

 

type_instance.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
- type() を使って型を識別する例
"""
import sys

datas = {
            '数値'      : 1           ,
            '文字列'    : 'あいうえお',
            'バイト型'  : b"abcde"    ,
            'Raw型'     : r"a b c d e",
            'モジュール': sys         
        }

def tell_me_type( key, val ):
    t = type(val)
    print("「{v}」の型は「{t}」です".format(v=val,t=t))

def tell_me_instance( key, val ):
    if isinstance( val, int ):
        print("{0} は「int」型です".format(val))
    elif isinstance( val, bytes ):
        print("{0} は「bytes」型です".format(val))
    elif isinstance( val, str ):
        print("{0} は「str」型です".format(val))
    elif isinstance( val, object ):
        print("{0} は「object」型です".format(val))
    else:
        print("!!!! {0} の型は不明です !!!!".format(val))

if __name__ == '__main__':
    for k,v in datas.items():
        print("--------------------------------------------")
        print("{v}が{k}か否か判定する".format(k=k,v=v))
        print("--------------------------------------------")
        tell_me_type( k, v )
        tell_me_instance( k, v )
        #print("instance( {0} , {1} ) => {2}\n".format(v, i, isinstance( v, type(v) )))

 

getattr.py

  • オブジェクトからアトリビュートを取り出す
  • 関数もアトリビュートなので取り出すことができる(以下、例)
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
s = "abcde"

if __name__ == '__main__':

    # str型かチェックする
    if isinstance(s, str):
        print(getattr( s, "find"))
        # str::find() を使って "cd" を含むかチェックする
        print(s.find("cd")) #=> 2
        # getattr() を使って str::find() を呼び出す
        print( getattr( s, "find")("cd") ) #=> 2
||<        
 
** filelen.py

>|python|
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
import sys

if __name__ == '__main__':

    for fn in sys.argv[1:]:  # 配列の2番目以降を取り出す
        try:
            f = open(fn)
        except FileNotFoundError:
            print("{}というファイルは存在しません".format(fn))
        else:                           # 例外が発生しなかった場合
            try:
                print(fn,len(f.read())) # ファイル名とサイズを表示する
            finally:                    # 例外の有無に関係無く必ず通る
                f.close()               # ファイルをクローズする

 

with_cat_n.py

with を使って「cat -n ファイル」相当の処理をする。

  • with 文での例外処理
    • 下記の場合、ファイルが存在しなければ例外が発生して with 内部に入らない
  • with 文にはコンテキストマネージャに対応したオブジェクトを添えて書く
    • 下記の場合、ファイル型オブジェクトである f が該当する
  • with 文の終了処理ではコンテキストマネージャがリソースの後始末をしてくれる
    • 下記の場合、コンテキストマネージャが再度働いてファイルを閉じてくれる
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
import sys

if __name__ == '__main__':

    for fn in sys.argv[1:]:  # 配列の2番目以降を取り出す
        with open(fn) as f:
            for i, line in enumerate(f, start=1):
                print(i, line, end="")

 

raise.py

  • 例外各種を無理矢理発生させてみる
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
import traceback

ERRORS = {
            "ValueError"         : ValueError,
            "NameError"          : NameError,
            "AttributeError"     : AttributeError,
            "TypeError"          : TypeError,
            "IndexError"         : IndexError,
            "KeyError"           : KeyError,
            "ImportError"        : ImportError,
            "UnicodeDecodeError" : UnicodeDecodeError,
            "UnicodeEncodeError" : UnicodeEncodeError,
            "ZeroDivisionError"  : ZeroDivisionError,
         }

def  invoke_traceback_print_exc(e):
    print("Error with {0}. details=>{1}".format(e, traceback.print_exc()))
    #print("Error with {0}".format(e))

if __name__ == '__main__':

    for k,ex in ERRORS.items():
        print("------------ {} ------------".format(k))
        try:
            print("DEBUG: raise {}".format(k))
            raise ex(k)
        except ValueError as e:
            invoke_traceback_print_exc(e)
        except NameError as e:
            invoke_traceback_print_exc(e)
        except AttributeError as e:
            invoke_traceback_print_exc(e)
        except TypeError as e:
            invoke_traceback_print_exc(e)
        except IndexError as e:
            invoke_traceback_print_exc(e)
        except KeyError as e:
            invoke_traceback_print_exc(e)
        except ImportError as e:
            invoke_traceback_print_exc(e)
        except UnicodeDecodeError as e:
            invoke_traceback_print_exc(e)
        except UnicodeEncodeError as e:
            invoke_traceback_print_exc(e)
        except ZeroDivisionError as e:
            invoke_traceback_print_exc(e)
        else:
            print("---- exception is nothing ----")
        finally:
            pass

 

OrderedDict.py

  • OrderedDict は登録順でデータを保持する辞書
  • 下記は git log の結果が OrderedDict オブジェクトに登録した順で表示されることを確認するプログラム
  • 具体的には以下の処理をしている (が、rm -rf 処理は危険なのでコメントアウトしている)

% rm -rf /tmp/repo
% mkdir /tmp/repo
% git clone -b master https://github.com/Shougo/echodoc.vim
% cd echodoc
% git log -5
% git checkout -b new_branch

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import git  # https://github.com/gitpython-developers/GitPython
import traceback
import shutil
from datetime import datetime as dt 
from time import *
from collections import OrderedDict

WORKDIR = '/tmp/'
TARGET = 'https://github.com/Shougo/echodoc.vim'

def do_rmdir( *args ) -> "rm -rf をするが、間違えると危険なので要注意" :
    for p in args:
        try:
            # shutil.rmtree(p)
            print("[Disable] rm -rf {0}".format(p))
        except:
            sys.exit(1)
        else:
            pass

def do_mkdir( *args ):
    for p in args:
        try:
            if not os.path.isdir(p):
                print("mkdir {0}".format(p))
                os.makedirs(p)
            else:
                print("{0} is alreadly existing".format(p))
        except:
            sys.exit(1)
        else:
            pass

if __name__ == '__main__':

    old_cwd = os.getcwd()
    od = OrderedDict()

    try:
        _local_repo = os.path.join(WORKDIR, 'repo')
        _branch = 'master'
        _log_num = 5
        _new_branch= 'new_branch'
        do_rmdir( _local_repo )  # rm -rf /tmp/repo
        do_mkdir( _local_repo )  # mkdir /tmp/repo

        # git clone
        print("[DEBUG] git clone -b {0} {1}".format(_branch, TARGET))
        repo = git.Repo.clone_from( TARGET, _local_repo, branch=_branch)

        # git log -5 を整形して表示する
        print("[DEBUG] git log -{0}".format(_log_num))
        for item in repo.iter_commits(_branch, max_count=_log_num):
            d = dt.fromtimestamp(item.authored_date).strftime("%Y-%m-%d %H:%M:%S")
            h = item.hexsha
            a = item.author
            od[h] = { d : a }
            print("[{0}] {1} [by {2}]".format(d, h, a))

        # OrderedDict の結果
        print("---- OrderedDict の結果 ----")
        for h,v in od.items():
            for k,a in v.items():
                print("[{0}] {1} [by {2}]".format(k, h, a))

        # git checkout -b new_branch をする場合
        print("[DEBUG] git checkout -b {0}".format(_new_branch))
        repo.git.checkout('-b', _new_branch)

    except:
        e = traceback.print_exc()
        print('エラー原因: {0}'.format(e))
        pass
    else:
        pass
    finally:
        os.chdir(old_cwd)

 

tuple2dict_1.py

  • 辞書にキーが無ければ新規作成、あれば追加登録をするプログラム

>|python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
みんなのPython 第4版
"""
animals = [ ('猫', '三毛'), ('犬', 'コーギー'),
('猫', 'シャム'), ('犬', 'ダックス'),
('犬', '黒ラブ'), ('ハムスター', 'ゴールデン')
]

if __name__ == '__main__':

d = {}
for k, v in animals:
if k not in d: # 辞書にキーが無ければ、新規登録する
d[k] = [v]
else:
d[k].append(v) # 辞書にキーがあれば、追加登録する

print(d)
|

 

tuple2dict_2.py

  • タプルから辞書を作るプログラム。
  • tuple2dict_1.py の改良版。
  • 辞書の setdefault() を使うことで余計な分岐を無くしている。
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
animals = [ ('猫', '三毛'),   ('犬', 'コーギー'),
            ('猫', 'シャム'), ('犬', 'ダックス'),
            ('犬', '黒ラブ'), ('ハムスター', 'ゴールデン')
          ]

if __name__ == '__main__':

    # tuple2dict_1.py の分岐を無くしたパターン
    d = {}
    for k, v in animals:
        d.setdefault(k, []).append(v)

    print(d)
    #=> {'犬': ['コーギー', 'ダックス', '黒ラブ'],
    #    '猫': ['三毛', 'シャム'],
    #    'ハムスター': ['ゴールデン']}

 

tuple2dict_3.py

  • タプルから辞書を作るプログラム。
  • tuple2dict_2.py の改良版。
  • defaultdict() の引数に list() というリスト作成の組み込み関数が指定されている
    • その結果、「dd」はデフォルト値として空のリストを返す辞書となる
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
from collections import defaultdict

animals = [ ('猫', '三毛'),   ('犬', 'コーギー'),
            ('猫', 'シャム'), ('犬', 'ダックス'),
            ('犬', '黒ラブ'), ('ハムスター', 'ゴールデン')
          ]

if __name__ == '__main__':

    # tuple2dict_2.py をさらに簡潔に書いたパターン
    dd = defaultdict(list)

    for k, v in animals:
        dd[k].append(v)

    print(dd)
    #=> defaultdict(<class 'list'>, {'猫': ['三毛', 'シャム'],
    #                                'ハムスター': ['ゴールデン'],
    #                                '犬': ['コーギー', 'ダックス', '黒ラブ']})

 

dict_update.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
"""
みんなのPython 第4版
"""
from pprint import pprint 

rssitem = { "title"   : "Pythonの勉強前",
            "link"    : "http://host.to/blog/entry",
            "dc:date" : "2016-05-16T13:24:04Z" }

rssitem.update({"title"      : "Pythonの勉強中!!",
                "dc:creator" : "someone"})

if __name__ == '__main__':

    print(rssitem.keys())

    pprint(rssitem)

 

kwargs.py

未定義のキーワード引数を受け取る。
受取先では辞書としてデータを保持する。

#!/usr/bin/env python3
# -*- coding: utf-8 -*- 

def bar( a, b, **kwargs ):
    print("(a, b) => ({0}, {1}, {2})".format(a, b, kwargs))

if __name__ == '__main__':
    bar( 1, 2 )                 #=> (a, b) => (1, 2, {})
    bar( 1, 2, c=3, d=4, e=5 )  #=> (a, b) => (1, 2, {'e': 5, 'd': 4, 'c': 3})
#   bar( 1, 2, { 'c':3, 'd':4, 'e':5 } )    # これはエラーになる

 

args.py

C、C++ でいう可変長引数を受け取る。

  • 可変長のリストやタプルを受け取る。
  • 辞書は受け取れない
#!/usr/bin/env python3
# -*- coding: utf-8 -*- 
def bar( a, b, *args ):
    print("(a, b) => ({0}, {1}, {2})".format(a, b, args))

if __name__ == '__main__':
    bar( 1, 2 )                         #=> (a, b) => (1, 2, ())
    bar( 'ls', '-l' )                   #=> (a, b) => (ls, -l, ())
    bar( 'ls', '-l', '-A' )             #=> (a, b) => (ls, -l, ('-A',))
    bar( 'ls', '-l', ['-A'] )           #=> (a, b) => (ls, -l, (['-A'],))
    bar( 'ls', '-l', ['-A', '-tr'] )    #=> (a, b) => (ls, -l, (['-A', '-tr'],))
    bar( 'ls', '-l', ('-A') )           #=> (a, b) => (ls, -l, (('-A'),))
    bar( 'ls', '-l', ('-A', '-tr') )    #=> (a, b) => (ls, -l, (('-A', '-tr'),))
#   bar( 1, 2, c=3, d=4, e=5 )              # これはエラーになる
#   bar( 1, 2, { 'c':3, 'd':4, 'e':5 } )    # これはエラーになる