【合格体験記】1ヶ月で3つのPython3エンジニア認定試験に合格しました

# はじめに

2024年の4〜5月にかけて、[Pythonソフトウェア財団（PSF）が運営するPythonエンジニア認定試験](https://www.pythonic-exam.com/exam)に3つ合格しました。スコアは、基礎試験とデータ分析試験が950、実践試験が925でした。

本記事では、受験のきっかけや勉強方法、これから受験を考えている方へのアドバイス等を共有させていただきます。

![exam-result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969456/f0fe8e77-fead-a762-7f31-e988e21ad27c.png)

:::note warn

2024/7/1より、データ分析試験が一部改訂される予定です。最新の試験情報は[公式サイト](https://www.pythonic-exam.com/exam)を必ずご確認ください。

:::

# 受験のきっかけ
私は2018年から業務でPythonを使用しています。Python認定試験の存在は以前から知っていましたが、これまでは業務繁忙や他の資格取得を優先しており、受験を見送っていました。今回、年度末を過ぎて空き時間ができたこと、弊社の資格支援制度の拡充がされた等のタイミングが重なったことから、受験を決意しました。

また、各試験では出題範囲が一部重複していること、さらに本業と並行して試験勉強を何ヶ月も続けるのは負担が大きいと考え、**1ヶ月以内に3つの認定試験に全て合格する**ことを目指しました。

:::note info

勉強期間が1試験あたり1〜2週間と非常にタイトでしたが、結果的には短期集中だからこそ毎日集中して学習できた気がします。

:::

受験する順番は、[公開されている合格率](https://www.pythonic-exam.com/archives/7533)と自身のスキルセットを踏まえ、**基礎試験 → データ分析試験 → 実践試験**としました。

:::note info

[2024/5/30のコラム](https://www.pythonic-exam.com/archives/7787)で合格率が更新されました。2024年4月の実践試験受験者の合格率は58%だったそうです。

:::

# 学習コンテンツと勉強方法
各試験の底本となっている[認定教材](https://www.pythonic-exam.com/material)を中心に勉強しました。全部買うと本代だけで1万円近くかかるため、ちょっと高いですね。私の場合は、所属部署の本棚や近隣の図書館に同じ本（版は古かった...）があり、運よく借りることができました。

::: note info

本記事の執筆時点で、「受験申し込み & SNSで受験宣言すると認定教材がプレゼント」されるキャンペーンが開催されています。受験まで日数に余裕がある方は、こちらもチェックしてみて下さい。

[受験宣言して試験を申し込んで主教材・公式問題集をもれなくGET！](https://www.pythonic-exam.com/archives/news/555camp)

:::

教材で試験範囲を学びつつ、模擬試験を解いて理解度を確認していきます。**不正解となった問題は実際にコーディング&デバッグ**して、

- なぜこのような実行結果になるのか？
- コードを変更したら結果はどう変化するか？
- この仕様は、公式ドキュメントのどこに明記されているのか

を**自らの手で確かめていく**ことで理解を深めました。

::: note info

個人の体感として、Pythonのコーディング経験があり、認定教材と模擬試験の大半が理解・実装できるなら十分に合格圏内と思われます。初学者で不安な方は、Udemyの教材やその他の問題集なども活用してみましょう。

:::

# 新たに学んだこと
Pythonの基本構文や標準ライブラリには自信がありましたが、いざ試験勉強してみると、理解が曖昧だった機能や全く知らなかった仕様などが色々ありました。以下に、新たに学んだことや「意外な仕様だなぁ」と驚いたことの一部を紹介します。

## 基礎試験
### nonlocalとglobal
変数のスコープを制御する[nonlocal](https://docs.python.org/ja/3/reference/simple_stmts.html#nonlocal)と[global](https://docs.python.org/ja/3/reference/simple_stmts.html#global)はどちらも実務での使用経験がなかったため、これらの挙動は改めて学習しました。

### シーケンスの比較
文字列やリストなどのシーケンスオブジェクト同士を比較する際、「先頭要素から辞書順で比較される」ことは理解していましたが、「**シーケンス長が異なる場合はシーケンス長の大小も比較される**」という仕様は理解不足でした。
```python
"abc" < "abe"  # True
"ab"  < "abc"  # True
"ac"  < "abc"  # False
```

### 複数の比較演算
pythonの比較演算では、例えば`(a < x) and (x < b)`なら`a < x < b`とシンプルに記述できます。ただ、模擬試験で見た以下のような式は正直面食らいました。実務で使うには流石に読みづらいため、`()`で囲うのが望ましいでしょう。
```python
(2 - 1) > False == 0  # True
```

:::note info

解説すると、上の比較演算は`((2 - 1) > False) and (False == 0)`と解釈されます。そして、pythonでは[`bool`は`int`のサブクラス](https://docs.python.org/ja/3/library/stdtypes.html#boolean-type-bool)であるため、`True`と`False`はそれぞれ整数の`1`と`0`のように振る舞います。

:::

## データ分析試験
### matplotlib
Pythonを学び始めた初期は[matplotlib](https://matplotlib.org)をよく使っていたのですが、以降は[seaborn](https://seaborn.pydata.org)などの高レベルAPIを使うことがほとんどだったため、`axes`や`subplot`などの仕様を改めて学び直しました。特に[円グラフ](https://matplotlib.org/stable/plot_types/stats/pie.html)は1度も使ったことが無く、「デフォルトの回転方向が反時計回り」という仕様に驚きながら覚えていきました。

:::note warn

試験とは無関係ですが、「円グラフは使用を避けるべき」という意見もあります。円グラフは全体の割合を表現しやすい反面、色への依存が強く、カテゴリ同士を比較しづらいためです。実務でチャートを使用する際は、円グラフの使用が適切かを考えてみても良いでしょう。

- [データ表示に円グラフを使うのは避けるべきという主張、その理由とは？](https://gigazine.net/news/20240113-almost-never-use-a-pie-chart/)
- [円グラフの弱点と代替チャートの提案](https://qiita.com/PrskAby/items/108f5b441fbf1b8d3ea0)

:::

## 実践試験
### shutil
`shutil`ライブラリには、ファイルをコピーするメソッドが[shutil.copyfile](https://docs.python.org/ja/3/library/shutil.html#shutil.copyfile)、[shutil.copy](https://docs.python.org/ja/3/library/shutil.html#shutil.copy)、[shutil.copy2](https://docs.python.org/ja/3/library/shutil.html#shutil.copy2)と3種類もあります。**名前だけでは何が違うのか全く想像つかない**ですね。実際は、メタデータやパーミッションもコピーするか否か、で仕様が異なっています。

### operator
[operator.itemgetter](https://docs.python.org/ja/3/library/operator.html#operator.itemgetter)を使うと、オブジェクトから`__getitem__()` メソッドを使って1つもしくは複数の要素を取得できます。以下のように**マッピングオブジェクトにも使えたり、複数のソート条件を簡潔に指定できることを初めて知り、目から鱗でした！**。

```python
from operator import itemgetter

# シーケンスオブジェクトからの取得
items = "ABCDEF"
itemgetter(1)(items)     # 'B'
itemgetter(2, 4)(items)  # ('C', 'E')

# マッピングオブジェクトからの取得
items = {200: "OK", 400: "Bad Request", 500: "Internal Server Error"}
itemgetter(200)(items)       # 'OK'
itemgetter(400, 500)(items)  # ('Bad Request', 'Internal Server Error')

# タプルのリストを、タプル内要素の1番目、0番目の順で昇順ソート
items = [(3, 1), (2, 0), (5, 1), (4, 0)]
# lambdaでの実装例
sorted(items, key=lambda x: (x[1], x[0]))  # [(2, 0), (4, 0), (3, 1), (5, 1)]
# itemgetterでの実装例
sorted(items, key=itemgetter(1, 0))        # [(2, 0), (4, 0), (3, 1), (5, 1)]
```

[operator.attrgetter](https://docs.python.org/ja/3/library/operator.html#operator.attrgetter)を使えば、同様のオブジェクトから1つもしくは複数の属性値を効率よく取得できます。

```python
from datetime import date
from operator import attrgetter

now = date(2024, 7, 1)
attrgetter("year")(now)          # 2024
attrgetter("month", "day")(now)  # (7, 1)
```

### io.StringIO
[io.StringIO](https://docs.python.org/ja/3/library/io.html#io.StringIO)には`initial_value`という初期文字列を入れる引数があります。ただし、**`initial_value`を指定してもシーク位置は先頭(`0`)に戻っている**という仕様のため、**そのまま追記すると初期文字列が上書き**されてしまいます。

以下は初期文字列`Python`に`!`を追記する実験コードです。`tell()`はシークの現在位置を出力します。
```python
from io import StringIO, SEEK_END

# 失敗例
with StringIO(initial_value="Python") as f:
    f.tell()      # 0（シーク位置が先頭に戻っている！）
    f.write("!")
    f.getvalue()  # '!ython'

# 成功例
with StringIO(initial_value="Python") as f:
    f.seek(0, SEEK_END)  # シーク位置を末尾に移動する
    f.tell()             # 6
    f.write("!")
    f.getvalue()         # 'Python!'
```


# 試験会場
試験勉強と並行して、試験会場を予約します。

今回は[オデッセイテスティングセンター](https://otc.odyssey-com.co.jp)の有楽町店で受験しました。この会場は[1日に受験できる時間帯が7枠](https://otc.odyssey-com.co.jp/exam/flow.php)と多く、比較的空いていて予約しやすいためオススメです。横浜店もあります。

:::note info

[試験会場を検索](https://cbt.odyssey-com.co.jp/place/index.html)すると、東京都内だけで30か所以上もあります。職場や自宅から行きやすい会場を選択しましょう。

:::

# 受験
体調を整え、いよいよ受験です！

各試験とも難易度は模擬試験に近しい印象でしたので、模擬試験をしっかり対策すれば大丈夫かと思います。

ただ、実践試験はそれなりに難しかったです。私の時は**出題された最初の2問がいきなり分からず**、「これは勉強不足だったか...」とかなり焦りました。幸い、後の問題は何とか答えることができました。

全問に回答してアンケートに記入すると、その場で合否が出力されます。退室後、受付から試験結果レポートが手渡され、合計得点とカテゴリ毎の正答率が確認できます。

:::note info

まだ試験内容が頭に残っている内に、振り返りをすることを推奨します。特に回答に自信が無かった問題があれば、認定教材で読み返したり実際にコーディングして出力結果を確かめておくと、後でモヤモヤが残らずスッキリします。

:::

# 受験して何が変わったか？
**Pythonに対する知識の幅が増えた** と感じます。特に実践試験の認定教材からは、

- 標準ライブラリにはこんな便利な機能があったんだ！
- 似ている２つの機能は、こうやって使い分ければ良いんだ！
- 今まで汚いコードで実装してきた内容が、これを使えばもっとPythonicに書けそうだ！

といった発見が多々得られ、試験の合否に関わらず大きな学びとなりました。

# まとめ
本記事では、Python認定試験の合格体験記を共有させていただきました。試験合格を目指す方々の参考になれば幸いです。