吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2850|回复: 25
收起左侧

[Python 原创] (整活向)史上最复杂的Hello Python World!

[复制链接]
hrh123 发表于 2023-6-29 17:11
本帖最后由 hrh123 于 2023-6-30 18:05 编辑

print("Hello, World!"),恐怕是每个人学Python的第一个程序,这几天心血来潮,看到Hello  World就让我想到我初学编程时的样貌,于是打算简单地给它"重构"下,先亮代码:

import re
import tkinter as tk
import asyncio

class HelloWorldGUI:
    def __init__(self, master):
        self.master = master
        self.label = tk.Label(self.master)
        self.label.pack()
        self.hello_world_generator = self.hello_world()

    def hello_world(self):
        while True:
            yield "Hello, World!"

    def update_label(self):
        try:
            message = next(self.hello_world_generator)
        except StopIteration:
            self.hello_world_generator = self.hello_world()
            message = next(self.hello_world_generator)
        self.label["text"] = message

    def start(self):
        self.master.after(0, self.update_label)
        self.master.mainloop()

def coroutine_decorator(func):
    def wrapper(*args, **kwargs):
        coro = func(*args, **kwargs)
        next(coro)
        return coro

    return wrapper

@coroutine_decorator
def regex_coroutine(regex, target):
    while True:
        text = yield
        matches = re.findall(regex, text)
        for match in matches:
            target.send(match)

def main():
    root = tk.Tk()
    gui = HelloWorldGUI(root)

    regex = r"Hello, World!"

    @coroutine_decorator
    def print_match():
        while True:
            match = yield
            print(f"Match found: '{match}'")

    regex_coro = regex_coroutine(regex, print_match())
    loop = asyncio.get_event_loop()

    def schedule_regex_coroutine():
        text = gui.label["text"]
        regex_coro.send(text)
        loop.call_later(1, schedule_regex_coroutine)

    loop.call_soon(schedule_regex_coroutine)

    gui.start()

if __name__ == "__main__":
    main()

现在来详细分析下具体原理(结合代码看效果更佳):

  1. 导入必要的库,不多说了
  2. 定义一个HelloWorldGUI类,用来封装GUI
  3. 在类的初始化方法中,创建一个master属性,用于存储tkinter的根窗口对象;创建一个label属性,用于存储tkinter的标签对象,并将其添加到master中;创建一个hello_world_generator属性,用于存储一个生成器对象,该生成器可以不断产生“Hello, World!”字符串
  4. 定义一个hello_world方法,该方法使用一个while循环.不断地yield“Hello,World!”字符串,用于创建上述生成器对象
  5. 定义一个update_label方法,用于更新label的文本内容.该方法使用try-except语句,尝试从hello_world_generator中获取下一个字符串,并赋值给message变量.如果遇到StopIteration异常.说明生成器已经耗尽,那么重新创建一个新的生成器对象.并从中获取下一个字符串.然后将message变量赋值给label的text属性
  6. 定义一个start方法,用于启动GUI的主循环.该方法使用master的after方法,在0毫秒后调用update_label方法;然后使用master的mainloop方法,进入GUI的事件循环
  7. 定义一个coroutine_decorator函数,用于装饰协程函数.该函数接受一个函数作为参数,并返回一个包装函数.包装函数会调用原函数,并获取返回的协程对象.然后使用next函数预激活协程对象,并返回它
  8. 使用coroutine_decorator装饰一个regex_coroutine函数,用于创建一个协程对象,该协程可以接收文本,并使用正则表达式查找匹配结果,并将其发送给另一个目标协程.该函数接受两个参数:regex和target.regex是一个正则表达式字符串,target是另一个协程对象.该函数使用一个while循环,不断地yield等待接收文本,并使用re模块的findall函数查找匹配结果.然后使用for循环遍历匹配结果,并将其发送给target协程
  9. 定义一个main函数,用于执行主要逻辑
  10. 在main函数中,创建一个tkinter的根窗口对象,并赋值给root变量;创建一个HelloWorldGUI对象,并传入root作为参数,并赋值给gui变量
  11. 定义一个regex变量,赋值为r"Hello, World!",表示要查找的正则表达式
  12. 使用coroutine_decorator装饰一个print_match函数,用于创建一个协程对象,该协程可以接收匹配结果,并打印出来.该函数使用一个while循环,不断地yield等待接收匹配结果,并赋值给match变量.然后使用print函数打印出匹配结果
  13. 创建一个print_match协程对象,并赋值给print_match变量;创建一个regex_coroutine协程对象,并传入regex和print_match作为参数并赋值给regex_coro变量
  14. 使用asyncio模块的get_event_loop函数获取当前事件循环对象,并赋值给loop变量
  15. 定义一个schedule_regex_coroutine函数,用于定时调度regex_coro协程.该函数首先获取label的text属性,并赋值给text变量;然后使用regex_coro的send方法发送text给协程;最后使用loop的call_later方法,在1秒后再次调用schedule_regex_coroutine函数
  16. 使用loop的call_soon方法,尽快调用schedule_regex_coroutine函数
  17. 使用gui的start方法,启动GUI的主循环
  18. 代码的最后,使用if语句判断是否为主模块,如果是,则调用main函数  

