Python 3 エンジニア認定基礎試験 標準ライブラリと仮想環境 問題

ゆめさくが作った練習問題です。本試験の問題ではありません。

標準ライブラリと仮想環境の問題を1⁠5問、小分野ごとにまとめました。選ぶと、その場で正誤と解説が出ます。

ログインなしで解けます。答えはこのブラウザの中だけに残り、どこにも送りません。

この分野の小分野

  • 標準ライブラリめぐり(10問)
  • 標準ライブラリめぐり Part II と仮想環境(5問)

標準ライブラリと仮想環境の問題

15 問

選ぶと、すぐに正誤と解説が出ます。選んだ答えは変えられません。

  1. 標準ライブラリめぐり

    問 1os モジュールを使うとき、from os import * ではなく import os の形で読み込むよう勧められている理由として正しいものはどれですか。

  2. 問 2空のディレクトリで次のコードを実行したときの出力として正しいものはどれですか。

    import glob, shutil
    
    open('a.txt', 'w').close()
    open('b.csv', 'w').close()
    shutil.copyfile('a.txt', 'c.txt')
    print(sorted(glob.glob('*.txt')))
  3. 問 3次のプログラムを demo.py として保存し、python demo.py -n 3 a.txt b.txt で実行したときの出力として正しいものはどれですか。

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('files', nargs='+')
    parser.add_argument('-n', '--count', type=int, default=1)
    args = parser.parse_args()
    print(args.files, args.count)
  4. 問 4次のコードを実行したときの出力として正しいものはどれですか。

    import re
    
    print(re.findall(r'\b\d+\b', 'room 12, floor 3a, no 45'))
  5. 問 5random.sample(range(100), 10) を何度も呼んだとき、毎回必ず成り立つことはどれですか。

  6. 問 6with urlopen(url) as response で開き、for line in response で 1 行ずつ読んだときの line について正しい説明はどれですか。

  7. 問 7次のコードを実行したときの出力として正しいものはどれですか。

    from datetime import date
    
    d1 = date(2024, 2, 27)
    d2 = date(2025, 2, 27)
    print((date(2024, 3, 1) - d1).days, (d2 - d1).days)
  8. 問 8zlib.compress() の使い方として正しい説明はどれですか。

  9. 問 9from timeit import timeit のあと timeit('sum(range(100))', number=1000) を呼んだときの戻り値として正しいものはどれですか。

  10. 問 10doctest モジュールの doctest.testmod() が行うこととして正しいものはどれですか。

  11. 標準ライブラリめぐり Part II と仮想環境

    問 11次のコードを実行したときの出力として正しいものはどれですか。

    from string import Template
    
    t = Template('$item は ${n}個')
    print(t.safe_substitute(item='りんご'))
  12. 問 12次のコードを実行したときの出力として正しいものはどれですか。

    from decimal import Decimal
    
    print(Decimal('0.1') * 3 == Decimal('0.3'), 0.1 * 3 == 0.3)
  13. 問 13設定を何もせずに logging.debug('a') と logging.warning('b') を順に実行したときの動きとして正しいものはどれですか。

  14. 問 14python -m venv tutorial-env を実行したときに起きることとして正しいものはどれですか。

  15. 問 15仮想環境の中で python -m pip freeze > requirements.txt として作ったファイルについて、正しい説明はどれですか。

15 問中 0 問に答えました

解説の一覧

解いたあとに読み返せるよう、全問の解説を並べています。問いを開くと解説が出ます。

標準ライブラリめぐり

問1os モジュールを使うとき、from os import * ではなく import os の形で読み込むよう勧められている理由として正しいものはどれですか。

正解は「os.open() が組み込みの open() を覆い隠してしまうから」です。os モジュールには open という関数があり、組み込み関数の open() とは動きが大きく違います。from os import * と書くと os の中の名前がまとめて取り込まれ、open という名前が os.open() を指すようになって、組み込みの open() が隠れてしまいます。import os の形なら os.open() と open() を書き分けられるので、この事故を避けられます。from os import * でも公開されている関数は取り込まれるので、1 つも読み込まれないわけではありません。読み込みの速さは勧められる理由ではありません。from モジュール import * は Python 3 でも使える構文で、エラーにはなりません。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#operating-⁠system-⁠interface

問2空のディレクトリで次のコードを実行したときの出力として正しいものはどれですか。
import glob, shutil

