Pythonのクラス変数とメンバ変数の更新について速度と挙動が気になった

## コード
``` python3
import time

## Color codes
YELLOW = "\033[33m"
CYAN = "\033[36m"
END = "\033[0m"


class TestClass:
    loop_fps = 60

    def modal_class_v(self, fps):
        time_start = time.perf_counter()
        TestClass.loop_fps = fps
        print(f"Instance: {self.loop_fps}fps")
        print(f"Class: {TestClass.loop_fps}fps")
        time_end = time.perf_counter()
        print(f"{YELLOW}modal_class_v(): {time_end - time_start}sec{END}")

    def modal_instance_v(self, fps):
        time_start = time.perf_counter()
        self.loop_fps = fps
        print(f"Instance: {self.loop_fps}fps")
        print(f"Class: {TestClass.loop_fps}fps")
        time_end = time.perf_counter()
        print(f"{CYAN}modal_instance_v(): {time_end - time_start}sec{END}")

    def modal_print(self):
        time_start = time.perf_counter()
        print(f"Instance: {self.loop_fps}fps")
        time_instance_v = time.perf_counter()
        print(f"Class: {TestClass.loop_fps}fps")
        time_class_v = time.perf_counter()
        print(f"print Instance: {time_instance_v - time_start}sec")
        print(f"print Class: {time_class_v - time_instance_v}sec")


op = TestClass()
op.modal_class_v(10)
op.modal_print()
op.modal_instance_v(25)
op.modal_print()
op.modal_class_v(10)
op.modal_print()
op.modal_instance_v(20)
```
#### 実行環境
3.9.10 | packaged by conda-forge | (main, Feb  1 2022, 21:27:43) 
[Clang 11.1.0 ]
macOS-13.4.1-arm64-i386-64bit

## 実行結果
``` bash
>>> op.modal_class_v(10)
Instance: 10fps
Class: 10fps
modal_class_v(): 1.2957999842910795e-05sec
>>> op.modal_print()
Instance: 10fps
Class: 10fps
print Instance: 1.4290999843069585e-05sec
print Class: 1.9590002011682373e-06sec
>>> op.modal_instance_v(25)
Instance: 25fps
Class: 10fps
modal_instance_v(): 6.583999947906705e-06sec
>>> op.modal_print()
Instance: 25fps
Class: 10fps
print Instance: 7.04200010659406e-06sec
print Class: 2.3749998945277184e-06sec
>>> op.modal_class_v(10)
Instance: 25fps
Class: 10fps
modal_class_v(): 1.7374999970343197e-05sec
>>> op.modal_print()
Instance: 25fps
Class: 10fps
print Instance: 6.999999641266186e-06sec
print Class: 2.166000285797054e-06sec
>>> op.modal_instance_v(20)
Instance: 20fps
Class: 10fps
modal_instance_v(): 8.874999821273377e-06sec
```
## 議論
### 実行順序について
1. 最初に`modal_class_v(10)`が実行され、クラス変数`loop_fps`が10に設定されます。この時点で、このクラスから生成されるすべてのインスタンスに対して`loop_fps`が10であるという共通の状態が設定されます。

2. 次に`modal_print()`が実行され、インスタンス変数とクラス変数の値が出力されます。この時点では、インスタンス変数`loop_fps`はまだ設定されていないため、クラス変数の値が出力され、両方とも10と表示されます。

3. `modal_instance_v(25)`が実行され、特定のインスタンスの`loop_fps`が25に設定されます。この操作は、そのインスタンスにのみ影響を与え、クラス変数や他のインスタンスには影響しません。その結果、インスタンスの`loop_fps`は25、クラス変数の`loop_fps`は依然として10となります。

4. 再び`modal_class_v(10)`が実行されますが、この時点で特定のインスタンスには既に独自の`loop_fps`が設定されているため、クラス変数の更新はそのインスタンスには影響しません。そのため、インスタンス変数は25のまま、クラス変数は10となります。

5. 最後に`modal_instance_v(20)`が実行され、特定のインスタンスの`loop_fps`が20に更新されます。これにより、そのインスタンスの`loop_fps`は20となり、クラス変数の`loop_fps`は10のままです。

### 実行時間について
`modal_class_v`メソッドと`modal_instance_v`メソッドの実行時間を見てみます。これらのメソッドは、クラス変数とインスタンス変数を更新するために呼び出されています。

- `modal_class_v`の実行時間は、最初の呼び出しで約1.30e-05秒、2回目の呼び出しで約1.74e-05秒でした。
- `modal_instance_v`の実行時間は、最初の呼び出しで約6.58e-06秒、2回目の呼び出しで約8.87e-06秒でした。

ここから、`modal_class_v`メソッドの実行時間が`modal_instance_v`メソッドよりも若干長いことがわかります。

また、`modal_print`メソッドの実行時間を見てみます。このメソッドは、インスタンス変数とクラス変数の値を単に出力するだけです。

- `print Instance`の実行時間は、最初の呼び出しで約1.43e-05秒、2回目で約7.04e-06秒、3回目で約7.00e-06秒でした。
- `print Class`の実行時間は、最初の呼び出しで約1.96e-06秒、2回目で約2.37e-06秒、3回目で約2.17e-06秒でした。

ここから、インスタンス変数とクラス変数の値を出力するのにかかる時間も非常に短いことがわかります。また、`print Class`の方が`print Instance`よりも若干短い時間であることがわかります。