4 ms·
I took a quiz at the Facebook booth at PyCon this past weekend. It was Python specific, but had a few annoying gotchas. There was one question in there twice, b
by squeaky-clean 9y ago
I took a quiz at the Facebook booth at PyCon this past weekend. It was Python specific, but had a few annoying gotchas. There was one question in there twice, but with 2 different values for the input (which is what tipped me off that it was a trick).
It basically relied on this fact...
x = 256
x is 256 # True
y = 257
y is 257 # False
Which for one, you shouldn't use `is` to compare integers in Python. I wish I could have just written that as my answer.
Secondly, you need to be aware the CPython uses an integer cache which causes the answers to be different. You'll actually get different answers based on whether you run it as a file, enter it line-by-line into the interpreter, or use a different implementation such as PyPy.
https://stackoverflow.com/questions/15171695/whats-with-the-integer-cache-inside-python https://stackoverflow.com/questions/15171695/whats-with-the-...
There wasn't any point to the quiz, so it's okay that they put in silly questions like that. But it's clearly there just to try and trick you, and not quiz you on anything relevant. Most of the other questions were tricks of the sort, or or Python 3 specific gotcha's.
- Bartweiss 9y agoThat's kind of nasty. It's certainly fun to play with pathological language features, but it's not exactly a useful thing to test on when the answer is "don't do that". I'd enjoy a JavaScript quiz on some of the "wat?" features, but I wouldn't want to be evaluated on my ability to guess them.
- squeaky-clean 9y agoSeriously! I think these sort of tricks are really fun (I read IOCCC and other stuff), but I only know this because of a famous codegolf answer that takes advantage of this trick [0]. I wouldn't expect anyone else to know it, and don't consider it something positive or negative as far as programming skill is concerned. It's kind of related to interest, but admittedly I waste a lot of time playing with stupid details like this in programming languages, so maybe it actually makes me less productive than the average person. [0] "Write a program that makes 2 + 2 = 5" https://codegolf.stackexchange.com/a/28851 https://codegolf.stackexchange.com/a/28851 edit: wording change
- nebabyte 9y ago> There wasn't any point to the quiz Knowing fb, there might well have been; if they had a facial recognition webcam up and noted applicant scores no one would hear about it. They'd probably just call it an "experiment in hiring"
- teekert 9y agoAs a Python beginner I'm completely flabbergasted... How can this be? And why can't I use "is" to compare integers? This is insane. The quoted stackoverflow is not very readable to me... By the way y == 257 does work.
- kbp 9y ago"is" is for asking whether two objects are the same exact object in memory. "==" is for asking whether two objects are logically equal, ie, that they represent the same value. As an example: >>> x = [1,2,3] >>> y = [1,2,3] >>> x == y True # two lists with the same values; equal >>> x is y False # two different lists; doesn't matter that they contain the same values >>> z = x >>> z is x True # same list object in memory Because here you want to know if the two integers are logically equal, not if they're necessarily the same object in memory, you want "==" and not "is". Due to an optimisation, "is" might work for small integers, depending on implementation, but the takeaway is not to use "is" for value comparisons; that's what "==" is for.
- mattbreeden 9y agoTo expand on this, python creates some values as singletons to save memory/speed things up because they are used so often. The most well known examples are True/False/None. That's why you can always do None is None, because all None are the same None in memory. Python takes this a step further by creating lower integer singletons. So any integer from 0-256 (not sure about negatives) will always be the same number in memory. Above 256 python will start actually allocating memory for integers, so two of the same number won't be at the same memory address, and there for won't be comparable by 'is'.
- bakery2k 9y ago0-256 not sure about negatives -5 to 256 (inclusive) [https://github.com/python/cpython/blob/master/Objects/longobject.c#L18 https://github.com/python/cpython/blob/master/Objects/longob...]
- 9y ago
- makmanalp 9y agoI 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...