Python bug: Can assign [] = (), but not () = []
bugs.python.org
bugs.python.org
Perhaps based on older versions of PHP or merely uninformed snark?
>>> 'x'*3.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'
>>> import numpy as np
>>> print 'x'*np.float64(3.5)
xxxIs this behavior because numpy overloads the multiplication operation with a string as string repetition and then implicitly casts the float64 down to an integer of 3? I'm curious why this behavior manifests. When I get a chance I'll test 'xyz'*np.float(3.5)
>>> "x" * 3
xxx
The only weird part (and it's not that weird IMO) is that numpy's "float" can be implicitly coerced to integer. >>> import warnings
>>> warnings.simplefilter('always')
>>> 'x'*np.float64(3.5)
__main__:1: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
'xxx' xxx›(it makes sense if you know why Roman numerals look the way they do)
>>> (a, b) = 2, 3
>>> {a, b} = 2, 3
File "<interactive input>", line 1
SyntaxError: can't assign to literal>>> a, b, c, d = {1, 2, 3, 'a'}
>>> a
'a'
Regardless, it shouldn't be surprising when writing insane code, that the language starts acting insane. Python as a whole is pretty decent when it comes to handling syntactic edge cases.
[0]: https://docs.python.org/3/reference/simple_stmts.html#assign...
[] = (); VM105:2 Uncaught ReferenceError: Invalid left-hand side in assignment
() = []; VM114:2 Uncaught SyntaxError: Unexpected token )
>>> True = False
>>> False = True>>> 1 if False else 0
1
>>> bool(0) == False
False
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> (True, False) = (False, True)
File "<stdin>", line 1
SyntaxError: can't assign to keyword >>> (False, True) = (True, False)
File "<stdin>", line 1
SyntaxError: can't assign to keyword In[2]: (True, False) = (False, True)
In[3]: True
Out[3]: False
In[4]: 1 if False else 0
Out[4]: 1
In[5]: 'yes' if bool(0) == False else 'no'
Out[5]: 'no'
In[6]: bool(0) == False
Out[6]: False
What bothers me here is that when the interpreter says "False", it clearly means the opposite of (the new) False. So by reassigning True and False, I've actually caused inconsistent behavior in python, not just really-confusingly-named behavior. Suddenly False sometimes means one thing and sometimes means something else. >>> A()
False
>>> bool(A())
True
>>> type(A())
<class '__main__.A'>
A repr is just a representation in development context, nothing more and nothing less, there is no requirement that it be sensible or of any use, though that's certainly recommended (contrary to __str__/__unicode__ which should be silly): >>> B()
A gray parrot
The only "inconsistency" you've created is that False in the console's local namespace does not match __builtins__.False or the interpreter's internal False object. You can still access the former by the way: >>> False
True
>>> __builtins__.False
False
unless you also override it: >>> __builtins__.False = True
>>> __builtins__.False
True
the interpreter still does not care though, you've just broken any Python code relying on the builtin (you can actually alter the "true" False object via ctypes)You could write (False, True) = (True, False) though.
(https://gist.github.com/Jach/1208215 works in Python 3 too.)
try:
True
except NameError:
True = 1==1
False = not True
Such code would likely be at least 10 years old. Given the transition to Python 3, it seems the general answer is "yes, they deserve to die."Also, I don't see how that wouldn't be compatible with forbidding assignments to True/False. It'd never execute the except block.
from _compat import True, False, next, enumerate
This is allowed under Python 2, but not under Python 3. As you suggest, it could be made possible to allow an import like this so long as the actual imported value is indeed the True or False singleton. But it's a lot of work with little gain.While on the other hand, even in Python 2 it was a SyntaxError to say "None = None" or to import None. Extending that check to include True and False is much easier, and consistent with existing use.
I got stuck for a while trying to back out. Finally figured the way to reverse is to use del(): del(True) del(False).
stuff = ()
print(type(stuff))
<class 'tuple'>