python - 这是对元类的有效使用吗
问题描述
我一直在看一些关于装饰器和元类的视频,我想我现在对它们有了更好的理解。我拿走的一个格言是“如果你可以在不使用元类的情况下更简单地做到这一点,就不要使用元类”。前段时间我写了一个元类,但并没有真正理解我在做什么,我回去复习了它。我很确定我在这里做了一些明智的事情,但我想我会检查....
PS 我有点担心在Metaclass定义中使用了 Color 类,我觉得它应该在Class级别使用,但这会使代码复杂化。
import webcolors
# This is a holding class for demo purposes
# actual code allows much more, eg 0.3*c0 + 0.7*c1
class Colour(list):
def __init__(self,*arg):
super().__init__(arg)
# define a metaclass to implement Class.name
class MetaColour(type):
def __getattr__(cls,name):
try:
_ = webcolors.name_to_rgb(name)
return Colour(_.blue,_.green,_.red)
except ValueError as e:
raise ValueError(f"{name} is not a valid name for a colour ({e})")
return f"name({name})"
# a class based on the metaclass MetaColour
class Colours(metaclass=MetaColour):
pass
print("blue = ",Colours.blue)
print("green = ",Colours.green)
print("lime = ",Colours.lime)
print("orange = ",Colours.orange)
print()
print("lilac = ",Colours.lilac)
编辑:我意识到我可以编写 Color 类,以便 Colour("red") 等同于 Colours.red 但当时觉得使用 Colours.red 更优雅,并添加了 Color 'red' 是恒定的,而不是必须查找并且可以变化的东西。
解决方案
如果你真的需要Colours
成为一个类,那么这个元类就可以完成它的工作——而且看起来还不错。在Colour
里面使用完全没有问题——没有“元类代码不能使用任何‘普通’类”之类的东西——它像往常一样是 Python 代码。
我要说的是,也许您不需要将其Colours
用作类,而只需创建Colours
具有您需要的所有功能的类,并创建它的单个实例。其余代码将使用此实例而不是 Colors 类。
是的,单个实例是“单例模式”——但与一些复杂的代码不同,您可以找到有关如何使您的类“成为单例”的信息(包括一些广泛传播的关于需要元类在 Python 中具有单例的不良做法) ),您可以只创建实例,为其分配一个名称,然后完成它。就像在您的示例中一样,您拥有正在使用的“webcolors”对象。
为了获得额外的单例奖励,您可以将 Colors 的单个实例命名为Colours
,并隐藏该类,以防止意外使用该类而不是该实例。
(而且,虽然这可能很明显,但为了完整起见:在“使用颜色作为实例”的情况下,根本不需要这个元类 - 相同的__getattr__
方法进入类主体)
当然,同样,如果您将 Colors 用作一个类,那么这种设计没有问题。
推荐阅读
- javascript - MongoDB 与 nodejs 的连接返回承诺
- spring-boot - Spring Batch 将 FlatFileItemReader 与数据库读取相结合
- powerbi - 是否可以在群集柱形图 Power BI 上添加可编辑/可移动的水平线?
- python - 选择具有多个重复字段值的行
- python - 为自定义子命令 discord.py 编写函数
- python - 在 EXE 中运行 Python 应用程序时,我得到 .. 'vba_extract.py' 无法识别
- r - 如何在仅属于刻面的刻面堆积条形图中显示 x 轴标签?
- reactjs - 反应 | 选择金额
- pascal - 有没有办法找出在运行时运行可执行文件的位置?
- php - 如何使用 get 方法删除此 Laravel 表单