-2

Which variable types (int, float, list, dict, string, etc...) would assume the same address when their values are same.

a1, b1 = 1, 1                                           #int
a2, b2 = 1.1, 1.1                                       #float
a3, b3 = 1j, 1j                                         #complex
a4, b4 = [1, 2], [1, 2]                                 #list
a5, b5 = (1, 2), (1, 2)                                 #tuple
a6, b6 = range(10), range(10)                           #range
a7, b7 = {"a": 1, "b": 2}, {"a": 1, "b": 2}             #dict
a8, b8 = {1, 2}, {1, 2}                                 #set
a9, b9 = frozenset({1, 2}), frozenset({1, 2})           #frozenset
a10, b10 = True, True                                   #bool
a11, b11 = b"aa", b"aa"                                 #bytes
a12, b12 = bytearray((1, 2)), bytearray((1, 2))         #bytearray
chakmeshma
  • 246
  • 8
  • 27
  • 1
    Small integers are cached (-5 to 256). Some strings are interned. Booleans are global constants... All other objects have unique instances... Does this answer your question? – OneCricketeer Nov 08 '21 at 18:20
  • What about other types? – chakmeshma Nov 08 '21 at 18:21
  • 2
    How about you try it? `print(id(a4), id(b4))`? – OneCricketeer Nov 08 '21 at 18:22
  • 7
    What *problem do you hope to solve* by having this information? – Karl Knechtel Nov 08 '21 at 18:23
  • If they're mutable, they have to be separate objects. If they're not, it's really up to the Python implementation to decide what common values it wants to cache. It should not concern you. – khelwood Nov 08 '21 at 18:24
  • int is mutable right? but they have same address when i checked – chakmeshma Nov 08 '21 at 18:27
  • 1
    "Which variable types (int, float, list, dict, string, etc...) would assume the same address when their values are same." **None**. You should *never assume that the same value implies identity* only for a couple language-guaranteed singletons (e.g., `None`) – juanpa.arrivillaga Nov 08 '21 at 18:27
  • @chakmeshma no, `int` is absolutely **not** mutable, and **no** you cannot know if it will have the same address. This is very, very important to understand, you should **never** use identity when you mean equality. – juanpa.arrivillaga Nov 08 '21 at 18:28
  • Does this answer your question? [What's with the integer cache maintained by the interpreter?](https://stackoverflow.com/questions/15171695/whats-with-the-integer-cache-maintained-by-the-interpreter) – Tomerikoo Nov 08 '21 at 18:28
  • @OneCricketeer you cannot rely on small integers being identitcal if they have the same value. – juanpa.arrivillaga Nov 08 '21 at 18:28
  • Related: https://stackoverflow.com/questions/56247227/why-isnt-is-comparison-used-in-place-of-for-primitive-types – juanpa.arrivillaga Nov 08 '21 at 18:30
  • Also, a nitpick, but *variables don't have types in Python*. Objects have types, variables can refer to any type of object – juanpa.arrivillaga Nov 08 '21 at 18:34

1 Answers1

0

This is not a safe assumption for any type of variable, except booleans.

In general this behavior is known as "interning" - simple immutable values get stored and cached, to save a little bit of memory. As elaborated upon in this answer, small integers and Strings are usually interned, but not always, and relying on this behavior will lead you to some hard-to-debug errors.

int and str, and specifically the empty tuple (), are the only types I've observed to exhibit this behavior, and even then, it's unpredictable when they'll stop.

For most other simple immutable types (int, float, complex, tuple, bool, bytes) you can compare literals to each other and the interpreter will tell you True, after spitting out a warning, but assigning them to variables and repeating the check will produce False:

>>> (1, 2) is (1, 2)
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> a = (1, 2)
>>> b = (1, 2)
>>> a is b
False

Mutable or complex types (range, list, dict, set, frozenset, bytearray) will never occupy the same memory as each other, even if identical, and so even doing an is comparison with literals will return false:

>>> bytearray((1, 2)) is bytearray((1, 2))
False

It should be obvious that any two different types will never return true in an is comparison.


Booleans, and None, are a special case. They are defined as global constants, and in fact every invocation of True and False explicitly points to the same two instances in memory. You can safely use is for comparing any two booleans.

This is actually useful when you want to disambiguate between a value that could be True, False, or None. Simply checking truthiness (if not condition:) would group False and None together, so you might need to instead check if condition is False: to explicitly exclude None.

Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • 1
    It's not a safe assumption for booleans! `x = 1; y = False` `x == y` but `x is y` is false – juanpa.arrivillaga Nov 08 '21 at 18:29
  • @juanpa.arrivillaga `1` is not a `Boolean`, so of course `is` would return false. I added an addendum to my post to explain booleans - what I meant to say was that since `True` and `False` are global constants, every `True` is the same object, so using `is` with booleans-to-booleans will always work. – Green Cloak Guy Nov 08 '21 at 18:32
  • Sure, although, I think using `is` to check for `None` is more common, actually needing to know if an object is `False` or `True` is rare – juanpa.arrivillaga Nov 08 '21 at 18:33
  • eh, I've used it before. – Green Cloak Guy Nov 08 '21 at 18:34