Search code examples
pythonpython-3.xclassvariablesint

Int is not a keyword, What happens if we use it as a variable?


Int is not a keyword in python, and hence can be used as a variable name. I tried to assign a string into the name and it worked.

I did this in the IDLE of Python3.8.2

>>> a = int(4.5)
>>> print(a)
4
>>> int = 'abc'
>>> print(int)
abc
>>> b = int(5.7)
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    b = int(5.7)
TypeError: 'str' object is not callable
>>> print(b)

the code works without the last part. ie from b = int(5.7)

Why does it happen? and shouldn't int be a keyword? how can we fix it keeping the existing code intact as if working in the console?

I tried using the del keyword and it worked. but I don't know why.

>>> del int
>>> b = int(5.7)
>>> print(b)
5

This works.

Please explain. :)


Solution

  • None of the basic types are keywords, they are type objects

    >>> type(int)
    <class 'type'>
    

    and they create instances of their class when used

    >>> type(int('100'))
    <class 'int'>
    

    They work like classes you define yourself

    >>> class Foo:
    ...     pass
    ... 
    >>> type(Foo)
    <class 'type'>
    >>> type(Foo())
    <class '__main__.Foo'>
    

    The only difference is that they are in the "builtins" namespace, but due to python's scoping rule, "builtins" is check last. Any variable you create is in a namespace checked before builtins so shadows the builtin itself.

    As for why, just about everything in python is a first class object and they all follow the same rules. There is no special code or any special rules for int (other than its implementation) - it works the same as any other class.

    Namespaces are hierarchical, mostly builtins --> module --> local meaning that local shadows module which shadows builtins. del removes a variable from a namespace, removing that shadow. If you create a variable called int and then del int, python will no longer find it in the local namespace and will fall back to the original.

    Of course, you can always mess things up on a more permanent basis if you wish:

    >>> __builtins__.__dict__['int'] = float
    >>> int(1)
    1.0