open('a.txt', 'w').close()
open('b.csv', 'w').close()
shutil.copyfile('a.txt', 'c.txt')
print(sorted(glob.glob('*.txt')))

正解は「['a.txt', 'c.txt']」です。shutil.copyfile(元, 先) はファイルの中身を別の名前のファイルにコピーするので、コピーしたあとも元の a.txt は残ります。glob.glob('*.txt') はワイルドカードに合うファイル名のリストを返します。ディレクトリには a.txt、b.csv、c.txt の 3 つがあり、*.txt に合うのは a.txt と c.txt です。glob の結果の並びは決まっていないので sorted で並べ、['a.txt', 'c.txt'] になります。['a.txt'] はコピーで c.txt ができないと考えた誤りです。b.csv を含む選択肢は、*.txt が拡張子に関係なくすべてに合うと考えた誤りです。['c.txt'] は copyfile が移動のように元を消すと考えた誤りで、移動は shutil.move です。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#file-⁠wildcards

問3次のプログラムを demo.py として保存し、python demo.py -n 3 a.txt b.txt で実行したときの出力として正しいものはどれですか。
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='+')
parser.add_argument('-n', '--count', type=int, default=1)
args = parser.parse_args()
print(args.files, args.count)

正解は「['a.txt', 'b.txt'] 3」です。コマンドラインの引数は sys.argv にリストで入り、argparse モジュールはそれを解析して名前で取り出せるようにします。add_argument('files', nargs='+') は 1 つ以上の位置引数を files にリストで集めます。add_argument('-n', '--count', type=int, default=1) は省略できる引数で、-n 3 と渡すと 3 が int に変換されて count に入ります。-n とその値 3 は files には入らないので、['a.txt', 'b.txt'] 3 です。count が 1 になるのは -n を付けなかった場合で、default の値が使われます。-n や 3 が files に入る選択肢は、オプションと位置引数を区別せずに集めると考えた誤りです。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#command-⁠line-⁠arguments

問4次のコードを実行したときの出力として正しいものはどれですか。
import re

print(re.findall(r'\b\d+\b', 'room 12, floor 3a, no 45'))

正解は「['1⁠2', '4⁠5']」です。re.findall はパターンに合う部分をすべて探し、文字列のリストで返します。\d+ は 1 けた以上の数字の並び、\b は単語の境目を表します。1⁠2 と 4⁠5 は前後が空白やカンマなので境目があり、どちらも取り出されます。3a の 3 は後ろが英字の a で、数字と英字はどちらも単語の文字なので 3 と a の間に境目がありません。そのため 3 は合わず、['1⁠2', '4⁠5'] になります。['1⁠2', '3', '4⁠5'] は \b を無視した場合の結果です。'3a' は \d+ が英字にも合うと考えた誤りです。1 文字ずつに分かれる選択肢は + を付けない \d の場合で、+ があると続く数字をまとめて取ります。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#string-⁠pattern-⁠matching

問5random.sample(range(1⁠0⁠0), 1⁠0) を何度も呼んだとき、毎回必ず成り立つことはどれですか。

正解は「0 から 9⁠9 までの、重複しない 1⁠0 個の数が返る」です。random.sample(母集団, k) は、母集団から k 個を重複なしで選んだリストを返します。range(1⁠0⁠0) は 0 から 9⁠9 までの数なので、結果は必ず 0 から 9⁠9 までの、互いに重複しない 1⁠0 個の数です。中身と並びは呼ぶたびに変わります。毎回同じ結果になるのは、random.seed で同じ種を与えて呼び直した場合などです。sample は選んだ順に返すので、小さい順に並ぶとは限りません。同じ数が入りうるのは random.choices のように重複を許す選び方で、sample では起きません。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#mathematics

問6with urlopen(url) as response で開き、for line in response で 1 行ずつ読んだときの line について正しい説明はどれですか。

正解は「bytes なので、文字列として扱うには decode() で str にする」です。urllib.request の urlopen は URL を開き、ファイルのように読めるオブジェクトを返します。for で 1 行ずつ取り出すと、各行は bytes です。チュートリアルの例でも line = line.decode() と書いて bytes を str に変えてから文字列として調べています。urlopen の戻り値は with 文で使え、ブロックを抜けると閉じられます。自動で str になるという説明は誤りで、decode() が要ります。for で回すと 1 行ずつ渡されるので、全体が 1 回で渡されることはありません。with 文と使えないという説明も誤りで、チュートリアルの例自体が with 文を使っています。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#internet-⁠access

