Python 动态创建一个类的示例代码

 更新时间:2025年06月19日 08:47:52   作者:JHC000000  
这篇文章主要介绍了Python 动态创建一个类的示例代码,通过实例代码补充介绍了python动态实例化的相关知识,需要的朋友可以参考下

Python 动态创建一个类的示例代码:

# 动态创建类
# class_body 里是类里边的函数,可以写在文件里,从文件中读取
class_body = """
def running_function(self):
    print(self.name)
    print("running function")
def set_name(self,name):
    self.name = name
"""
class_dict = {}
# 加载类方法到class_dict里
exec(class_body,globals(),class_dict)
# 把class_dict中的方法加载到类里边
Customer = type("Customer",(object,),class_dict)
# 实例化类,调用类方法
c = Customer()
c.set_name("12")
c.running_function()

补充:python动态实例化

python动态实例化

前言

最近在查一个服务的问题时,看到有一段代码if .. elif ... 写了近百行,类似

if command == "xxx":
	obj = CommandX()
	obj.run()
	# ...
elif command == "yyy":
	obj = CommandY()
	obj.run()
    # ...
elif command == "zzz":
	obj = CommandZ()
	obj.run()
    # ...
# ...

翻了下git记录,最开始其实只有两三个条件判断,后来command越加越多,就这么延续下来了。

代码逻辑其实没什么问题,也很简单明了,就是看起来有点丑,而且我还开了比较高的桌面缩放,导致一屏幕几乎都是这段if ... elif

看来看去越发觉得丑,先写个demo看看能不能跑通代码。

方式1, 字典映射

如果需要判断的条件比较少,用字典做映射还是挺方便的,但如果条件多,看起来还是挺丑的。

from abc import ABC, abstractmethod
class AbstractCommand(ABC):
    @abstractmethod
    def run(self):
        pass
class CommandA(AbstractCommand):
    def run(self):
        return "this is command A"
class CommandB(AbstractCommand):
    def run(self):
        return "this is command B"
class CommandC(AbstractCommand):
    def run(self):
        return "this is command C"
class CommandFactory:
    @staticmethod
    def create_command(command_type: str) -> AbstractCommand:
        command_mapping = {
            "cmda": CommandA,
            "cmdb": CommandB,
            "cmdc": CommandC
        }
        cls = command_mapping.get(command_type.lower())
        if not cls:
            raise ValueError(f"Unknown command type: {command_type}")
        return cls()
if __name__ == "__main__":
    cmd = CommandFactory.create_command("cmda")
    assert cmd.run() == "this is command A"
    cmd = CommandFactory.create_command("cmdb")
    assert cmd.run() == "this is command B"
    cmd = CommandFactory.create_command("cmdc")
    assert cmd.run() == "this is command CD"  # should be exception
    cmd = CommandFactory.create_command("cmdd")  # should be exception
    assert cmd.run() == "this is command D"

方式2, __init_subclass__

《流畅的Python(第2版)》的最后一章提到了这个__init__subclass__,根据python官方文档:

当所在类派生子类时此方法就会被调用。cls 将指向新的子类。如果定义为一个普通实例方法,此方法将被隐式地转换为类方法。传给一个新类的关键字参数会被传给上级类的 __init_subclass__。 为了与其他使用 __init_subclass__ 的类兼容,应当去掉需要的关键字参数再将其他参数传给基类。

借助这个机制,可以在实现抽象基类时自动注册子类,避免手动维护注册表。

from abc import ABCMeta, abstractmethod
from threading import Lock
from collections import UserDict
class ThreadSafeDict(UserDict):
    """线程安全的字典"""
    def __init__(self):
        super().__init__()
        self._lock = Lock()
    def __setitem__(self, key, item):
        with self._lock:
            super().__setitem__(key, item)
