Python:常量类

Gab*_*lin 7 python enums class

我正在研究这个问题的答案: 是否可以在Enum中定义一个类常量?

最让我感兴趣的是Ethan Furman答案中的Constant课程.

class Constant:
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)
Run Code Online (Sandbox Code Playgroud)

问题是关于Python 3.4,但我使用的是2.7.在答案中,Ethan将引力常数设置为Planet类的实例变量,如下所示:

G = Constant(6.67300E-11)
Run Code Online (Sandbox Code Playgroud)

我在2.7中对这个类的测试表明只输入G就是这样:

Out[49]: Constant(3)
Run Code Online (Sandbox Code Playgroud)

(我将它设置为3以便于测试时使用.这看起来像__repr__输出给我,如果我错了,请纠正我.)

该值可通过G.value获得.但是,在Ethan的回答中他使用了

return self.G * self.mass / (self.radius * self.radius)
Run Code Online (Sandbox Code Playgroud)

这显然只有在__repr__输出值返回时才有效.现在,如果我class Constant:改为class Constant(int):然后输入GI仍然得到__repr__输出,但如果我输入G * 4我得到的12不是我得到的错误.(TypeError:*:'instance'和'int'不支持的操作数类型)

很明显像int对象这样的东西在调用时可以输出一个数字.有没有一种我想要的魔术方法可以让我为Constant类做这个?由于常量可以是字符串,整数或浮点数,因此我更倾向于使用1个处理它们的类,而不是扩展这些对象的3个单独的类.

该值也可通过G.value设置.我可以将其锁定,以便Constant类的行为类似于实际的常量吗?(我怀疑答案是否定的.)

bax*_*ico 2

你的 Constant 类应该继承自 object,成为一个新风格的 Python 类。

这样 Constant 将成为所谓的描述符。简单来说,描述符是一个 Python 构造,用于自定义获取和设置类属性的行为。当描述符的实例被设置为另一个类的属性时,它们非常有用。

在您的示例中,Constant 是描述符,Planet 有一个属性,它是 Constant 的实例。当您获取 Planet 类的属性 G(在示例中为 self.G)时,您真正获得的是描述符的 __get__ 方法返回的内容,即值。

请注意,仅当描述符实例被另一个类属性访问时才会调用 __get__ 。

因此,像这样定义类:

class Constant(object):
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)
Run Code Online (Sandbox Code Playgroud)

然后这个小例子:

c = Constant(3.14)
print c

class Test:
    c = Constant(3.14)

t = Test()
print t.c
Run Code Online (Sandbox Code Playgroud)

将打印:

Constant(3.14)
3.14
Run Code Online (Sandbox Code Playgroud)

看到当Constant实例直接打印时,会调用方法__repr__,但是当打印为另一个类属性时,会使用__get__。

您可以在这篇精彩的文章中阅读有关描述符的更多信息。