# GESP等级：一级 | GESP Python 一级考点
"""
第5课·第1节 —— 四种类型：int/float/str/bool + None
课程对应：
  - 00:00-10:00 导入：turtle场景四种类型各用一遍
  - 30:00-40:00 演示：print(type("red")) → str / print(type(6)) → int
  - 记忆钩子："str穿引号 int光膀子 float小数点 bool是/否 None空盒子"
  - GESP 考点：#28 数据类型基本概念

运行方式：
  每个函数独立运行，按教学节奏调用。
"""

import turtle
import time

# ============================================================
# 阶段一：导入——turtle场景四种类型（00:00-10:00）
# ============================================================
def demo_turtle_four_types():
    """
    用turtle画彩色多边形，展示str/int/float/bool四种类型。
    老师逐行讲解每个值的"长相特征"。
    """
    t = turtle.Turtle()
    t.speed(5)

    # ========== 第1种类型：str（字符串）= 文字穿引号 ==========
    # 颜色名"red"被引号包着——这就是str的特征
    color_name = "red"       # ← str！看，有引号！
    t.color(color_name)
    print(f"1️⃣  color_name = {color_name!r}")
    print(f"   type(color_name) → {type(color_name)}")
    print(f"   👉 \"red\" 穿了引号 → 这是 str（字符串）\n")

    # ========== 第2种类型：int（整数）= 光膀子整数 ==========
    # 边数6没有引号、没有小数点——光膀子整数
    sides = 6               # ← int！光膀子！
    print(f"2️⃣  sides = {sides}")
    print(f"   type(sides) → {type(sides)}")
    print(f"   👉 6 光膀子没有引号 → 这是 int（整数）\n")

    # ========== 第3种类型：float（浮点数）= 带小数点 ==========
    # 360/6=60.0，带了小数点——这是float
    angle = 360 / sides     # ← float！有小数点！
    print(f"3️⃣  angle = {angle}")
    print(f"   type(angle) → {type(angle)}")
    print(f"   👉 60.0 带小数点 → 这是 float（浮点数）\n")

    # ========== 第4种类型：bool（布尔值）= 是/否 ==========
    # True/False —— 只有两个值，大写开头
    pen_down = True         # ← bool！是/否！
    print(f"4️⃣  pen_down = {pen_down}")
    print(f"   type(pen_down) → {type(pen_down)}")
    print(f"   👉 True 是/否 → 这是 bool（布尔值）\n")

    # ========== 用这些值来画画 ==========
    print("🎨 开始画一个正六边形...\n")

    if pen_down:          # bool 作为条件判断
        t.pendown()
    else:
        t.penup()

    for i in range(sides):  # int 控制循环次数
        t.forward(100)
        t.left(angle)       # float 控制旋转角度

    # ========== 第5种类型：None（空盒子） ==========
    # 没有颜色——None 表示"什么都没有"
    print("5️⃣  None = 空盒子——里面什么都没有")
    print(f"   type(None) → {type(None)}")
    print(f"   👉 试试 t.color(None) → 没有颜色\n")

    # 用 None 演示：不设置颜色，绘制第二个图形
    t.penup()
    t.goto(-200, -100)
    t.pendown()
    t.color(None)  # None 作为颜色 → 没有颜色（透明）
    t.write("None = 空盒子", font=("Arial", 16, "normal"))

    print("🎯 五种类型展示完毕！")
    print("记忆钩子：str穿引号 🙌 int光膀子 💪 float小数点 👆 bool是/否 👍👎 None空盒子 🖐️")

    turtle.done()


