1

I stumbled into an interesting phenomenon with Python (3.7.6). I'd like to preface by saying that naming variables like this is a terrible idea that one should never do. However, the following code amazingly compiles:

list = (123, "abc", 222, "foo", "bar", 333); #Tuple named list
print(list);

However:

list = (123, "abc", 222, "foo", "bar", 333);
list = list(list);
print(list);

Raises a type error as tuples are not callable, and presumably it believes you are trying to call the tuple instead of cast the tuple to a list.

Of course, by changing the variable name like follows:

a = (123, "abc", 222, "foo", "bar", 333);
a = list(a);
print(a);

One is able to successfully cast a tuple to a list. It appears that this behavior exists for several different keywords. However, for some keywords this behavior is not seen such as with from. Can anyone explain this madness? Specfically, what keywords can be used as variables like this, and why is this even permitted in the first place?

Rachel Casey
  • 205
  • 2
  • 11
  • 3
    None of those are key-words. By *definition* keywords cannot be used as variable names. You can get a list of keywords for your current python version using `import keyword; print(keyword.kwlist)` Anyway, `list` is merely the name of a built-in function, and like any other variable, it can be re-assigned, although, it is highly inadvisable to do so. Examples of keywords are things like `class`, `in`, `for` etc, usually parts of statements. – juanpa.arrivillaga Mar 06 '20 at 23:52
  • 3
    As an aside, and this is totally an aside, the word "cast" I think, isn't a useful way of thinking about these things in Python. You are passing a `tuple` object to the `list` object constructor, this constructor creates a *new list object* out of that `tuple`, because the `list` constructor takes any arbitrary iterable. The word *cast* comes with various erroneous (in Python) implications from lower-level, statically typed languages like C and C++. But I understand that "cast" is just used loosely to mean "convert" – juanpa.arrivillaga Mar 06 '20 at 23:56
  • 1
    Does this answer your question? [Why are 2 of the 6 built-in constants assignable?](https://stackoverflow.com/a/44972211/12299000) – kaya3 Mar 06 '20 at 23:58

2 Answers2

1

list is a built-in function. It is not a keyword. The whole keywords list can be seen here - Python Keywords

Keywords can not be used as a variable name nor any object name. But built-in function names can be re-defined as you said.

The common mixed usage is id. For example,

def getTableFromDatabase(id):
    print ( id(dbname) ) # error, cos id is not a function
    return getTable(dbname, id)

t = getTableFromDatabase(1)

, where id is used for the id of a table. But id is one of the built-in functions. It is used for getting the hash id of an object. The better practice is to use append underscores in front of such keywords.

def getTableFromDatabase(_id):
    print( id(dbname) ) # prints id of dbname variable
    return getTable(dbname, _id)

t = getTableFromDatabase(1)
DumTux
  • 668
  • 1
  • 9
  • 24
1

list isn't a python keyword. Its an object (specifically a type object) bound to builtins.list which is used as a fallback in all modules. When you assign the list variable in your namespace, you mask the orignal type object. The type object is still available in builtins

>>> import builtins
>>> list = "foo"
>>> list("bar")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>> builtins.list("bar")
['b', 'a', 'r']

And you can always get it back

>>> list=builtins.list
>>> list("bar")
['b', 'a', 'r']

But best to avoid messing with those types. dir(builtins) will tell you what to avoid.

tdelaney
  • 73,364
  • 6
  • 83
  • 116