不甚了了的程序其实就是这个,
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
)是两个不同的控制字符,它们有着不同的作用和行为:
\\r
(回车):将光标移动到当前行的开头(行首),以便覆盖之前已经输出的内容。它只会移动光标,不会创建新的行。常见的应用是实现动态更新或进度条的效果。\\n
(换行):将光标移动到下一行的开头,即在当前行的末尾插入一个换行符。它会在当前行后创建一个新的行,并将光标移动到新行的开头。这是常用的用于换行的控制字符。综上所述,两者的区别在于移动光标的位置和行为:
\\r
只移动光标到行首,不会创建新的行。\\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 语言里面是一个很典型的特性。
上面这个例子,打印一下自然知晓其具体的效果了。