In Python, does `is not int` ever return false?
Question: I am using argument parser to allow passing port number to my program. I then
try to validate the value, and one of the first tests is the `is int` test:

    
    
        parser = argparse.ArgumentParser(description='Provides XML-RPC API.')
        parser.add_argument('--port', dest='port', default=9666, type=int,
                           help='port to listen on, 9666 by default.');
        args = parser.parse_args()
    
        if args.port is not int:
            raise TypeError("Port must be integer (%s given), use -h argument to get help."%(type(args.port).__name__))
        if args.port>=65536 or args.port<=0:
            raise IndexError("Port must be lower than 65536, 65535 is the maximum port number. Also, port can only be positive, non-zero number. Use -h argument to get help.")
        if args.port<=1204:
            print("Notice: ports up to 1024 are reserved to well known services, using this port numbers often leads to conflicts. Use -h argument to get help.")
    

Now whatever I do, I get the error:

    
    
    Port must be integer (int given), use -h argument to get help.
    

I mean, what the hell? Even the error says it was int, so what's going on?


Answer: `args.port is not int` will return `False` if `args.port` was ever set to the
`int` type:

    
    
    args.port = int
    args.port is int  # True
    

or you re-bound `int` to the same object `args.port` already is bound to:

    
    
    int = args.port
    args.port is int  # True
    

That is because `is` tests if two references are pointing to the exact same
object.

Perhaps you were confused on how to test for the type of an object, for that
you use the [`isinstance()`
function](https://docs.python.org/2/library/functions.html#isinstance), or
test the output of
[`type()`](https://docs.python.org/2/library/functions.html#type):

    
    
    type(args.port) is not int  # False if args.port is a different type
    not isinstance(args.port, int)  # False if args.port is a different type and not a subclass either
    

This will never be the case either, because you configured your
`ArgumentParser` option to only accept integers:

    
    
    parser.add_argument('--port', dest='port', default=9666, type=int,
                       help='port to listen on, 9666 by default.')
    

The `type=int` argument is important, because that means that anything that
cannot be interpreted as an integer will be rejected by the parser. You will
never get past `parser.parse_args()` here:

    
    
    >>> import argparse
    >>> parser = argparse.ArgumentParser(description='Provides XML-RPC API.')
    >>> parser.add_argument('--port', dest='port', default=9666, type=int,
    ...                     help='port to listen on, 9666 by default.')
    _StoreAction(option_strings=['--port'], dest='port', nargs=None, const=None, default=9666, type=<type 'int'>, choices=None, help='port to listen on, 9666 by default.', metavar=None)
    >>> parser.parse_args(['--port', 'not an integer'])
    usage: [-h] [--port PORT]
    : error: argument --port: invalid int value: 'not an integer'
    

That's because `'not an integer'` cannot be converted by the `int()` function;
a `ValueError` is raised and `argparse` translates that to an error message
for you:

    
    
    >>> int('not an integer')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: 'not an integer'
    

You could supply your own conversation function that limits the range:

    
    
    def portnumber(value):
        port = int(value)  # may raise ValueError
        if not 0 <= port <= 65536:
            raise ValueError('Not a valid port number')
        return port
    

Then use that as the `type`:

    
    
    parser.add_argument('--port', dest='port', default=9666, type=portnumber,
                       help='port to listen on, 9666 by default.')
    