問7次のコードを実行したときの出力として正しいものはどれですか。
from datetime import date

d1 = date(2024, 2, 27)
d2 = date(2025, 2, 27)
print((date(2024, 3, 1) - d1).days, (d2 - d1).days)

正解は「3 3⁠6⁠6」です。datetime モジュールの date どうしを引き算すると、日数の差を持つ timedelta ができ、.days で日数を整数で取り出せます。2⁠0⁠2⁠4 年はうるう年なので 2 月が 2⁠9 日まであります。2 月 2⁠7 日から 3 月 1 日までは 2⁠8 日、2⁠9 日、3 月 1 日と進むので 3 日です。2⁠0⁠2⁠4 年 2 月 2⁠7 日から 2⁠0⁠2⁠5 年 2 月 2⁠7 日までの 1 年には 2⁠0⁠2⁠4 年 2 月 2⁠9 日が入るので 3⁠6⁠6 日です。日付の計算はカレンダーに合わせて行われます。2 3⁠6⁠5 はうるう年を無視した結果です。3 3⁠6⁠5 は 1 年を常に 3⁠6⁠5 日と考えた誤りです。2 3⁠6⁠6 は 2 月 2⁠9 日が 1 年の差には入るのに、3 月 1 日までの差には入らないと考えた、食い違った読み方です。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#dates-⁠and-⁠times

問8zlib.compress() の使い方として正しい説明はどれですか。

正解は「bytes を渡すと、圧縮したデータが bytes で返る」です。zlib はデータ圧縮の形式を直接扱うモジュールです。zlib.compress(data) は bytes のデータを圧縮し、圧縮したデータを bytes で返します。元に戻すには zlib.decompress() に渡します。同じ並びを繰り返す b'xyz' * 5⁠0 を圧縮すると長さは大きく縮み、decompress で元と同じ bytes に戻ります。str を渡すと TypeError になるので、文字列は encode() で bytes にしてから渡します。ファイルを扱うのは gzip などのモジュールで、compress にファイル名を渡しても中身は圧縮されません。リストを渡しても TypeError で、要素ごとに圧縮はしません。 出典 https://docs.python.org/ja/3/library/zlib.html#zlib.compress

問9from timeit import timeit のあと timeit('sum(range(1⁠0⁠0))', number=1⁠0⁠0⁠0) を呼んだときの戻り値として正しいものはどれですか。

正解は「1⁠0⁠0⁠0 回実行するのにかかった合計の秒数を float で返す」です。timeit.timeit は、渡した文を number 回実行するのにかかった時間を測ります。既定のタイマーは秒数を浮動小数点数で返すので、戻り値は number 回ぶんの合計の秒数を表す float です。1 回あたりの時間が欲しいときは、戻り値を number で割ります。number を省くと 1⁠0⁠0 万回実行します。測った秒数は機械や混み具合で毎回変わります。平均を返すという説明は誤りで、返るのは合計です。測る対象の式の値は返しません。単位はミリ秒ではなく秒で、型も int ではなく float です。 出典 https://docs.python.org/ja/3/library/timeit.html#timeit.Timer.timeit

問10doctest モジュールの doctest.testmod() が行うこととして正しいものはどれですか。

正解は「docstring に書いた対話の例を実行し、表示が書いた結果と合うかを確かめる」です。doctest はモジュールの docstring に埋め込まれたテストを探して実行し、結果を確かめます。テストは、対話モードでの呼び出しの例とその表示を docstring に貼り付けるだけで作れます。たとえば docstring に double(4) の結果を 8 と書き、本体を n * 3 にしておくと、testmod() は 1 件を試して 1 件の失敗を見つけます。使い方の例がそのままテストになるので、説明とコードのずれに気づけます。型ヒントの照合は doctest の仕事ではありません。docstring が書かれているかどうかも調べません。TestCase を継承したクラスのテストを動かすのは unittest モジュールです。 出典 https://docs.python.org/ja/3/tutorial/stdlib.html#quality-⁠control

標準ライブラリめぐり Part II と仮想環境

問11次のコードを実行したときの出力として正しいものはどれですか。
from string import Template

t = Template('$item は ${n}個')
print(t.safe_substitute(item='りんご'))