# ============================================================
# 阶段三：演示——type() 照妖镜（30:00-40:00）
# ============================================================
def demo_type_function():
    """
    演示 type() 函数的用法——type()是"照妖镜"，
    照一下就知道值是什么类型。
    """
    print("=" * 60)
    print("🔍 type() 照妖镜——一照就知道是什么类型！")
    print("=" * 60)

    # === 演示1：5种基本类型的type() ===
    print("\n--- 演示1：5种基本类型 ---")

    values = [
        ("\"red\"", "red"),        # str
        ("6", 6),                  # int
        ("3.14", 3.14),            # float
        ("True", True),            # bool
        ("None", None),            # NoneType
    ]

    for label, val in values:
        result = type(val)
        print(f"   type({label:12s}) → {result}")
        # 记忆钩子提示
        hint = {
            str: "← 🙌 str 穿引号！",
            int: "← 💪 int 光膀子！",
            float: "← 👆 float 带小数点！",
            bool: "← 👍👎 bool 是/否！",
            type(None): "← 🖐️ None 空盒子！",
        }
        print(f"      {hint.get(type(val), '')}")

    # === 演示2：区分 "6" 和 6 和 6.0（重点！） ===
    print("\n--- 演示2：\"6\" vs 6 vs 6.0 的区别 ---")

    print("   \"6\" 穿了引号 → ", end="")
    print(f"type(\"6\") = {type('6')}  ← str")

    print("   6 光膀子 → ", end="")
    print(f"type(6) = {type(6)}  ← int")

    print("   6.0 带小数点 → ", end="")
    print(f"type(6.0) = {type(6.0)}  ← float")

    print("\n   💡 长得像但类型不同！")
    print("      \"6\" 是文字（str）——可以拼接成 \"66\"")
    print("      6 是数字（int）——可以做加法 6+6=12")
    print("      6.0 是小数（float）——6.0+6.0=12.0")

    # === 演示3：更多例子 ===
    print("\n--- 演示3：试试更多值 ---")

    more_values = [
        ("\"你好\"", "你好"),
        ("100", 100),
        ("-0.5", -0.5),
        ("False", False),          # bool 的第二个值
        ("\"\" (空字符串)", ""),
        ("0", 0),                  # int 的0
        ("0.0", 0.0),              # float 的0
    ]

    for label, val in more_values:
        print(f"   type({label:15s}) → {type(val)}")

    print("\n" + "=" * 60)
    print("🎯 总结：type() 是照妖镜——一照就知道是什么类型！")
    print("=" * 60)


# ============================================================
# 阶段三补充：type() 返回值的类型也是 type（趣味知识）
# ============================================================
def demo_type_of_type():
    """类型的类型——趣味拓展，让学生知道 type 本身也是一个类型"""
    print("=" * 60)
    print("🤯 拓展：类型的类型也是类型！")
    print("=" * 60)

    t_str = type("red")
    print(f"   type(\"red\") → {t_str}")
    print(f"   type({t_str}) → {type(t_str)}  ← 类型的类型是 type！")

    print("\n   就像盒子的盒子也是盒子一样！😄")


# ============================================================
# 阶段三补充：用 turtle 演示 type 的直观理解
# ============================================================
def demo_turtle_type_show():
    """
    用turtle在画布上写出每个值的类型——视觉化 type() 的结果。
    适合在大屏幕上投影，全班一起看。
    """
    t = turtle.Turtle()
    t.speed(5)
    t.penup()

    # 设置位置和字体
    start_y = 200
    items = [
        ("type(\"red\")", str, -300, start_y),
        ("type(6)", int, -300, start_y - 60),
        ("type(3.14)", float, -300, start_y - 120),
        ("type(True)", bool, -300, start_y - 180),
        ("type(None)", type(None), -300, start_y - 240),
    ]

    for label, typ, x, y in items:
        t.goto(x, y)
        t.pendown()
        # 写代码
        t.write(f">>> {label}", font=("Consolas", 14, "normal"))
        t.penup()

        t.goto(x + 50, y - 35)
        t.pendown()
        # 写结果
        result = f"<class '{typ.__name__}'>"
        t.color("blue")
        t.write(result, font=("Consolas", 14, "normal"))
        t.color("black")
        t.penup()

    # 在底部写记忆钩子
    t.goto(-300, start_y - 320)
    t.pendown()
    t.color("green")
    t.write("记忆钩子：str穿引号 int光膀子 float小数点 bool是/否 None空盒子",
            font=("Arial", 16, "bold"))
    t.color("black")
    t.penup()

    turtle.done()