最终效果:生成一个GUI,中间有一个标签,显示Hello, World!的文本


更新:相信大家已经学会了上面的基本代码,现在继续来上强度:

import asyncio
import re
import tkinter as tk

class MyDescriptor:
    def __get__(self, obj, objtype):
        print(f"Getting attribute '{self.name}'")
        return obj.__dict__[self.name]

    def __set__(self, obj, value):
        print(f"Setting attribute '{self.name}' to '{value}'")
        obj.__dict__[self.name] = value

    def __set_name__(self, owner, name):
        self.name = name

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print(f"Creating class '{name}' with bases '{bases}' and attributes '{attrs}'")
        new_attrs = {}
        for attr_name, attr_value in attrs.items():
            if isinstance(attr_value, MyDescriptor):
                attr_value.name = attr_name
            new_attrs[attr_name] = attr_value
        return super().__new__(cls, name, bases, new_attrs)

class HelloWorldGUI(metaclass=MyMeta):
    label = MyDescriptor()

    def __init__(self, master):
        self.master = master
        self.label = tk.Label(self.master)
        self.label.pack()
        self.hello_world_generator = self.hello_world()

    def hello_world(self):
        while True:
            yield "Hello, World!"

    def update_label(self):
        try:
            message = next(self.hello_world_generator)
        except StopIteration:
            self.hello_world_generator = self.hello_world()
            message = next(self.hello_world_generator)
        self.label["text"] = message

    def start(self):
        self.master.after(0, self.update_label)
        self.master.mainloop()

def coroutine_decorator(func):
    def wrapper(*args, **kwargs):
        coro = func(*args, **kwargs)
        next(coro)
        return coro

    return wrapper

@coroutine_decorator
def regex_coroutine(regex, target):
    while True:
        text = yield
        matches = re.findall(regex, text)
        for match in matches:
            target.send(match)

def main():
    root = tk.Tk()
    gui = HelloWorldGUI(root)

    regex = r"Hello, World!"

    @coroutine_decorator
    def print_match():
        while True:
            match = yield
            print(f"Match found: '{match}'")

    regex_coro = regex_coroutine(regex, print_match())
    loop = asyncio.get_event_loop()

    def schedule_regex_coroutine():
        text = gui.label["text"]
        regex_coro.send(text)
        loop.call_later(1, schedule_regex_coroutine)

    loop.call_soon(schedule_regex_coroutine)

    gui.start()

if __name__ == "__main__":
    main()