正解は「りんご は ${n}個」です。string.Template は $ で始まるプレースホルダを値に置き換えます。後ろに名前の文字が続くときは ${n} のように波括弧で囲みます。substitute() は値の無いプレースホルダがあると KeyError を送出しますが、safe_substitute() は値の無いプレースホルダをそのまま残します。ここでは item だけ渡しているので $item は りんご に替わり、${n} は残って りんご は ${n}個 になります。りんご は 個 は、値の無いプレースホルダが空の文字列に替わると考えた誤りです。KeyError で止まるのは substitute() を使った場合です。$item は ${n}個 は、1 つでも値が欠けると何も置き換えないと考えた誤りです。 出典 https://docs.python.org/ja/3/tutorial/stdlib2.html#templating

問12次のコードを実行したときの出力として正しいものはどれですか。
from decimal import Decimal

print(Decimal('0.1') * 3 == Decimal('0.3'), 0.1 * 3 == 0.3)

正解は「True False」です。decimal モジュールの Decimal は 1⁠0 進数で計算するので、文字列 '0.1' から作った値は 0.1 をそのまま正確に表します。Decimal('0.1') を 3 倍すると Decimal('0.3') とぴったり等しくなり True です。一方、float の 0.1 は 2 進数では正確に表せない近い値なので、0.1 * 3 は 0.3⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠0⁠4 になり、0.3 と等しくならず False です。お金の計算のように 1⁠0 進数で正確さが要る場面で Decimal が役立ちます。False False は Decimal でも誤差が出ると考えた誤りです。True True と False True は float でも 0.1 * 3 が 0.3 と等しいと考えた誤りです。 出典 https://docs.python.org/ja/3/tutorial/stdlib2.html#decimal-⁠floating-⁠point-⁠arithmetic

問13設定を何もせずに logging.debug('a') と logging.warning('b') を順に実行したときの動きとして正しいものはどれですか。

正解は「b の記録だけが出て、出る先は標準エラー出力である」です。logging モジュールは、既定では info() と debug() の記録を抑え、出力を標準エラー出力に送ります。warning() は抑えられる段階より上なので記録が出ます。よって b の記録だけが標準エラー出力に出ます。標準出力に出るという説明も、debug の記録が出るという説明も、既定の動きと違います。basicConfig を呼ばなくても warning 以上の記録は出ます。warning() は記録を残すだけで、例外は送出しません。 出典 https://docs.python.org/ja/3/tutorial/stdlib2.html#logging

問14python -m venv tutorial-⁠env を実行したときに起きることとして正しいものはどれですか。

正解は「tutorial-⁠env ディレクトリが作られ、中に Python インタープリタと補助ファイルが置かれる」です。venv モジュールは仮想環境を作って管理します。python -m venv tutorial-⁠env を実行すると、tutorial-⁠env ディレクトリが無ければ作られ、その中にサブディレクトリと、Python インタープリタ (チュートリアルの言い方ではそのコピー、macOS や Linux では実体へのシンボリックリンクのことが多い) と各種の補助ファイルが置かれます。使うには、Unix や macOS なら source tutorial-⁠env/bin/activate、Windows なら tutorial-⁠env\Scripts\activate で有効化します。pip でパッケージを入れるコマンドではありません。作っただけでは有効にならず、activate で有効化する必要があります。ネットから最新の Python を取ってくることもなく、実行した Python の版が使われます。出典 https://docs.python.org/ja/3/tutorial/venv.html#creating-⁠virtual-⁠environments

問15仮想環境の中で python -m pip freeze > requirements.txt として作ったファイルについて、正しい説明はどれですか。

正解は「パッケージ名==版 の形で並び、pip install -r で同じ版をまとめて入れられる」です。pip freeze は、インストール済みのパッケージの一覧を pip install が受け付ける形式で出力します。各行は novas==3.1.1.3 のように パッケージ名==版 の形です。この出力をふつう requirements.txt に保存し、バージョン管理に入れてアプリと一緒に配ります。受け取った人は python -m pip install -r requirements.txt を実行すると、書かれた版のパッケージをまとめて入れられます。名前だけが並ぶという説明は誤りで、== の後ろに版が入り、pip install -r では書かれた版が入ります。Python 本体の版を書くファイルではなく、python -m venv に渡すものでもありません。requirements.txt は Python のプログラムではないので、python requirements.txt と実行するものではなく、pip install -r に渡して使います。出典 https://docs.python.org/ja/3/tutorial/venv.html#managing-⁠packages-⁠with-⁠pip

ほかの分野

Python 3 エンジニア認定基礎試験の頁に、6分野の入口と試験の案内があります。

続きはゆめさくで

試験の知識を仕事につなげる一歩を、ここにまとめています。