# ============================================================
# 阶段二补充：is vs == ——双胞胎 vs 同一个人（10:00-30:00 知识点⑥）
# ============================================================
def demo_is_vs_equals():
    """
    演示 is（身份比较）和 ==（值比较）的区别。
    GESP考点补充：is 和 == 的差异。
    """
    print("=" * 60)
    print("🔍 is vs ==：双胞胎 vs 同一个人")
    print("=" * 60)

    # === 演示1：基本类型 ===
    print("\n--- 演示1：基本类型 ---")

    a = 100
    b = 100

    print(f"   a = {a}, b = {b}")
    print(f"   a == b → {a == b}  ← 值相等（双胞胎长得一样）")
    print(f"   a is b → {a is b}  ← Python对小整数复用同一个对象")

    print("\n   💡 对于小整数（-5到256），Python会重复使用同一个对象")
    print("      所以 a is b 也是 True")

    # === 演示2：用列表展示区别 ===
    print("\n--- 演示2：列表的 is vs == ——关键区别！ ---")

    list_a = [1, 2, 3]
    list_b = [1, 2, 3]  # 和 list_a 内容一样，但是另一个盒子
    list_c = list_a      # list_c 就是 list_a

    print(f"   list_a = {list_a}")
    print(f"   list_b = {list_b}  ← 内容一样，但新盒子")
    print(f"   list_c = list_a    ← list_c 就是 list_a 的别名\n")

    print(f"   list_a == list_b → {list_a == list_b}  ← 值相等 ✅")
    print(f"   list_a is list_b → {list_a is list_b}  ← 不同对象 ❌\n")
    print(f"   list_a == list_c → {list_a == list_c}  ← 值相等 ✅")
    print(f"   list_a is list_c → {list_a is list_c}  ← 同一个对象 ✅\n")

    # === 演示3：None 的最佳实践 ===
    print("--- 演示3：None 比较——永远用 is None ---")

    x = None

    print(f"   x = {x}")
    print(f"   x is None     → {x is None}      ← ✅ 推荐的写法")
    print(f"   x == None     → {x == None}      ← ⚠️ 也能用但不推荐")

    y = 0
    print(f"\n   y = {y}")
    print(f"   y is None     → {y is None}     ← ✅ None 身份不同")
    print(f"   y == None     → {y == None}     ← ✅ 值也不同")

    print("\n" + "=" * 60)
    print("🎯 记忆口诀：==两个等号比内容，is一个身份查到底")
    print("   比较None时，永远用 is None！")
    print("=" * 60)


# ============================================================
# 入口
# ============================================================
if __name__ == "__main__":
    print("🐢 第5课·第1节 —— 四种类型：int/float/str/bool + None")
    print("=" * 60)
    print()
    print("请选择要运行的功能：")
    print("  1 - turtle场景四种类型导入（00:00-10:00 阶段）")
    print("  2 - type() 照妖镜演示（30:00-40:00 阶段）")
    print("  3 - type 的类型趣味拓展")
    print("  4 - turtle 可视化 type 展示")
    print("  5 - is vs == 身份比较演示（知识点⑥）")
    print()

    try:
        choice = int(input("请输入数字 (1-4)，直接回车默认 2: ") or "2")
    except (ValueError, EOFError):
        choice = 2

    print()

    if choice == 1:
        demo_turtle_four_types()
    elif choice == 2:
        demo_type_function()
    elif choice == 3:
        demo_type_of_type()
    elif choice == 4:
        demo_turtle_type_show()
    elif choice == 5:
        demo_is_vs_equals()
    else:
        print("无效选择，运行默认演示2")
        demo_type_function()