代码逻辑分析:

  1. 定义了一个自定义描述符类MyDescriptor,它重写了__get__,__set____set_name__方法,用于在获取或设置属性时打印一些信息,并将属性名和值存储在对象的__dict__
  2. 定义了一个自定义元类MyMeta,它重写了__new__方法,用于在创建类时打印一些信息,并将描述符对象的名字设置为属性名
  3. 定义了一个GUI类HelloWorldGUI,它使用了自定义元类,并定义了一个描述符属性label.它的初始化方法中,创建了一个tkinter标签对象,并将其赋值给描述符属性.它还定义了一个生成器方法hello_world,用于不断地生成"Hello,World!"字符串.它还定义了一个更新标签文本的方法update_label,用于从生成器中获取下一个字符串,并将其设置为标签的文本.最后,它定义了一个启动GUI的方法start,用于调用tkinter的定时器和主循环
  4. 定义了一个协程装饰器函数coroutine_decorator,用于在调用协程函数时自动执行一次next操作,以便激活协程
  5. 定义了一个正则匹配协程函数regex_coroutine,它接受一个正则表达式和一个目标协程作为参数.它不断地从外部接收文本,并使用正则表达式在文本中查找匹配结果.对于每个匹配结果,它将其发送给目标协程
  6. 在主函数中,创建了一个tkinter根窗口对象,并传递给GUI类的实例.然后定义了一个正则表达式字符串"Hello, World!",用于匹配"Hello, World!"中的"Hello, World!".然后定义了一个打印匹配结果的协程函数print_match,并使用协程装饰器装饰.然后创建了一个正则匹配协程对象,并将正则表达式和打印匹配结果的协程作为参数传递.然后获取了asyncio模块的事件循环对象,并定义了一个调度正则匹配协程的函数schedule_regex_coroutine.这个函数会获取当前标签的文本,并将其发送给正则匹配协程.然后使用事件循环的定时器,在一秒后再次调用这个函数.最后,使用事件循环的启动函数,在尽快执行一次调度正则匹配协程的函数之后,启动GUI

最终效果:依然是生成一个GUI,中间有一个标签,显示Hello, World!的文本

免费评分

参与人数 5吾爱币 +9 热心值 +4 收起 理由
junjia215 + 1 + 1 用心讨论,共获提升!
wushaominkk + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
dreamrise + 1 + 1 别人是helloworld,你这是hellworld
Bob5230 + 1 + 1 谢谢@Thanks!
Andrea + 1 还得是你会玩

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| hrh123 发表于 2023-6-30 17:49
本帖最后由 hrh123 于 2023-6-30 18:06 编辑

最终版代码,这次就不分析了,感兴趣的自己看看:

import asyncio
import re
import tkinter as tk

class MyDescriptor:
    def __get__(self, obj, objtype):
        print(f"Getting attribute '{self.name}'")
        return obj.__dict__[self.name]

    def __set__(self, obj, value):
        print(f"Setting attribute '{self.name}' to '{value}'")
        obj.__dict__[self.name] = value

    def __set_name__(self, owner, name):
        self.name = name

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print(f"Creating class '{name}' with bases '{bases}' and attributes '{attrs}'")
        new_attrs = {}
        for attr_name, attr_value in attrs.items():
            if isinstance(attr_value, MyDescriptor):
                attr_value.name = attr_name
            new_attrs[attr_name] = attr_value
        return super().__new__(cls, name, bases, new_attrs)

class HelloWorldGUI(metaclass=MyMeta):
    label = MyDescriptor()

    def __init__(self, master):
        self.master = master
        self.label = tk.Label(self.master)
        self.label.pack()
        self.hello_world_generator = self.hello_world()

    def hello_world(self):
        while True:
            yield "Hello, World!"

    def update_label(self):
        try:
            message = next(self.hello_world_generator)
        except StopIteration:
            self.hello_world_generator = self.hello_world()
            message = next(self.hello_world_generator)
        self.label["text"] = message

    def start(self):
        self.master.after(0, self.update_label)
        self.master.mainloop()

