为什么Python决定反对常量引用?

时间:2010-11-16 07:42:51

标签: python reference constants language-design language-features

注意:我不是在谈论阻止重新绑定变量。我正在谈论防止变量引用的内存的修改,以及通过跟随嵌套容器可以从那里访问的任何内存。

我有一个大型数据结构,我希望以只读方式将其公开给其他模块。在Python中执行此操作的唯一方法是深度复制我想要公开的特定部分 - 在我的情况下非常昂贵。

我确信这是一个非常普遍的问题,似乎一个恒定的参考将是一个完美的解决方案。但我必须遗漏一些东西。也许在Python中很难实现常量引用。也许他们并不像我认为的那样做。

任何见解都将不胜感激。


虽然答案很有帮助,但我还没有看到为什么const在Python中难以实现或不可行的原因。我猜“非Pythonic”也算是一个有效的理由,但它真的吗? Python确实对私有实例变量进行了加扰(从__开始)以避免意外错误,并且const在精神上似乎没有那么不同。


编辑:我刚刚提供了非常适度的赏金。我正在寻找更多关于为什么Python没有const结束的细节。我怀疑原因是实施起来真的很难;我想明白为什么这么难。

5 个答案:

答案 0 :(得分:13)

与私有方法相同:as consenting adults代码的作者应该在不需要强制的情况下就接口达成一致。因为真正真的强制执行合同是很难,并且这样做的方式是半途而废的,导致了大量的hackish代码。

使用get-only描述符,并在文档中清楚地说明这些数据意味着是只读的。毕竟,一个坚定的编码人员可能会找到一种方法来以不同的方式使用你的代码。

答案 1 :(得分:10)

PEP 351中,Barry Warsaw提出了一个“冻结”任何可变数据结构的协议,类似于frozenset创建不可变集的方式。冻结的数据结构是可以清除的,因此可以用作词典中的键。

该提案为discussed on python-dev,其中Raymond Hettinger's criticism最为详细。

这不是你想要的,但它是我能找到的最接近的,并且应该让你对Python开发人员关于这个主题的想法有所了解。

答案 2 :(得分:8)

关于任何语言都有很多设计问题,其中大多数的答案都是“仅仅因为”。很明显,像这样的常量会违背Python的意识形态。


但是,您可以使用descriptors创建只读类属性。这不是微不足道的,但并不是很难。它的工作方式是你可以使用property装饰器创建属性(看起来像属性但是在访问时调用方法的东西);如果你制作一个getter而不是setter属性,那么你将获得一个只读属性。元类编程的原因是,由于__init__收到了类的完全形成的实例,实际上您无法在此阶段将属性设置为您想要的属性!相反,你必须在创建类时设置它们,这意味着你需要一个元类。

来自this recipe的代码:

# simple read only attributes with meta-class programming

# method factory for an attribute get method
def getmethod(attrname):
    def _getmethod(self):
        return self.__readonly__[attrname]

    return _getmethod

class metaClass(type):
    def __new__(cls,classname,bases,classdict):
        readonly = classdict.get('__readonly__',{})
        for name,default in readonly.items():
            classdict[name] = property(getmethod(name))

        return type.__new__(cls,classname,bases,classdict)

class ROClass(object):
    __metaclass__ = metaClass
    __readonly__ = {'a':1,'b':'text'}


if __name__ == '__main__':
    def test1():
        t = ROClass()
        print t.a
        print t.b

    def test2():
        t = ROClass()
        t.a = 2

    test1()

答案 3 :(得分:1)

虽然编写代码的程序员是同意的成年人,但是使用相同代码的两名程序员很少同意成年人。更重要的是,如果他们不重视代码之美,而是他们的最后期限或研究基金。

对于这样的成年人,有一些类型安全,由Enthought Traits提供。

您可以查看Constant and ReadOnly特征。

答案 4 :(得分:1)

对于其他一些想法,这里有一个类似的问题: Why is there no Constant feature in Java?

当问及为什么Python 决定反对常量引用时,我认为考虑如何在语言中实现它们是有帮助的。 Python是否应该使用某种特殊声明 const 来创建无法更改的变量引用?为什么不允许变量被声明为float / int /那么......这些肯定有助于防止编程错误。虽然我们正在使用它,但添加了类和方法修饰符,如protected / private / public / etc.将有助于强制执行编译类型检查以防止非法使用这些类。 ...很快,我们失去了Python的美丽,简洁和优雅,我们正在用C ++ / Java的某种混蛋编写代码。

Python目前还通过引用传递所有内容。这将是某种特殊的传递参考 - 但是 - 标志 - 它要防止 - 修改......一个非常特殊的情况(并且正如Python的道所指出的那样,只是“非Pythonic”)。

如前所述,在没有实际改变语言的情况下,这种行为可以通过类和实现来实现。描述。它可能无法阻止确定的黑客进行修改,但我们同意成年人。 Python并不一定决定反对将其作为一个包含的模块(“包含电池”)提供 - 对它的需求从来没有。