Behaviour of "is" is different for primitives in python [duplicate] - python

This question already has an answer here:
What's with the integer cache maintained by the interpreter?
(1 answer)
Closed 6 years ago.
is in Python tests if 2 references point to the same object.
Numbers between -5 and 256 are cached internally so:
a = 10
b = 10
a is b # Results in True
How does this explain something like:
20000 is 20000 # Results in True
Both numbers are above 256.
Should not the 2 integers be 2 distinct objects?

The Python interpreter sees you are re-using a immutable object, so it doesn't bother to create two:
>>> import dis
>>> dis.dis(compile('20000 is 20000', '', 'exec'))
1 0 LOAD_CONST 0 (20000)
3 LOAD_CONST 0 (20000)
6 COMPARE_OP 8 (is)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Note the two LOAD_CONST opcodes, they both load the constant at index 0:
>>> compile('20000 is 20000', '', 'exec').co_consts
(20000, None)
In the interactive interpreter Python is limited to having to compile each (simple or compound) statement you enter separately, so it can't reuse these constants across different statements.
But within a function object it certainly would only create one such integer object, even if you used the same int literal more than once. The same applies to any code run at the module level (so outside of functions or class definitions); those all end up in the same code object constants too.

Python stores objects in memory to make things more efficient. It only needs to assign one block of memory to 20000, and so both references point to the same block of memory, resulting in True.

Related

*= multiplier question between arrays and integers [duplicate]

This question already has answers here:
Why does += behave unexpectedly on lists?
(9 answers)
Closed 1 year ago.
I'm trying to learn coding through some tutorials and encountered something curious as I'm going over operators. The basic ones I get, but some others (like *= here) throw me off.
a = 1
b = a
a *= 2
print(a)
print(b)
Output
2
1
But when a is an array, this happens:
a = np.array([1, 2, 3, 3, 5, 5])
b = a
a *= 2
print(a)
print(b)
Output
[2 4 6 6 10 10]
[2 4 6 6 10 10]
Any insight as to why this happens? I can't really find much about it. The only thing I came across was "coercion rules"; does the second instance happen because a is being assigned to an array but then to an integer? Or is it a matter of the print statement order?
It's probably trivial but I'm just curious, thanks!
The Simple answer to your question is,
There are two kinds of objects in Python: Mutable objects and Immutable objects. The value of a mutable object can be modified in place after it’s creation, while the value of an immutable object cannot be changed.
Immutable(Not Modifiable) Object: int, float, long, complex, string tuple, bool
Mutable(Modifiable) Object: list, dict, set, byte array, user-defined classes.
So,here in your case firstly a and b are immutable objects as it belongs to class int in python,"b=a" means b is pointing towards a address,and as you update value of a to a*=2, the value is store on new memory location, but b is still pointing towards older address, thats why b is not showing changed value of a.
For more understanding of memory management in python, please read this blog, thankyou :)
https://medium.com/#tyastropheus/tricky-python-i-memory-management-for-mutable-immutable-objects-21507d1e5b95

How probing works in python dictionary? [duplicate]

This question already has answers here:
How Python dict stores key, value when collision occurs? [duplicate]
(2 answers)
How are Python's Built In Dictionaries Implemented?
(3 answers)
Why can a Python dict have multiple keys with the same hash?
(5 answers)
Closed 4 years ago.
my_dict = {}
my_dict["qwerty"] = "some_value"
my_dict[114378642] = "some_other_value"
The above code contains a python dictionary containing two keys, where the first key is of type string and the second key is of type integer. Though both keys are of different types it produces the same hash i.e,
hash("qwerty") = 114378642
hash(114378642) = 114378642
and hence,
hash("qwerty") == hash(114378642) #True
Couldn't get a proper answer until now,
Firstly, I was under an impression that "only two similar objects
produce the same hash".
Secondly, how a python dictionary performs collision recovery in
the above case?
Finally, what is the initial capacity and of a python dictionary
in the first line of code?
hash() produces the same result as the int value you input, no surprise here.
>>> for i in range(10) : print i, hash(i)
...
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
Dictionaries use a different hashing to store their values.

