python 常数怎么表达_Python的常数类

我在看这个问题的答案:是否可以在枚举内定义类常量?

最让我感兴趣的是伊桑·弗曼的回答中不断出现的问题。

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将重力常数设置为类行星的一个实例变量,如下所示:

G = Constant(6.67300E-11)

我在2.7中对这门课的测试表明,只要输入g就可以得到:

Out[49]: Constant(3)

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

该值可通过g.value获得。然而,在伊桑的回答中,他使用了

return self.G * self.mass / (self.radius * self.radius)

这显然只在返回值与__repr__输出的情况下有效。现在,如果我把class Constant:改成class Constant(int):,那么G型仍然可以得到__repr__的输出,但是如果我把G * 4改成12,我得到的不是我得到的错误。(类型错误:不支持*:"instance"和"int"的操作数类型)

所以很明显,像int对象这样的对象在调用时可以输出一个数字。有没有一个神奇的方法可以让我为常量类做这个?因为常量可以是字符串、整数或浮点数,所以我宁愿用一个类来处理它们,而不是用三个独立的类来扩展这些对象。

该值也可以通过g.value设置。我可以把这个锁起来,这样常量类的行为就像一个实际常量吗?(我怀疑答案是否定的。)

你为什么要它是常数?

@为什么我不想要常量?还是类中的只读值?从我读到的关于Python的文章中,我了解到这与Python的"我们都是同意的成年人"理念背道而驰。到目前为止,我真的很喜欢Python,但我认为哲学是一个疏忽。我为我自己编写程序,而我-没有人会读或使用它。在过去的15年里,我用几种语言进行了编码,学到了一些东西。其中一件事是,我可以通过简单地设计一个类来阻止值得调试的日子,在这个类的内部之外,某些东西是不能更改的。

我更想知道你在什么程度上要求它保持不变;我的观点是检查你是否同意"通过公共接口保持不变",这是正确的方法,或者你真的希望它保持不变,这是不可能的。

另外,他们不关心是否可以设置value,只需将其命名为_value,就可以将其私有化。那你就不用担心P了?E?O?P?L?E?你自己改变了。

@吠陀很抱歉,我关于Python的前两个问题得到了礼貌的回答,为什么你要做这么愚蠢的事情?就常量而言,我可以通过公共接口对它们进行只读。我希望它们是真常量,并且我可以编写一个类变量,该变量在定义它的类之外是只读的,但是我理解在Python中这些变量可能是不可能的。

类常量应该从对象继承,成为一个新样式的Python类。

这样,常量就是所谓的描述符。简单来说,描述符是一个python构造,用于定制获取和设置类属性的行为。当描述符的一个实例被设置为另一个类的属性时,它们是有用的。

在您的示例中,常量是描述符,行星有一个属性,它是常量的一个实例。当你得到行星类的属性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)

然后这个小例子:

c = Constant(3.14)

print c

class Test:

c = Constant(3.14)

t = Test()

print t.c

将打印:

Constant(3.14)

3.14

请注意,当直接打印常量实例时,将调用方法repr,但当作为另一个类属性打印时,将使用get。

您可以在这篇伟大的文章中阅读更多关于描述符的内容。

根据我所测试的,只有当它是类变量而不是实例变量时,它才有效。如果我通过self.c = Constant(...)将c = Constant移动到__init__,那么我得到__repr__输出。它仍然是可写的,对于一个常数来说是可以的,因为我可以用所有的大写字母命名。理想情况下,我希望找到一种方法,使实例变量能够从类内写入,而不是从__main__脚本外写入。我在PHP中做了一些很好的工作,但是根据我目前所读到的内容,在Python中是不可能的。类属性似乎总是可用于覆盖。谢谢

好吧,value是你的class Constant的一个成员,所以你可以试着让它私有化:

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)

另一种方法是遵循这个配方。

试一试,现在就让我来。希望我能帮助你!

我还没有试过这个配方,但是你提供的代码对我来说不起作用。我再也不能直接得到价值了。我怀疑这是因为@baxeico说过它必须成为类中的描述符。谢谢

这道菜似乎行得通。但是,它必须驻留在一个文件中并被导入。它似乎也是一个单身汉。在类中导入它(在类定义的正下方)不会将其限制在该类的命名空间中。进口线也不在__init__中。如果你能忍受这些限制的话,这个食谱会很好地工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值