プログラミング入門I
2024.12.23
オブジェクトと型

Back to index page



  1. 本日の作業内容

  2. 前回の宿題について

    今回も実行時のエラーが無く気持ちよく採点できました.その点はうれしかったです.ただ,依然として習ってもいないリストを使う人がなくなりません.もちろん分かって使っているのなら問題は無いのですが,それだけのスキルがある人ならしないような不備もあるので,やっぱり検索やAIに頼ってしまって実力が伴っていない人と判断差ざるを得ないものが大半です.何のために大学で高い授業料を原って授業を履修しているのか,その意味をよく考えてください.

    出力時番号間違い: b2447

    以下は例によって問題のあるプログラムの例です.参考にしてください.

    MIN = 100
    MAX = 1
    

    変数名は小文字で始めるように何度も何度も何度も何度も...

    for _ in range(5):
            mx=0
            mini=100
            for _ in range(10):
                ran = random.randint(1,100)
                print(f'{ran:3}',end = ' ')
                if mx < ran:
                    mx = ran
                if mini > ran:
                    mini = ran
            else:
               print(f' -- {mini:3} {mx:3}')
            
    else:
        print()
    

    目には見えないのですが,上の print 文の中に全角スペースが入っています.そのため,私の環境では表示が下のようになってしまいます.

    100  35  63  87  73  57  63  10   9  51  □@--   9 100
      7  35  23  39  10  45  25   7  49  44  □@--   7  49
     45 100  85  81   1  67  37  36  66  12  □@--   1 100
    100  68  73  78  34  86  45  65  77  49  □@--  34 100
     39   3  16 100  52  84  43  68  34  50  □@--   3 100
    

    for j in range(5):
            mn=101
            mx=0
            for i in range(10):
                    num=random.randint(1,100)
                    print(f'{num:3}',end=' ')
                    if num > mx:
                            mx = num
                    if num < mn:
                            mn = num
            print(f' -- {mn:3} {mx:3}')
    else:
            print()
    

    上の例は中身は問題ないのですが,インデントのTAB幅が2倍になっています.インデントが進むたびにどんどん右にずれていくので,全体としては見づらいものになります.IDLEでは標準で4文字分になっているはずですが,その設定がもし変わってしまったのなら直してください.

    num = random.randint(1,100)
    print(f'{num:3}', end = '')
    

    発生させる乱数は1から100までですので,3桁は合っているのですが,スペースを入れていないのでくっついて見づらくなります.

    71 76 82 33100 61 84100 19 76  --  19100
    19 42 51 97 61 74 64 45 47 86  --  19 97
    78 21 19 98 45 37 75 15 41 96  --  15 98
    33 52 84 14 56 11 63 28 43 35  --  11 84
    55 40 32 87 41 37 90 30 99 87  --  30 99
    

    for i in range(1,6):
        ma = 0
        mi = 100
        for j in range(1,11):
            j = random.randint(1,100)
            print(f'{j:3} ', end = '')
            if j > ma:
                ma = j
            elif j < mi:
                mi = j
        print(f'  -- {mi:3} {ma:3}')
    

    内側の for 文の引数 j を乱数にも使うという良くない書き方をしていますが,それに加えて,最小値の判定を elif にしているので,結果が以下のように間違ったものになります.elif を使った人は他にも何人かいました.最大値か最小値かは関係しないものなので,最大値でなければ最小値かという処理は間違いです.

    1  65  98  67  27  46  21  64  48  46   --  21  98
    70  82  56  34  62  50  97  76  64  46   --  34  97
    14  20  71  70   7  54  35  62  23  63   --   7  71
    90  78  27  56  32  58  15  56  57  74   --  15  90
    30  57  28  94  39  13  14  81  58  22   --  13  94
    

    large = 0
    small = 101
    for _ in range(1,6):
        for _ in range(1,11):
            num = random.randint(1,100)
            print(f'{num:3}',end = '' )
            if num > large:
                large = num
            if num < small:
                small = num
        print(f'--{small:4}{large:4}')
    

    最大値と最小値の初期値をループの外で行っているので,初期値が更新されず,前の値を引きずってしまっています.そのため,当然下のように結果は間違ったものになります.

    55 78 91 80 47 37 25 56 30 26--  25  91
    81 88 23 68 74 36 37 39 42 61--  23  91
    16 34  1 61 86 96 77 31 65 24--   1  96
    74 98 80 52 12 11 35 66 29 51--   1  98
    74  5  3 90 65 50  4 93 65 34--   1  98
    

    max1=0
    min1=100
    n=0
    for i in range(1,6):
        for u in range(1,11):
            n+=random.randint(1,100)
            print(f'{n:3}',end=' ')
            if max1n:
                min1=n
            n=0
        else:
            print(f' -- {min1:3} {max1:3}')
        max1=0
        min1=100
    else: print()
    

    こちらは初期化はできているので値は正しいものになっていますが,最初に行った初期化は意味がありません.ループの先頭で1回書けば済みます.

    for  _ in range(5):
        max1=0
        min1=101
        keep=0
        for _ in range(10):
            keep=random.randint(1,100)
            print(f'{keep:3}',end=' ')
            if max1keep:
                min1=keep
        print(f'--{min1:3} {max1:3}')
    

    内側のループの前の変数 keep への代入は不要ですね.

    print(f"{numbers_str:<25} -- {min_value:<10}{max_value:<10}")
    

    なんで左揃えになってしまうのでしょうか?

    for _ in range(5):
        num1 = random.randint(1, 100)
        print(f'{num1:4}', end ='')
        mx = 0
        mn = 100
        for _ in range(9):
            num2 = random.randint(1, 100)
            
            print(f'{num2:4}', end = ' ')
            if num2 > mx :
                mx = num2
            if num2 < mn:
                mn = num2
            if num1 > mx:
                mx = num1
            if num1 < mn:
                mn = num1
            
            
            
        else:
            print(f' -- {mn:3} {mx:3}')
    

    10個の整数を2つの組に分ける意味が分かりません.当然 if 文の処理も無駄に多くなります.

        print(" ".join(f"{num:2d}" for num in numbers), end="  --  ")
        print(f"{min_num:2d} {max_num:2d}")
    

    1から100までの数なので,3桁ですよね?なぜ2桁分の表示なんでしょうかね.当然画面の表示は乱れます.自分でも気づいているはずですが.

    以下はリストを使用したものです.心配しなくてもプログラミング入門IIでリストはやりますから,今は学習した内容を反映させて,今の能力で適切なものを作ってください.

    for _ in range(5):
        num = []
        count = 0
        while count < 10:
            num.append(random.randint(1, 100))
            count += 1 
    
        small = 101  
        large = -1  
    
        for n in num:
            if n < small:
                small = n
            if n > large:
                large = n
    
        print(" ".join(f"{n:>3}" for n in num) + f"  -- {small:>3} {large:>3}")
    

    for i in range(5):
        n = [random.randint(1, 100)for _ in range(10)]
        MIN = min(n)
        MAX = max(n)
        numbers = ' '.join(f'{num:2}' for num in n)
        print(f'{numbers}  --  {MIN} {MAX}')
    else:
        print()
    

    リストを使いこなせる能力があるのなら当然表示桁数もちゃんとできるはずですよねえ.

    64 12  9 11 53 66 23 54 17 39  --  9 66
    69 24 47 84 81 25 71 42 30 86  --  24 86
     7 75 63 10 96 10  2  9 44 25  --  2 96
     7 25 60 36 100 47  8 77 37 26  --  7 100
     4 93 43 47 74 100 12 18 41 100  --  4 100
    

    for _ in range(5):
        
        random_num = [random.randint(1, 100) for _ in range(10)]
        
        
        min_num = min(random_num)
        max_num = max(random_num)
        
    
        print(f"{random_num}",end = ' ')
        print(f"-- {min_num}",end = ' ')
        print(f"{max_num}")
    

    リストを使いこなせる能力があるのなら,当然アンパックくらいは知っていて,下のような変な表示はしないですよねえ.

    [64, 33, 63, 67, 1, 100, 1, 83, 35, 79] -- 1 100
    [90, 91, 32, 6, 23, 14, 15, 9, 20, 45] -- 6 91
    [86, 95, 85, 57, 85, 46, 47, 19, 21, 89] -- 19 95
    [4, 19, 35, 15, 18, 67, 72, 57, 58, 5] -- 4 72
    [58, 84, 7, 54, 97, 68, 23, 96, 62, 49] -- 7 97
    

  3. 前回の復習

    今回は確認テストで復習状況をチェックしますので,しっかり準備してください.

  4. オブジェクトと型

    Python は「オブジェクト指向言語」というプログラミング言語の一つです.その「オブジェクト」の意味がこの章では詳しく説明されています.ただ,この授業で行っているような初歩的なプログラムではその恩恵を受けることはほとんどありませんが,それでも今回はいろいろと確認していきましょう.

    1. オブジェクトとは
    2. 変数に値を代入するという操作はオブジェクトとしての値に変数名を紐づける,ということになります.それが特にわかるようなことはプログラミングの作業中にはありませんが,後ほど出てくるように誰も参照しないオブジェクトは削除する,という裏側の機能によってメモリの無駄遣いを防ぐことにはなっています.

      まずは,教科書 p.116 にあるようにインタラクティブシェルで試してみてください.

    3. ミュータブルとイミュータブル
    4. まだリストなどを学習していないので,このミュータブルとイミュータブルの違いを実感することはありません.リストを学習し始めて,変な処理を書いてしまうと,これに関するエラーを目にすることがあるかもしれません.

    5. 同一性判定演算子
    6. == は値が同じかどうかを判定する比較演算子でしたが,is 演算子はオブジェクトそのものが同じかどうかを判定します.

  5. 型と演算
    1. これまでにも型の話は出てきていますが,実際に演算を行うとどうなるのかについて,一応教科書をよく見て確認しておいてください.また,教科書 p.124 にある Table 5-3 には様々な組み込み関数が紹介されていますので,ここはぜひとも活用できるように覚えておきましょう.本日の演習問題ではこれらを使うプログラムを作っていきます.また,教科書 p.127 の List 5-7 に例示されている数値の表示の際の空白を 0 で埋める表現も,場合によっては使用しますので,確認しておいてください.

    2. ビット演算
    3. どのプログラミング言語の教科書にも出てくるビット演算ですが,入門的な範囲では基本的には使うことはありません.これは複数のフラグを管理するような用途において,通常の演算よりもビット演算の方が高速であるために用意されているものだと思ってください.

      今回はファイルのアクセス許可などで使用されているフラグ判定についての簡単な作業を演習で体験します.一応こんなもんだと思って知識として持っておいてください.

  6. 演習

    今回の演習問題です.

  7. 本日のまとめ

  8. 宿題

    宿題が公開されるのは明日火曜日10:00の予定で,締切りは来年の1月6日の10:00です.レポート提出システムを使用します.

  9. 次回の予習範囲

    次回は教科書のp.134-162の範囲を学習しますので,予習をしてきてください.


目次ページに戻る