为什么 Python 决定不使用常量引用?

发布于 2024-10-02 20:28:20 字数 540 浏览 3 评论 0原文

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

我有一个大型数据结构,我想以只读方式将其公开给其他模块。在 Python 中做到这一点的唯一方法是深度复制我想要公开的特定部分 - 对我来说成本高昂。

我确信这是一个非常常见的问题,似乎持续的参考将是完美的解决方案。但我一定错过了一些东西。也许常量引用很难在 Python 中实现。也许他们并没有完全按照我的想法去做。

任何见解将不胜感激。


虽然答案很有帮助,但我还没有看到 const 在 Python 中难以实现或无法使用的任何原因。我想“un-Pythonic”也可以算作一个有效的理由,但真的是这样吗? Python 确实对私有实例变量(以 __ 开头)进行加扰以避免意外错误,而 const 在精神上似乎并没有那么不同。


编辑:我刚刚提供了非常适度的赏金。我正在寻找更多关于为什么 Python 最终没有 const 的细节。我怀疑原因是完美工作确实很难实现;我想了解为什么这么难。

Note: I'm not talking about preventing the rebinding of a variable. I'm talking about preventing the modification of the memory that the variable refers to, and of any memory that can be reached from there by following the nested containers.

I have a large data structure, and I want to expose it to other modules, on a read-only basis. The only way to do that in Python is to deep-copy the particular pieces I'd like to expose - prohibitively expensive in my case.

I am sure this is a very common problem, and it seems like a constant reference would be the perfect solution. But I must be missing something. Perhaps constant references are hard to implement in Python. Perhaps they don't quite do what I think they do.

Any insights would be appreciated.


While the answers are helpful, I haven't seen a single reason why const would be either hard to implement or unworkable in Python. I guess "un-Pythonic" would also count as a valid reason, but is it really? Python does do scrambling of private instance variables (starting with __) to avoid accidental bugs, and const doesn't seem to be that different in spirit.


EDIT: I just offered a very modest bounty. I am looking for a bit more detail about why Python ended up without const. I suspect the reason is that it's really hard to implement to work perfectly; I would like to understand why it's so hard.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

枯叶蝶 2024-10-09 20:28:20

这与私有方法相同:作为同意的成年人作者代码应该在接口上达成一致,而不需要强制。因为确实真正执行合同是困难,而且半途而废的方式会导致大量黑客代码。

使用仅获取描述符,并在文档中明确说明这些数据意味着是只读的。毕竟,一个坚定的编码员可能会找到一种方法,以您想到的不同方式使用您的代码。

It's the same as with private methods: as consenting adults authors of code should agree on an interface without need of force. Because really really enforcing the contract is hard, and doing it the half-assed way leads to hackish code in abundance.

Use get-only descriptors, and state clearly in your documentation that these data is meant to be read only. After all, a determined coder could probably find a way to use your code in different ways you thought of anyways.

孤蝉 2024-10-09 20:28:20

PEP 351 中,Barry Warsaw 提出了一种用于“冻结”任何可变数据的协议结构,类似于frozenset创建不可变集合的方式。冻结的数据结构将是可散列的,因此能够用作字典中的键。

该提案在 python-dev 上进行了讨论,其中Raymond Hettinger 的批评最为详细。

这并不完全是你想要的,但它是我能找到的最接近的,并且应该让你了解 Python 开发人员在这个主题上的想法。

In PEP 351, Barry Warsaw proposed a protocol for "freezing" any mutable data structure, analogous to the way that frozenset makes an immutable set. Frozen data structures would be hashable and so capable being used as keys in dictionaries.

The proposal was discussed on python-dev, with Raymond Hettinger's criticism the most detailed.

It's not quite what you're after, but it's the closest I can find, and should give you some idea of the thinking of the Python developers on this subject.

夢归不見 2024-10-09 20:28:20

任何语言都有很多设计问题,其中大多数的答案是“只是因为”。很明显,这样的常量违背了 Python 的思想。


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

来自此食谱的代码:

# 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()

There are many design questions about any language, the answer to most of which is "just because". It's pretty clear that constants like this would go against the ideology of Python.


You can make a read-only class attribute, though, using descriptors. It's not trivial, but it's not very hard. The way it works is that you can make properties (things that look like attributes but call a method on access) using the property decorator; if you make a getter but not a setter property then you will get a read-only attribute. The reason for the metaclass programming is that since __init__ receives a fully-formed instance of the class, you actually can't set the attributes to what you want at this stage! Instead, you have to set them on creation of the class, which means you need a metaclass.

Code from 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()
一袭水袖舞倾城 2024-10-09 20:28:20

虽然一名编写代码的程序员是同意的成年人,但两名编写相同代码的程序员很少是同意的成年人。如果他们不看重代码的美观,而是看重最后期限或研究资金,那就更是如此。

对于这样的成年人,Enthought 的 特征

您可以查看 Constant< /code> 和 ReadOnly特征。

While one programmer writing code is a consenting adult, two programmers working on the same code seldom are consenting adults. More so if they do not value the beauty of the code but them deadlines or research funds.

For such adults there is some type safety, provided by Enthought's Traits.

You could look into Constant and ReadOnly traits.

橘寄 2024-10-09 20:28:20

对于一些额外的想法,这里有一个关于 Java 的类似问题:
为什么 Java 中没有 Constant 功能?

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

Python 目前还通过引用传递所有内容。这将是某种特殊的按引用传递但标记它以防止修改......一个非常特殊的情况(正如 Python 之道所表明的那样,只是“非 Pythonic”)。

如前所述,在不实际更改语言的情况下,可以通过类和类来实现这种类型的行为。描述符。它可能无法阻止坚定的黑客进行修改,但我们是同意的成年人。 Python 不一定决定不将其作为包含的模块提供(“包含电池”)——只是对它的需求永远不够。

For some additional thoughts, there is a similar question posed about Java here:
Why is there no Constant feature in Java?

When asking why Python has decided against constant references, I think it's helpful to think of how they would be implemented in the language. Should Python have some sort of special declaration, const, to create variable references that can't be changed? Why not allow variables to be declared a float/int/whatever then...these would surely help prevent programming bugs as well. While we're at it, adding class and method modifiers like protected/private/public/etc. would help enforce compile-type checking against illegal uses of these classes. ...pretty soon, we've lost the beauty, simplicity, and elegance that is Python, and we're writing code in some sort of bastard child of C++/Java.

Python also currently passes everything by reference. This would be some sort of special pass-by-reference-but-flag-it-to-prevent-modification...a pretty special case (and as the Tao of Python indicates, just "un-Pythonic").

As mentioned before, without actually changing the language, this type of behaviour can be implemented via classes & descriptors. It may not prevent modification from a determined hacker, but we are consenting adults. Python didn't necessarily decide against providing this as an included module ("batteries included") - there was just never enough demand for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文