"""第 1 章实战代码：从 Hello World 到字节码反汇编

运行方式：
    python hello_python.py

依赖：仅需 Python 3.10+ 标准库，无第三方包。
"""
import dis
import sys
import time


def hello_world() -> None:
    """最朴素的 Hello World：感受 Python 的简洁。"""
    print("Hello, Python!")


def disassemble_demo() -> None:
    """演示用 dis 模块查看 Python 字节码。"""
    print("\n" + "=" * 60)
    print("演示 1：dis 模块反汇编一段代码")
    print("=" * 60)

    def add(a: int, b: int) -> int:
        return a + b

    print("\n源代码：")
    print("    def add(a, b):")
    print("        return a + b")

    print("\ndis.dis(add) 的输出：")
    print("-" * 60)
    dis.dis(add)
    print("-" * 60)

    print("\n字节码指令解读：")
    print("  LOAD_FAST    a   把局部变量 a 推入操作数栈")
    print("  LOAD_FAST    b   把局部变量 b 推入操作数栈")
    print("  BINARY_OP    +   弹出栈顶两个值相加，结果推回栈")
    print("  RETURN_VALUE     弹出栈顶作为返回值")


def show_python_info() -> None:
    """打印当前 Python 解释器的关键信息。"""
    print("\n" + "=" * 60)
    print("演示 2：当前 Python 环境信息")
    print("=" * 60)

    print(f"  Python 版本   : {sys.version.split()[0]}")
    print(f"  实现名称      : {sys.implementation.name}  (CPython / PyPy / Jython 等)")
    print(f"  字节码版本    : magic = {sys.implementation.cache_tag}")
    print(f"  可执行文件    : {sys.executable}")
    print(f"  操作系统平台  : {sys.platform}")
    print(f"  最大递归深度  : {sys.getrecursionlimit()}")


def show_pyc_cache() -> None:
    """演示首次运行后会生成 __pycache__ 目录。"""
    print("\n" + "=" * 60)
    print("演示 3：__pycache__ 字节码缓存")
    print("=" * 60)
    print("""
    第一次运行模块时，Python 会把编译好的字节码缓存到：
        __pycache__/<模块名>.cpython-<版本>.pyc

    下次运行时，如果源文件没改（比对 mtime），直接读 .pyc 跳过编译。
    这就是 Python 启动比第一次"略快一点"的秘密。

    试试看：
        $ python -c "import dis; print('hi')"
        $ ls __pycache__/
    """)


def benchmark_print(n: int = 100_000) -> None:
    """对比 print 多次调用 vs 一次构造大字符串的性能差异。

    这是一个从一开始就培养"性能感觉"的小练习。
    """
    print("\n" + "=" * 60)
    print(f"演示 4：性能小实验（n={n:,} 次输出）")
    print("=" * 60)

    # 写入临时缓冲，避免刷屏
    import io

    buf = io.StringIO()

    t0 = time.perf_counter()
    for i in range(n):
        print(i, file=buf, end="")
    t1 = time.perf_counter()
    print(f"  方式 A: 循环 {n:,} 次 print  耗时 {(t1 - t0) * 1000:.2f} ms")

    buf2 = io.StringIO()
    t0 = time.perf_counter()
    chunk = "".join(str(i) for i in range(n))
    print(chunk, file=buf2, end="")
    t1 = time.perf_counter()
    print(f"  方式 B: join 后 1 次 print  耗时 {(t1 - t0) * 1000:.2f} ms")

    print("\n  结论：Python 函数调用本身有开销，能批量做就别循环做。")


def the_zen_of_python() -> None:
    """打印 Python 之禅 —— 这是 Python 的设计哲学。"""
    print("\n" + "=" * 60)
    print("演示 5：Python 之禅 (彩蛋)")
    print("=" * 60)
    import this  # noqa: F401  导入即触发打印


def main() -> None:
    print("=" * 60)
    print(" Python 第 1 章 · Hello World & 字节码探秘")
    print("=" * 60)

    hello_world()
    disassemble_demo()
    show_python_info()
    show_pyc_cache()
    benchmark_print()
    the_zen_of_python()

    print("\n" + "=" * 60)
    print(" 跑完了！下一步建议：")
    print("   1) 用 python -m dis hello_python.py 反汇编整个文件")
    print("   2) 修改 add 函数为乘法，再看字节码变化")
    print("   3) 打开同目录下的 demo.html，体验可视化执行流程")
    print("=" * 60)


if __name__ == "__main__":
    main()
