3 ms·
I took the same quiz, and noticed the exact same. When I saw the first one, my thought was "crap, I don't remember how many integers python interns", and then I
by makmanalp 9y ago
I took the same quiz, and noticed the exact same. When I saw the first one, my thought was "crap, I don't remember how many integers python interns", and then I saw the next question and figured it out, but it was sort of silly that a lot of their test was stuff like this that can easily be looked up and can change by implementation (e.g. does pypy do the same? ironpython?) Plus, I was a bit mad that they wouldn't tell you which ones you got right or wrong, or even how many. Why did I bother taking it then?
- squeaky-clean 9y agoYeah, they never emailed me the scores either, and told me there was no way to know at the booth... I even joked with them that they were just trying to link it to my fb profile. I actually didn't catch the trick until I asked someone later if they had gotten the same problem twice, "Almost, but the values were different" which is when I realized it (I blame the beer during opening night). However, as I found out today, because the way they worded the question it was all on a single line (if I remember correctly). So both cases should actually have been True, and I was right both times :P > (e.g. does pypy do the same? ironpython?) I wasted... ahem, spent a few hours today playing with this and found a few things, it's pretty neat! In PyPy, `is` will always be True for primitives. This also means NaN is NaN (but still never == NaN). It doesn't use memory location for things like id() like CPython does, but it guarantees you get a unique representation. [0] In CPython (3.5.2), it will always cache [-5, 256]. Here's the code that creates that array at startup [1] and each possible init/copy function calls this first to see if it's a cached int [2]. But it can sometimes cache other values! It also depends on if you do it from a module or the repl, and it's different depending on what scope or line each name/value is on. This one weirded out some coworkers, all from one continuous repl session: >>> x = 500 >>> x is 500 False >>> x = 500; x is 500 True >>> def wat(): ... x = 500 ... return x is 500 >>> wat() True >>> x = 500 >>> def wat_wat(): ... return x is 500 >>> wat_wat() False If you run it from a script you instead get True, True, True, False. You can disassemble it to get a hint at why. One uses STORE_FAST and LOAD_FAST, and the other LOAD_GLOBAL. >>> disassemble(wat.__code__) 2 0 LOAD_CONST 1 (500) 3 STORE_FAST 0 (x) 3 6 LOAD_FAST 0 (x) 9 LOAD_CONST 1 (500) 12 COMPARE_OP 8 (is) 15 RETURN_VALUE >>> disassemble(wat_wat.__code__) 2 0 LOAD_GLOBAL 0 (x) 3 LOAD_CONST 1 (500) 6 COMPARE_OP 8 (is) 9 RETURN_VALUE Now I'm still trying to figure out why STORE_FAST and LOAD_FAST cause it to use the same object, and why those only get called when it's interpreted together. When I figure this out I might put together a longer post about all this. Also don't use `is` for comparing integers. ;) [0] http://doc.pypy.org/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id http://doc.pypy.org/en/latest/cpython_differences.html#objec... [1] https://github.com/python/cpython/blob/master/Objects/longobject.c#L5491 https://github.com/python/cpython/blob/master/Objects/longob... [2] https://github.com/python/cpython/blob/ba85d69a3e3610bdd05f0dd372cf4ebca178c7fb/Objects/longobject.c#L63 https://github.com/python/cpython/blob/ba85d69a3e3610bdd05f0...
- makmanalp 9y agoWow, this is amazing research! I had no idea the rules actually varied this much. The same like one is especially odd. The LOAD_FAST seems to make sense because it's defined as : "Pushes a reference to the local co_varnames[var_num] onto the stack." (emphasis mine). Also see the global case: In [2]: x = 500 In [7]: def wat_wat_wat(): ...: global x ...: x = 600 ...: return x is 600 ...: In [8]: dis.disassemble(wat_wat_wat.__code__) 3 0 LOAD_CONST 1 (600) 2 STORE_GLOBAL 0 (x) 4 4 LOAD_GLOBAL 0 (x) 6 LOAD_CONST 1 (600) 8 COMPARE_OP 8 (is) 10 RETURN_VALUE In [9]: wat_wat_wat() Out[9]: True But this only goes further to prove my point - it's a bit of a silly question to quiz someone on :-) For one the question didn't seem to be well defined enough, but also it tests something that no one in their right mind would do, and also I don't know if the authors realized these nuances themselves either. I guess it makes for good trivia.
- squeaky-clean 9y agoHaha thanks, I was inspired by David Wolever's talk this year. This is the first time I've gone through the disassembler module or the CPython source, it's much less intimidating than I thought it would be. Also wat! The bytecode for the global case makes sense, but I wasn't expecting True?!
- makmanalp 9y agoYeah, now I'm even more confused!