这是元类的有效用法吗

2024-04-20 05:11:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在看一些关于装饰器和元类的视频,我想我现在更了解它们了。我带走的一条格言是“如果不使用元类就可以做得更简单,那么就不要使用元类”。不久前,我写了一个元类,却没有真正理解我在做什么,于是我回去复习了它。我很确定我在这里做了一些明智的事情,但我想我应该检查一下

PS我有点担心COLOR类在元类定义中使用,我觉得应该在级别使用,但这会使代码复杂化

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)

编辑:我意识到我可以编写颜色类,这样颜色(“红色”)就等同于colors.red,但当时觉得使用colors.red更优雅,并添加了颜色“red”是一个常量的含义,而不是必须查找和变化的东西


Tags: nameforis颜色defgreenbluered
1条回答
网友
1楼 · 发布于 2024-04-20 05:11:18

如果您真的需要Colours成为一个类,那么这个元类就完成了它的工作——而且看起来很好。在它里面使用Colour一点问题都没有——没有“元类代码不能使用任何‘普通’类”这样的东西——它是Python代码

我想说的是,也许你不需要使用Colours作为一个类,而只需要创建Colours类,以及你需要的所有功能,并创建它的一个实例。代码的其余部分将使用此实例而不是colors类

是的,单个实例就是“单例模式”——但与一些复杂的代码不同,您可以找到一些关于如何使类“成为单例”(包括一些广泛传播的关于需要元类才能在Python中拥有单例的错误实践),您只需创建实例,将其分配给一个名称,然后就可以使用它了。就像在您的示例中一样,您使用的是“WebColor”对象

为了获得额外的单例奖励,您可以将colors的单个实例命名为Colours,并对该类进行阴影处理,以防止意外使用该类而不是实例

(而且,尽管这可能是显而易见的,但为了完整性:在“使用颜色作为实例”的情况下,根本不需要这个元类-相同的__getattr__方法进入类主体)

当然,同样,如果你把颜色作为一个类来使用,这个设计没有问题

相关问题 更多 >