Python: Constant Class
我在看这个问题的答案:是否可以在枚举内定义类常量?
最让我感兴趣的是伊桑·弗曼的回答中不断出现的问题。
1 2 3 4 5 6 7 | 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) |
问题是关于Python3.4,但我使用的是2.7。在答案中,Ethan将重力常数设置为类行星的一个实例变量,如下所示:
1 | G = Constant(6.67300E-11) |
我在2.7中对这门课的测试表明,只要输入g就可以得到:
1 | Out[49]: Constant(3) |
(我将它设置为3,以便在测试时使用。这看起来像是我的
该值可通过g.value获得。然而,在伊桑的回答中,他使用了
1 | return self.G * self.mass / (self.radius * self.radius) |
这显然只在返回值与
所以很明显,像int对象这样的对象在调用时可以输出一个数字。有没有一个神奇的方法可以让我为常量类做这个?因为常量可以是字符串、整数或浮点数,所以我宁愿用一个类来处理它们,而不是用三个独立的类来扩展这些对象。
该值也可以通过g.value设置。我可以把这个锁起来,这样常量类的行为就像一个实际常量吗?(我怀疑答案是否定的。)
类常量应该从对象继承,成为一个新样式的Python类。
这样,常量就是所谓的描述符。简单来说,描述符是一个python构造,用于定制获取和设置类属性的行为。当描述符的一个实例被设置为另一个类的属性时,它们是有用的。
在您的示例中,常量是描述符,行星有一个属性,它是常量的一个实例。当你得到行星类的属性g(例如self.g)时,你真正得到的是描述符的get方法返回的值。
注意,只有当描述符实例被另一个类属性访问时,才会调用get。
所以,像这样定义类:
1 2 3 4 5 6 7 | 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) |
然后这个小例子:
1 2 3 4 5 6 7 8 | c = Constant(3.14) print c class Test: c = Constant(3.14) t = Test() print t.c |
将打印:
1 2 | Constant(3.14) 3.14 |
请注意,当直接打印常量实例时,将调用方法repr,但当作为另一个类属性打印时,将使用get。
您可以在这篇伟大的文章中阅读更多关于描述符的内容。
好吧,
1 2 3 4 5 6 7 8 9 10 11 | class Constant: def __init__(self, value): # This actually transforms the variable to _Constant__value, # but also hides it from outer scope self.__value = value def __get__(self, *args): # Altough the member is theorically renamed as _Constant__value, # it is completely accesible from inside the class as __value reurn self.__value def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.__value) |
另一种方法是遵循这个配方。
试一试,现在就让我来。希望我能帮助你!