class coroutine_decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        coro = self.func(*args, **kwargs)
        next(coro)
        return coro

def find_matches(text, regex):
    return re.finditer(regex, text)

def regex_coroutine(regex, target):
    while True:
        text = yield
        matches = find_matches(text, regex)
        for match in matches:
            target.send(match)

def main():
    root = tk.Tk()
    gui = HelloWorldGUI(root)

    regex = r"Hello, World!"

    @coroutine_decorator
    def print_match():
        while True:
            match = yield
            print(f"Match found: '{match}'")

    regex_coro = regex_coroutine(regex, print_match())
    loop = asyncio.get_event_loop()

    def schedule_regex_coroutine():
        text = gui.label["text"]
        for match in regex_coro:
            regex_coro.send(text)
        loop.call_later(1, schedule_regex_coroutine)

    loop.call_soon(schedule_regex_coroutine)

    gui.start()

if __name__ == "__main__":
    main()
dreamrise 发表于 2023-6-30 08:58
直接复制粘贴了一个行内注释代码版
# coding:utf-8
"""最终效果:生成一个GUI,中间有一个标签,显示Hello,World!的文本
"""
import re
import tkinter as tk
import asyncio

class HelloWorldGUI:
    """定义一个HelloWorldGUI类,用来封装GUI"""
    def __init__(self, master):
        """
        在类的初始化方法中,创建一个master属性,用于存储tkinter的根窗口对象;
        创建一个label属性,用于存储tkinter的标签对象,并将其添加到master中;
        创建一个hello_world_generator属性,用于存储一个生成器对象,该生成器可以不断产生“Hello,World!”字符串
        """
        self.master = master
        self.label = tk.Label(self.master)
        self.label.pack()
        self.hello_world_generator = self.hello_world()

    def hello_world(self):
        """定义一个hello_world方法,该方法使用一个while循环.不断地yield“Hello,World!”字符串,用于创建上述生成器对象"""
        while True:
            yield "Hello, World!"

    def update_label(self):
        """定义一个update_label方法,用于更新label的文本内容.
        该方法使用try-except语句,尝试从hello_world_generator中获取下一个字符串,并赋值给message变量.
        如果遇到StopIteration异常.说明生成器已经耗尽,
        那么重新创建一个新的生成器对象.并从中获取下一个字符串.然后将message变量赋值给label的text属性
        """
        try:
            message = next(self.hello_world_generator)
        except StopIteration:
            self.hello_world_generator = self.hello_world()
            message = next(self.hello_world_generator)
        self.label["text"] = message

    def start(self):
        """定义一个start方法,用于启动GUI的主循环.该方法使用master的after方法,在0毫秒后调用update_label方法;
        然后使用master的mainloop方法,进入GUI的事件循环"""
        self.master.after(0, self.update_label)
        self.master.mainloop()

def coroutine_decorator(func):
    """
    定义一个coroutine_decorator函数,用于装饰协程函数.该函数接受一个函数作为参数,并返回一个包装函数.
    包装函数会调用原函数,并获取返回的协程对象.然后使用next函数预激活协程对象,并返回它
    """
    def wrapper(*args, **kwargs):
        coro = func(*args, **kwargs)
        next(coro)
        return coro

    return wrapper

@coroutine_decorator
def regex_coroutine(regex, target):
    """使用coroutine_decorator装饰一个regex_coroutine函数,用于创建一个协程对象,
    该协程可以接收文本,并使用正则表达式查找匹配结果,并将其发送给另一个目标协程.
    该函数接受两个参数:regex和target.
    regex是一个正则表达式字符串,target是另一个协程对象.该函数使用一个while循环,不断地yield等待接收文本,并使用re模块的findall函数查找匹配结果.然后使用for循环遍历匹配结果,并将其发送给target协程
    """
    while True:
        text = yield
        matches = re.findall(regex, text)
        for match in matches:
            target.send(match)

def main():
    """定义一个main函数,用于执行主要逻辑"""
    root = tk.Tk()
    """在main函数中,创建一个tkinter的根窗口对象,并赋值给root变量;"""

    gui = HelloWorldGUI(root)
    """创建一个HelloWorldGUI对象,并传入root作为参数,并赋值给gui变量"""

    regex = r"lo"
    """定义一个regex变量,赋值为r"lo",表示要查找的正则表达式"""

    @coroutine_decorator
    def print_match():
        """使用coroutine_decorator装饰一个print_match函数,用于创建一个协程对象,
        该协程可以接收匹配结果,并打印出来.该函数使用一个while循环,不断地yield等待接收匹配结果,并赋值给match变量.然后使用print函数打印出匹配结果"""
        while True:
            match = yield
            print(f"Match found: '{match}'")

    regex_coro = regex_coroutine(regex, print_match())
    """创建一个print_match协程对象,并赋值给print_match变量;创建一个regex_coroutine协程对象,并传入regex和print_match作为参数并赋值给regex_coro变量"""
    loop = asyncio.get_event_loop()
    """使用asyncio模块的get_event_loop函数获取当前事件循环对象,并赋值给loop变量"""

    def schedule_regex_coroutine():
        """
        定义一个schedule_regex_coroutine函数,用于定时调度regex_coro协程.
        该函数首先获取label的text属性,并赋值给text变量;
        然后使用regex_coro的send方法发送text给协程;
        最后使用loop的call_later方法,在1秒后再次调用schedule_regex_coroutine函数
        """
        text = gui.label["text"]
        regex_coro.send(text)
        loop.call_later(1, schedule_regex_coroutine)

    loop.call_soon(schedule_regex_coroutine)
    """使用loop的call_soon方法,尽快调用schedule_regex_coroutine函数"""

    gui.start()
    """使用gui的start方法,启动GUI的主循环"""

if __name__ == "__main__":
    """代码的最后,使用if语句判断是否为主模块,如果是,则调用main函数  """
    main()
px307 发表于 2023-6-29 17:22
dazhaxie 发表于 2023-6-29 18:04
狠人,事件循环用select或者epoll自己写一个

免费评分

参与人数 1热心值 +1 收起 理由
hrh123 + 1 6

查看全部评分

py学徒 发表于 2023-6-29 18:07
asyncio 是 Python 标准库中提供的一个异步编程框架。它允许您使用协程编写并发代码,通过多路复用 I/O 访问和运行网络客户端和服务器。

通过使用 asyncio,您可以编写比传统同步编程更高效和可扩展的异步代码。它使用事件循环来管理多个任务的并发执行,使您能够异步执行 I/O 操作,而不会阻塞其他任务的执行。

要使用 asyncio,通常需要使用 async 关键字将函数定义为协程,在其中等待异步操作。事件循环负责管理这些协程,安排它们的执行,并在它们等待 I/O 或其他非阻塞操作时进行切换。
头像被屏蔽
moruye 发表于 2023-6-29 18:09
提示: 作者被禁止或删除 内容自动屏蔽
myconan 发表于 2023-6-29 18:48
牛人教我学编程
諦覠 发表于 2023-6-29 18:55
第一次见到python版的复杂hello world
RainPPR 发表于 2023-6-29 21:59
记得第一次用Python编的“Hello World”是:
[Python] 纯文本查看 复制代码
printf("Hello World")

运行:
[Asm] 纯文本查看 复制代码
NameError: name 'printf' is not defined

免费评分

参与人数 1吾爱币 +1 收起 理由
hrh123 + 1 haha,欢迎讨论!

查看全部评分

jjoobb123 发表于 2023-6-30 08:35
有点复杂,膜拜下
vethenc 发表于 2023-6-30 08:46
大佬,带带我
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 19:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表