不甚了了的程序其实就是这个,

import itertools
import time
from threading import Thread, Event

def spin(msg: str, done: Event) -> None:
    for char in itertools.cycle(R"\\|/-"):
        status = f"\\r{char} {msg}"
        print(status, end="", flush=True)
        if done.wait(0.1):
            break
    blanks = " " * len(status)
    print(f"\\r{blanks}\\r", end="")

def slow() -> int:
    time.sleep(3)
    return 42

def supervisor() -> int:
    done = Event()
    spinner = Thread(target=spin, args=("thinking!", done))
    print(f"spinner object: {spinner}")
    spinner.start()
    result = slow()  # 这里函数是在执行,睡眠 3 秒
    done.set()
    spinner.join()
    return result

def main() -> None:
    result = supervisor()
    print(f"Answer: {result}")

if __name__ == "__main__":
    main()

问题一,itertools.cycle() 的作用。

其实就是循环地生产迭代器啦。

问题二,字符串大写的 R 前缀。

书上是小写,这里我是为了照顾 VSCode 的 Python 插件,所以改成大写。就单纯记录一下,防止遗忘。其实不算是问题。

问题三,\\r 的作用。

\\r 和换行(\\n)是两个不同的控制字符,它们有着不同的作用和行为:

  1. \\r(回车):将光标移动到当前行的开头(行首),以便覆盖之前已经输出的内容。它只会移动光标,不会创建新的行。常见的应用是实现动态更新或进度条的效果。
  2. \\n(换行):将光标移动到下一行的开头,即在当前行的末尾插入一个换行符。它会在当前行后创建一个新的行,并将光标移动到新行的开头。这是常用的用于换行的控制字符。

综上所述,两者的区别在于移动光标的位置和行为:

在实际应用中,常常会使用\\r\\n结合使用,例如,\\r\\n表示在当前行的末尾插入一个换行符,并将光标移动到新行的开头,实现在下一行开始输出内容的效果。

需要注意的是,不同的操作系统和文本处理环境对于换行的表示可能略有不同。在Unix/Linux系统中,通常使用\\n表示换行;而在Windows系统中,通常使用\\r\\n表示换行。Python中,无论在哪个平台上运行,都可以使用\\n表示换行,因为Python会自动处理跨平台的换行符。

问题四,print() 函数的 flush 参数究竟有什么用?我需要具体的例子。

具体的例子就是这个,

import time

print("Loading", end="")
time.sleep(1)

print(".", end="", flush=True)
time.sleep(1)
print(".", end="", flush=True)
time.sleep(1)
print(".", flush=True)

print(".", end="")
time.sleep(1)
print(".", end="")
time.sleep(1)
print(".")

sleep() 会让要打印的内容缓存起来,最后作一起打印,而把 flush 参数设置成 True 就是即时打印。这个在 C 语言里面是一个很典型的特性。

上面这个例子,打印一下自然知晓其具体的效果了。