Python?動態(tài)創(chuàng)建一個類的示例代碼
Python 動態(tài)創(chuàng)建一個類的示例代碼:
# 動態(tài)創(chuàng)建類 # class_body 里是類里邊的函數(shù),可以寫在文件里,從文件中讀取 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動態(tài)實例化
python動態(tài)實例化
前言
最近在查一個服務的問題時,看到有一段代碼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越加越多,就這么延續(xù)下來了。
代碼邏輯其實沒什么問題,也很簡單明了,就是看起來有點丑,而且我還開了比較高的桌面縮放,導致一屏幕幾乎都是這段if ... elif
看來看去越發(fā)覺得丑,先寫個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 將指向新的子類。如果定義為一個普通實例方法,此方法將被隱式地轉換為類方法。傳給一個新類的關鍵字參數(shù)會被傳給上級類的
__init_subclass__
。 為了與其他使用__init_subclass__
的類兼容,應當去掉需要的關鍵字參數(shù)再將其他參數(shù)傳給基類。
借助這個機制,可以在實現(xiàn)抽象基類時自動注冊子類,避免手動維護注冊表。
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: """工廠函數(shù)""" 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
乍一看還是挺不錯的,但是也有個缺點,那就是如果各個類分散在不同模塊中,那么工廠函數(shù)所在的模塊就要寫一堆from xxx import ...
如果module和類命名比較規(guī)范,也可以這么動態(tài)加載類
import importlib def create_class(module_name, class_name): module = importlib.import_module(module_name) cls = getattr(module, class_name) return cls()
補充
自動注冊類看起來炫,但是對代碼閱讀來說不是很直觀。易讀還是美觀?這是一個問題。
到此這篇關于Python 動態(tài)創(chuàng)建一個類的文章就介紹到這了,更多相關Python 動態(tài)創(chuàng)建一個類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python-pymysql如何實現(xiàn)更新mysql表中任意字段數(shù)據
這篇文章主要介紹了python-pymysql如何實現(xiàn)更新mysql表中任意字段數(shù)據問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05Python使用窮舉法求兩個數(shù)的最大公約數(shù)問題
這篇文章主要介紹了Python使用窮舉法求兩個數(shù)的最大公約數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12