简体   繁体   English

为什么可以在Python中为内置函数赋值?

[英]Why can you assign values to built-in functions in Python?

I found out about this by accident today when I noticed that a piece of Python code had used the built-in function all as a variable identifier to store the result of a list comprehension and it didn't throw an error, so I tried the following: 我今天偶然发现了这个,当我注意到一段Python代码使用了内置函数 all作为变量标识符来存储列表理解的结果并且它没有抛出错误,所以我尝试了以下:

type('abc')
Out[1]: str

type('abc') == str
Out[2]: True

str = int

type('abc') == str
Out[4]: False

type('abc')
Out[5]: str

type = [1,2,3]

type('abc')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-a74a7df76db1> in <module>()
----> 1 type('abc')

TypeError: 'list' object is not callable 

Hopefully, it's a valid question when I ask why this behavior is allowed in Python. 希望,当我问为什么在Python中允许这种行为时,这是一个有效的问题。

Or better yet, how do I make sure that a built-in function like str is really str and not say, int so str(123) won't be evaluated as int(123) by accident? 或者更好的是,我如何确保像str这样的内置函数真的是str而不是说int因此str(123)不会被意外地评估为int(123)

Python expects you to take responsibility for your code, is why. Python希望您对代码负责,这就是原因。 Python doesn't have private attributes, no protected classes, and almost no limits on what names you can use. Python没有私有属性,没有受保护的类,几乎没有限制你可以使用的名称。

Yes, that means you can accidentally rename a built-in. 是的,这意味着您可能会意外地重命名内置内容。 Create unittests for your code, use a linter, and generally, you'll quickly learn to spot accidental use of a built-in you needed. 为您的代码创建单元测试,使用linter,通常,您将很快学会发现意外使用您需要的内置代码。 It's no different from accidentally re-using any other name in your code. 与您在代码中意外重复使用任何其他名称没有什么不同。

Note that you are simply masking the built-in names; 请注意,您只是屏蔽了内置名称; name lookups that fail to find a global next look at the built-in namespace, so if you set str to something else, that is found before the built-in. 名称查找无法在内置命名空间中找到全局下一个查看,因此如果将str设置为其他内容,则会在内置命令之前找到。 Simply delete the global: 只需删除全局:

>>> str = 'foobar'
>>> isinstance('foobar', str)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
>>> del str
>>> isinstance('foobar', str)
True

The alternative would be to make every built-in name a reserved keyword, leaving you with a much diminished list of names that is allowed, and no flexibility in re-defining those objects. 另一种方法是使每个内置名称都成为一个保留关键字,这样你就可以获得一个允许的名称列表,并且没有灵活性来重新定义这些对象。 Python 2.7 has 144 such names, for example. 例如,Python 2.7有144个这样的名字。

In this context, see this blog post by Guido van Rossum on why None , True and False are now keywords in Python 3 : 在这种情况下,请参阅Guido van Rossum撰写的这篇博文 ,了解为什么NoneTrueFalse现在是Python 3中的关键字

Because you cannot use these as variable or function names anywhere, ever, in any Python program, everyone using Python has to know about all the reserved words in the language, even if they don't have any need for them. 因为你不能在任何Python程序中的任何地方使用它们作为变量或函数名称,所以使用Python的每个人都必须知道语言中的所有保留字,即使它们不需要它们。 For this reason, we try to keep the list of reserved words small, and the core developers hem and haw a lot before adding a new reserved word to the language. 出于这个原因,我们试图保留较小的保留字列表,并且在向该语言添加新的保留字之前,核心开发人员会出现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM