Live data from Hacker News

Weird Python Integers

kate.io

51–60 of 150 posts

Re: Weird Python Integers

#51

Is there any practical reason to use "is" to compare two ints (other than demonstrating integer interning)? Should doing so produce a warning?

Only if you want to determine whether two integers are the same object and not just two objects that look similar. `is` is for identity, whereas `==` is for equivalence.

Idiomatically, you generally only see `is` used for comparison to `None`. Sometimes developers want to check identity, and you'd use `is` there too (but I don't have a handy example offhand).

Re: Weird Python Integers

#52
post #26
post #7

Earlier quoted context omitted.

You could probably find out from the code's log. I'd guess the small positive integers are common due to e.g. iteration or len() of small collections and the like, and the very small negatives are due to things like error values.

I did some git archaeology. Here are relevant commits and bug reports: * Initial commit with -1...99 cached: https://github.com/python/cpython/commit/842d2ccdcd540399501... * Cache more negative numbers, -5...99: https://github.com/python/cpython/commit/c91ed400e053dc9f11d... https://bugs.python.org/issue561244 * Cache more positive numbers, -5...256: https://github.com/python/cpython/commit/418a1ef0895e826c65d... ht…

good find! here's a summary:

it looks like they searched the standard library for negative integer literals and that's how they settled on -5 for the low end.

the high end came after introducing the `bytes` object. it went up to 256 instead of just 255 for size/len checks.

Re: Weird Python Integers

#53
post #36

In [7]: a = "foo" In [8]: b = "foo" In [9]: a is b Out[9]: True In [10]: b = "foobaljlajdfsklfjds l;kjsl;dfj ls;dfj l;skdj flsdjluejsklnm " In [11]: a = "foobaljlajdfsklfjds l;kjsl;dfj ls;dfj l;skdj flsdjluejsklnm " In [12]: a is b Out[12]: False Seems to work with small and big strings too.

This would be due to string interning, which automatically caches small strings, which are very common because attribute names are just strings.

Re: Weird Python Integers

#54

Is there any practical reason to use "is" to compare two ints (other than demonstrating integer interning)? Should doing so produce a warning?

A lot of code relies on the fact that "is" is very fast because it just compares memory addresses. In order for it to give a warning when it is used on integers, it would need to also look at the types of the objects which would have have some performance impact.

No, it is not good practice to rely on the interning of ints and short strings. It's implementation-specific behavior and relying on it can cause your code to not work on PyPy or even potentially a future version of CPython.

Re: Weird Python Integers

#55
post #36

In [7]: a = "foo" In [8]: b = "foo" In [9]: a is b Out[9]: True In [10]: b = "foobaljlajdfsklfjds l;kjsl;dfj ls;dfj l;skdj flsdjluejsklnm " In [11]: a = "foobaljlajdfsklfjds l;kjsl;dfj ls;dfj l;skdj flsdjluejsklnm " In [12]: a is b Out[12]: False Seems to work with small and big strings too.

Relevant code here:

https://hg.python.org/cpython/file/f254ceec0d45/Objects/code...

Its not actually length, its whether the string looks like it could be a python name, and it only happens for string literals.

Re: Weird Python Integers

#56

Summary: Integers in python are full blown objects. Small numbers are stored in a central preallocated table where each entry represents one number. Setting a variable to a small integer makes it point to an entry in that table. Multiple variables may point to the same small integer objects in that table. Fooling around with the table leads to funny results.

It's just like Fortran, where everything including a constant is passed by reference, so if you assign to your arguments you might corrupt your program's only copy of 7 unless the linker put it in a read-only page.

Could you be more specific? Fortran passes arguments by reference, but writing to an argument won't mess up the "program's only copy of 7".

For example, the first output of the following program is 4, but the second is still 7.

       program main
       integer m,n

       m = 7
       call corrupt(m)
       write (*,*) m

       n = 7
       write (*,*) n
       stop
       end program main

       subroutine corrupt (a)
       integer a
       a = 4
       return
       end

Re: Weird Python Integers

#57
post #44

Is there any practical reason to use "is" to compare two ints (other than demonstrating integer interning)? Should doing so produce a warning?

I'll take it one step further - I don't think I've ever used `is` for anything other than comparisons to `None`.

It's useful when you want a sentinel object and you don't want to use None as the sentinel because it is a valid value. Some discussion here:

http://www.ianbicking.org/blog/2008/12/the-magic-sentinel.ht...

Re: Weird Python Integers

#58
post #35
post #24

https://github.com/adtac/exterminate Plugging my near useless Python library that does this and a lot of other subtle, annoying things to break programs. The library is essentially a display of how much Python actually exposes to the user and how modifiable it is.

Wow, the alternative print is extra evil ... >>> from exterminate import AltPrint >>> print("Hey! How are you?") Yo dawwwwg! Wuz crackalackin' yo? ... because that string is not calculated locally, but retrieved via HTTP from an API call. So everything you print is sent to an external server. AltPrint calls Gizoogle.translate(): https://github.com/adtac/exterminate/blob/f18862ed5b2e143e18... And Gizoogle.translate()…

print("'; drop table users")

Re: Weird Python Integers

#59
post #45

Earlier quoted context omitted.

The same is true for Java apparently: https://stackoverflow.com/a/2001861

That's only the case if you specifically treat them as full-blown objects. If you treat them as primitives they stay as primitives. Note that the type of these local variables is `Integer` rather than `int`.

Although you are technically correct (the best kind of correct), it is still a shortcoming of objects (or maybe just their implementation in Java).

It is just a bad idea to implement the '==' operator using comparison on addresses instead of on values and I consider languages pretty low-level that do that.

In a sane language == is always a function adhering the attributes of an equivalence relation (reflexivity, symmetry and transivity), where a user can expect an actual value comparison - AFAIK one is advised to overwrite `equals` in e.g. Java, but I do not think this is good design.

//edit:

There is no obvious answer, as one could argue, that languages just use different names for the same concepts ('==' vs 'equals') and consider comparison by value or by reference more fundamental (and choose '==' for that).

Re: Weird Python Integers

#60
I wrote a blog post about this in the past. It's really fun going through the oddities of the language like this.

It caches small integers, but also literals used in the same interpreter context (I'm probably getting that last term wrong). You'll get different results if you run these in from the shell as opposed to executing a script, try it out!

Here's a fun example

    >>> x = 256; x is 256
    True
    >>> x = 257; x is 257
    True
    >>> x = 257
    >>> x is 257
    False
    >>> def wat():
    ...   x = 500
    ...   return x is 500
    >>> wat()
    True
Post reply on HN