Style for continued multi-line f-strings [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Do any popular Python style guides express a preference between:
x = (f'One plus one is '
f'equal to {1+1}')
and:
x = ('One plus one is '
f'equal to {1+1}')
Does it make sense to omit the f prefix for lines that don't involve interpolation? Should it be included for consistency?
If you look at the generated byte code for each of those two options, you will see that this both results in the same set of operations:
>>> dis.dis("""f'One plus one is ' f'equal to {1+1}'""")
1 0 LOAD_CONST 0 ('One plus one is equal to ')
2 LOAD_CONST 1 (2)
4 FORMAT_VALUE 0
6 BUILD_STRING 2
8 RETURN_VALUE
>>> dis.dis("""'One plus one is ' f'equal to {1+1}'""")
1 0 LOAD_CONST 0 ('One plus one is equal to ')
2 LOAD_CONST 1 (2)
4 FORMAT_VALUE 0
6 BUILD_STRING 2
8 RETURN_VALUE
So for Python, this both does exactly the same thing: The string is being concatenated at compile-time, and the whole string is being evaluated as a format string.
Note though that as per the PEP, f-strings are actually concatenated at run-time, to make sure that every format expression is evaluated independently:
Adjacent f-strings and regular strings are concatenated. Regular strings are concatenated at compile time, and f-strings are concatenated at run time.
That is why the following example will generate two FORMAT_VALUE opcodes:
>>> dis.dis("""f'{2+2}' f'{3+3}'""")
1 0 LOAD_CONST 0 (4)
2 FORMAT_VALUE 0
4 LOAD_CONST 1 (6)
6 FORMAT_VALUE 0
8 BUILD_STRING 2
10 RETURN_VALUE
This will not have an effect for f-strings that don’t actually contain any format placeholders though. Those will still be concatenated at compile-time:
>>> dis.dis("""f'foo' f'bar'""")
1 0 LOAD_CONST 0 ('foobar')
2 RETURN_VALUE
So you can just include the f prefix for constant strings anyway and when they don’t contain a format expression, they won’t end up being handled as format strings.
So in your particular case, since there is no functional difference and both options are compiled to the same thing, that leaves this as a pure style choice which everyone has to answer for themselves.
If you are looking at existing style guides, chances are that they are not covering f-strings yet. But then, you could use the same guideline as for raw strings, although I personally don’t expect style guides to really cover that area much. Just choose what looks best, is readable, and what makes most sense to you. After all, continued strings are not really that common (and you are more likely to have triple-quotes for longer strings).

Python "is" v/s "=" weird behavior [duplicate]

This question already has answers here:
"is" operator behaves unexpectedly with integers
(11 answers)
Closed 9 years ago.
In Python, x is y returns true if the two sides evaluate to the same object; that is, it checks pointer equality. Now I tried something like this:
>>>a = 2
>>>a is 2
True
However..
>>>a = 9203409249024
>>>a is 9203409249024
False
Why this difference in behavior?
Python (and other languages) cache small numbers in memory, so that multiple variables that have the value (for example) 2 will point to the same location in memory (and, hence, is returns True).

python: how to get the source from a code object? [duplicate]

This question already has answers here:
What tools or libraries are there for decompiling python and exploring bytecode? [closed]
(6 answers)
Closed 9 years ago.
let's suppose we have a python string(not a file,a string,no files)
TheString = "k=abs(x)+y"
ok? Now we compile the string into a piece of python bytecode
Binary = compile( TheString , "<string>" , "exec" )
now the problem: how can i get from Binary , supposing i don't know TheString , a string that represents the original string object?
shortly: what is the function that is opposite to compile() ?
Without the source code, you can only approximate the code. You can disassemble the compiled bytecode with the dis module, then reconstruct the source code as an approximation:
>>> import dis
>>> TheString = "k=abs(x)+y"
>>> Binary = compile( TheString , "<string>" , "exec" )
>>> dis.dis(Binary)
1 0 LOAD_NAME 0 (abs)
3 LOAD_NAME 1 (x)
6 CALL_FUNCTION 1
9 LOAD_NAME 2 (y)
12 BINARY_ADD
13 STORE_NAME 3 (k)
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
From the disassembly we can see there was 1 line, where a function named abs() is being called with one argument named x. The result is added to another name y, and the result is stored in k.
Projects like uncompile6 (building on top of the work of many others) do just that; decompile the python bytecode and reconstruct Python code from that.

Categories