Python Forum

Full Version: Function Default Arguments
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi Viewer,

Got a query on function default arguments.

i = 10
def fun(l = 10):
    if i is l:
        print('mathced')
    else:
        print('not matched')
fun()
The above code would output "matched".

The same code when used a tuple instead of an integer,

i = (1, 2, 3)
def fun(l = (1, 2, 3)):
    if i is l:
        print('matched')
    else:
        print('not matched')
fun()
prints 'not matched'.

Integers and tuples both being immutable types, why does python differentiate between the both when it comes to default arguments? Thanks in advance.

Thanks,
Kiran.
Hi, this is odd, I run the very code you posted and get "matched" printed also for the second snippet.
Did you happen to copy/paste/run and redeclared only one object (e.g. i or fun declaration) instead of both, i and fun?
Hi,

I tried them seperately. And even now cross checked it. I am getting "not matched" in the second case.
is is identity operator. i.e. it compares that both names point to same object. You should not be using it in this case. Use comparison == in this case.
When it comes to integers read this SO answer
https://stackoverflow.com/a/28864111/4046632

you can print id(i) and id(l) to see if they are same object or not.

You will use is when you want to be certain to names point to exactly the same object. One exception is when you compare to None. You will do i is None, not i == None. That is because None is so called singleton (i.e. exists as object in only one place in memory).
Thanks Buran

I understand the difference between is and == in python. My question was more like even though tuples and integers are immutable types, for integers python decides to use the same object reference and where as for a tuple it creates a new object. Is there some rules or something by which we could know python would create a new object if I use this datatype?

I have noticed the behaviour different for complex numbers as well. For instance,

i = 3+4j
k = 3+4j
print(i is k) 
would print "False" where as

i = 4j
k = 4j
print(i is k)
would print "True".

Thanks
From the docs
https://docs.python.org/3/c-api/long.html

Quote:The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

In fact you can see that it's not only for the range -5, 256. Probably the range depends also on other factors...
Compare
i = 10**2
def fun(l = 100):
    print id(i), id(l)
    if i is l:
        print('matched')
    else:
        print('not matched')
fun()
and

i = 10**3
def fun(l = 1000):
    print id(i), id(l)
    if i is l:
        print('matched')
    else:
        print('not matched')
fun()
You can test it:
for a, b in zip(*[range(-5, 500)]*2):
    if a is not b:
        print(f'{a} is not {b}')
        break
Output:
257 is not 257
Never use is for numbers.
Otherwise you're relying on an implementation detail of CPython.
Thanks for taking time to respond.