Pythonのハマりやすいポイントを学ぶ問題集を作ってみた - 第二弾

# はじめに

Python の基礎知識やハマりやすいポイントを学ぶ問題集の第二弾（20 問は少し多かったので今回はとりあえず 10 問）を作ってみました。ぜひご活用ください！

- 注意事項
  - 本問題集は Python3.11 を基準に作成されています。
  - Python の基礎知識やハマりやすいポイントを全て網羅しているわけではありません。Python の学習や開発においては、他の情報源や公式ドキュメントを併せて活用することをお勧めします。
  - 問題の実行結果がエラーやベストプラクティスでない場合もありますので、解説を通じて理解を深めることをおすすめします。
  - 不明点や疑問点がある場合は、実際にコードを実行したり、公式ドキュメント等を参照することをおすすめします。

第一弾はこちら

https://qiita.com/to-fmak/items/9d1be12713f38b8bd6fa

# 問題 1

次のコードの実行結果を選択してください。

```python
if None or 0 or '疲れたな':
    print('休んでいいよ')
else:
    print('サボってんじゃねぇぞ')
```

```:選択肢
A: 休んでいいよ
B: サボってんじゃねぇぞ
C: None
D: 0
```

<details><summary>解答</summary>
正解：A

解説：

- 条件式 `None or 0 or '疲れたな'` は、論理演算子 or を使って 3 つの要素を結合しています。この場合、各要素は論理式として評価されます。
  - `None` は `False` と評価されます。
  - `0` も `False` と評価されます。
  - '疲れたな' は`非空の文字列`であるため、`True` と評価されます。
- 論理演算子 or は、左側の式から順に評価され、`最初に真`と評価された値が返されます。したがって、条件式全体としては '疲れたな' の部分が真と評価されるため、print('休んでいいよ') が実行され、結果として '休んでいいよ' が出力されます。

</details>

# 問題 2

次のコードの実行結果を選択してください。

```python
num = 1

if num % 2 == 0 or ...:
    print('even')
else:
    print('odd')
```

```:選択肢
A: even
B: odd
C: 何も出力されない
D: SyntaxError
```

<details><summary>解答</summary>
正解： A

解説：

- Python では、`Ellipsis` または `...` で表される Ellipsis というシングルトンオブジェクトがあって、主に拡張スライス構文やユーザ定義のコンテナデータ型において使われる特殊な値です。Ellipsis とは`省略`という意味なので、省略記号としてコードの一部が省略されていることを示すためにも使われます。
- ...は真偽値として評価されるときには`True`となります。
  ```python
  >>> bool(...)
  True
  ```
- この問題では、num の値が odd（奇数）で、num % 2 == 0 を満たさないですが、...が常に True のため、結果として間違った解答である even（偶数）という文字列が出力されます。

</details>

# 問題 3

次のコードの実行結果を選択してください。

```python
type = int
a = '1'
print(type(a))
```

```:選択肢
A: <class 'str'>
B: <class 'int'>
C: 1
D: TypeError
```

<details><summary>解答</summary>
正解：C

解説：この問題では、type という変数名が使われていますが、type は Python の組み込み関数です。type = int という代入文により、type 変数は int クラスそのものを参照するようになります。そのため、print(type(a)) が print(int(a)) と同じ意味になります。結果として、文字列 '1' が整数の 1 に変換されて表示されます。

</details>

# 問題 4

次のコードの実行結果を選択してください。

```python
print(f'{1_234.5678:,.3f}')
```

```:選択肢
A: SyntaxError
B: 1,234.568
C: 1234.5678
D: 1234.567
```

<details><summary>解答</summary>
正解：B

解説：この問題では、フォーマット指定子を使って浮動小数点数を指定された形式で表示しています。

- アンダースコア `_` は桁区切りのために使われており、コードの読みやすさを向上させています。1_234.5678 は`1234.5678`と同じ値を表します。
- `,` は桁区切りのカンマを指定します。この指定子により、整数部の 3 桁ごとにカンマが挿入されます。
- `.3f`は指定された桁数で小数点以下を丸めて表示します。この場合は、小数点以下 3 桁まで表示されます。
- したがって、f'{1_234.5678: ,.3f}' の結果は、1,234.568 となります。

</details>

# 問題 5

次のコードの実行結果を選択してください。

```python
a = {}
a.add(1)
print(a)
```

```:選択肢
A: {1}
B: 1
C: {}
D: AttributeError
```

<details><summary>解答</summary>
正解：D

解説：この問題では、集合（set）を定義しようとしていますが、誤って辞書（dict）を定義してしまっています。辞書には add()というメソッドが存在しないため、AttributeError が発生します。集合を定義する際に、以下のように書けます。

