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:
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.
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?
An example of something you can't do with Python keywords is assign something to them. If you try, then you'll get a SyntaxError . You won't get a SyntaxError if you try to assign something to a built-in function or type, but it still isn't a good idea.
The assignment operator, denoted by the “=” symbol, is the operator that is used to assign values to variables in Python. The line x=1 takes the known value, 1, and assigns that value to the variable with name “x”. After executing this line, this number will be stored into this variable.
No, you can't assign values to functions. You can assign values to function pointers, but not to functions in C++. Try assigning anything to foo in your example, for instance.
Python expects you to take responsibility for your code, is why. Python doesn't have private attributes, no protected classes, and almost no limits on what names you can use.
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. 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. 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.
In this context, see this blog post by Guido van Rossum on why None
, True
and False
are now keywords in 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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With