class Command(metaclass=ABCMeta):
    registry = ThreadSafeDict()
    def __init__(self):
        pass
    @abstractmethod
    def run(self):
        pass
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.registry[cls.__name__.lower()] = cls  # 自动注册子类
# 子类定义即自动注册
class CommandA(Command):
    def run(self):
        return "this is command a!"
class CommandB(Command):
    def run(self):
        return "this is command b!"
class CommandC(Command):
    def run(self):
        return "this is command b!"
def create_command(command_type: str) -> Command:
    """工厂函数"""
    cls = Command.registry.get(command_type.lower())
    if not cls:
        raise ValueError(f"Unknown command type: {command_type}")
    return cls()
if __name__ == "__main__":
    cmd = create_command("CommandA")
    assert cmd.run() == "this is command a!"
    cmd = create_command("CommandB")
    assert cmd.run() == "this is command b!"
    cmd = create_command("CommandC")
    assert cmd.run() == "this is command cc!"  # should be exception
    cmd = create_command("CommandD")
    assert cmd.run() == "this is command b!"  # should be exception

乍一看还是挺不错的,但是也有个缺点,那就是如果各个类分散在不同模块中,那么工厂函数所在的模块就要写一堆from xxx import ...

如果module和类命名比较规范,也可以这么动态加载类

import importlib
def create_class(module_name, class_name):
    module = importlib.import_module(module_name)
    cls = getattr(module, class_name)
    return cls()

补充

自动注册类看起来炫,但是对代码阅读来说不是很直观。易读还是美观?这是一个问题。

到此这篇关于Python 动态创建一个类的文章就介绍到这了,更多相关Python 动态创建一个类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python-pymysql如何实现更新mysql表中任意字段数据

    python-pymysql如何实现更新mysql表中任意字段数据

    这篇文章主要介绍了python-pymysql如何实现更新mysql表中任意字段数据问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Python使用穷举法求两个数的最大公约数问题

    Python使用穷举法求两个数的最大公约数问题

    这篇文章主要介绍了Python使用穷举法求两个数的最大公约数问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • django最快程序开发流程详解

    django最快程序开发流程详解

    这篇文章主要介绍了django最快程序开发流程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 基于Python实现加强版烟花

    基于Python实现加强版烟花

    这篇文章主要为大家详细介绍了如何利用Python制作一个加强版烟花景,文中的示例代码讲解详细,对我们学习Python有一定帮助,需要的可以参考一下
    2022-02-02
  • pytest自动化测试中的fixture的声明和调用

    pytest自动化测试中的fixture的声明和调用

    这篇文章主要为大家介绍了pytest自动化测试中的fixture的声明和调用,文中含有详细示例操作有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • Python中循环依赖问题及其解决方案

    Python中循环依赖问题及其解决方案

    在软件开发中,循环依赖是一个常见的问题,尤其是在使用 Python 这样的动态语言时,循环依赖指的是两个或多个模块或组件相互依赖,形成一个闭环,本文将探讨 Python 中循环依赖的问题,并提供一些解决方案,需要的朋友可以参考下
    2024-06-06
  • 人生苦短我用python python如何快速入门?

    人生苦短我用python python如何快速入门?

    这篇文章主要教大家如何快速入门python,一个简短而全面的入门教程带你走入Python的大门,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • python调用自定义函数的实例操作

    python调用自定义函数的实例操作

    在本文里我们给大家整理了关于python调用自定义函数的实例操作相关内容,有此需要的朋友们可以学习参考下。
    2019-06-06
  • Python3实现的简单三级菜单功能示例

    Python3实现的简单三级菜单功能示例

    这篇文章主要介绍了Python3实现的简单三级菜单功能,涉及Python用户交互以及针对json格式数据的遍历、读取、判断等相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • Python网络爬虫之Web网页基础

    Python网络爬虫之Web网页基础

    我们在学习爬虫之前,要先了解网页的组成,只有我们了解其组成吗,才可以方能百战百胜,文章中有详细的代码示例,需要的朋友可以参考一下
    2023-04-04

最新评论