```python
a = set()
a.add(1)
print(a) # {1}
```

</details>

# 問題 6

次のコードの実行結果を選択してください。

```python
num = '12345'
print(*num, sep=', ')
```

```:選択肢
A: 12345
B: 1 2 3 4 5
C: 1,2,3,4,5
D: 1, 2, 3, 4, 5
```

<details><summary>解答</summary>
正解：D

解説：この問題では、文字列 num が与えられており、その各文字をカンマとスペースで区切って出力しています。

- \*num は、文字列 num を`展開`する構文です。展開された結果は、各文字を個別の引数として渡すことになります。
- sep は、出力する`各要素の間に挿入するセパレータ`を指定しています。ここではカンマとスペースがセパレータとなります。
- したがって、選択肢 D が正しい出力結果です。

</details>

# 問題 7

次のコードの実行結果を選択してください。

```python
text = 'I love Python!'
print(text.find('Go'))
```

```:選択肢
A: 7
B: 8
C: -1
D: 0
```

<details><summary>解答</summary>
正解：C

解説：find() メソッドは、文字列内で指定したサブ文字列を検索し、最初に見つかった位置のインデックスを返します。`見つからなかった場合は -1 `を返します。文字列 text には 'Go' というサブ文字列は存在しないため、find() メソッドは -1 を返します。

</details>

# 問題 8

次のコードの実行結果を選択してください。

```python
num = 3
l = [i for i in range(0, 21, 5)]
print(min(l, key=lambda x: abs(x - num)))
```

```:選択肢
A: 0
B: 5
C: 3
D: 10
```

<details><summary>解答</summary>
正解：B

解説：この問題では、リスト l の中から num に`最も近い要素`を見つけようとしています。

- ２行目では、`リスト内包表記`を使って、0 から 20 までの範囲を 5 ずつ増やしながら要素を生成しています。（l = [0, 5, 10, 15, 20]）
- min() 関数は、与えられた要素の中から`最小値`を返す関数です。第一引数には比較対象の要素が入るリストやイテラブルを指定します。また、`key パラメータには比較基準を指定する関数（またはラムダ式）を指定`することができます。
- min(l, key=lambda x: abs(x - num)) では、リスト l を比較対象として、各要素 x に対して abs(x - num) を計算して最小値を求めています。abs(x - num) は要素 x と num の差の絶対値を表します。つまり、num に最も近い要素を探すために差の絶対値を基準に比較しています。
- 5 が 3 に最も近いため、選択肢 B が正しいです。

</details>

# 問題 9

次のコードの実行結果を選択してください。

```python
def generate_even_numbers():
    num = 0
    while num <= 100:
        yield num
        num += 2

even_nums = generate_even_numbers()
next(even_nums)
result = next(even_nums)

print(result)
```

```:選択肢
A: 100
B: 0
C: 2
D: 4
```

<details><summary>解答</summary>
正解：C

解説：この問題では、generate_even_numbers() という`ジェネレータ`関数が定義されています。ジェネレータ関数は yield 文を含む特殊な関数であり、繰り返し可能な値を逐次生成するために使われます。

- generate_even_numbers() 関数は 0 から 100 以下の偶数を生成し続けます。ループ内では yield num という文が実行され、num の値がジェネレータから返されます。その後、num に 2 を加えることで次の偶数を生成する準備がされます。
- even_nums という変数に generate_even_numbers() を呼び出した結果を代入して、`next(even_nums)` を呼び出すことでジェネレータから`次の値を取得`しています。
- 最初の呼び出しでは 0 が返されます。
- その後、さらに next(even_nums) を呼び出すことで、次の偶数 2 が生成されます。この値が変数 result に代入されます。
- 最後に、result を出力すると、ジェネレータから取得した偶数 2 が表示されます。

</details>

# 問題 10

次のコードの実行結果を選択してください。

```python
def sample_func():
    try:
        print('try')
        return 1
    except:
        print('except')
    finally:
        print('finally')

result = sample_func()
print(result)
```

```:選択肢
A: try
   1
B: try
   finally
C: try
   1
   finally
D: try
   finally
   1
```

<details><summary>解答</summary>
正解：D

解説：

- try ブロック内で `return 文が実行されても、finally ブロックは必ず実行`されます。
- `except`ブロックは例外が発生しない限り実行されません。
- したがって、この問題では、まず、try ブロック内の 'try' という文字列が出力されます。次に、finally ブロックの 'finally' という文字列が出力されます。最後に、sample_func() 関数の戻り値である 1 が出力されます。

</details>

# 参考

- https://docs.python.org/ja/3/