Everyone waxes lyrical about how Python 2.x was "good enough and why would you change it", but there were several things in Python 2.x that were objectively awful (unicode was broken, iterator variables can leak to the outer scope, division of integers producing integers, xrange, raw_input, mixed indentation "working", etc). And while no single issue alone would justify Python 3.x, the combination of all of these issues as well as some other semantic problems justified the need for Python 3.
Of course, that being said, Python 3 also had some issues that it took several versions to iron out.
{Describing the old python-2 behavior:}
-------- Quote: -------
The classic division operator makes it hard to write numerical expressions that are supposed to give correct results from arbitrary numerical inputs. For all other operators, one can write down a formula such as xy*2 + z, and the calculated result will be close to the mathematical result (within the limits of numerical accuracy, of course) for any numerical input type (int, long, float, or complex). But division poses a problem: if the expressions for both arguments happen to have an integral type, it implements floor division rather than true division.
-----------------------
To guarantee the correct mathematical behavior in python2, one would probably have to write:
def true_math_div(a,b) :
if type(a) is int or type(a) is long :
a = float(a)
if type(b) is int or type(b) is long :
b = float(b)
return a/b
as a and b could be int, float, complex, or some object defining the method __div__.The new case of / always being float division and // always being integer division just makes everything more explicit.
z = 3/y
you'll know that y is either always a float or always an int depending on its type and thus you'll 'know' what z is.I'm not a particular fan of that - they should have changed the name entirely, IMO, eg. to Rby - but Perl 5 is not getting discontinued.
It's really sad. In retrospect they certainly should have named it something different. The Perl 5 community could have progressed, maybe even made a Perl 6, while the NGPerl skunkworks project continued independently for 15 years.
I get that for people with no knowledge of programming whatsoever it can be confusing, but it's standard behavior in nearly every typed language.
In C/C++, you divide an Int and you get an Int. If you want floating point division, you divide by a float. Problem Solved.
Almost EVERYTHING else could have been done with slow migration, or simply documenting the odd or quirky behavior.
Iterator variable leaking is just a result of poor programming.
Raw_input vs input could have been solved by slowly deprecating input. Or just left as is.
xrange is the same story.
It all seems like someone just decided to throw their hands up in a fit, throw their toys on the ground, and make a new Python. I enthusiastically jumped at Python 3 in the begining, then ran into problems, and crawled back to my 2.7 and decided I could let others fight the stupid cult war that was coming over 2 vs 3. I'd rather use a tool that works than change all my code over someone's idea that newer is better.
And hence why it's a problem in Python. If you have a function like
def foo(a, b):
return a / b
What are the types of a and b? You don't know. Sure, you could check with isinstance, but now you've broken the illusion of duck typing. The argument is that Python should just do "the right thing". Just because 3/4==0 in most languages doesn't justify repeating that mistake. Not to mention that float(a)/float(b) -- aside from being incorrect in the general case -- is ugly as hell.> Iterator variable leaking is just a result of poor programming.
I think it's a language bug. Why? Imagine if you could do this in C:
for (int a = 1; i <= 3; a++)
foo(a);
printf("%d\n", a);
People would think this is clearly a language bug because it breaks the scoping semantics (not to mention common sense). Now, you could argue that Python supports this sort of nonsense so it's "fine": # a is not defined
if something:
a = 1
else:
a = 2
print(a)
But the reason that works is because otherwise Python would need to have JS-like "var" syntax to declare a variable. Personally I think that'd be better, but the for-loop situation is different.> raw_input vs input could have been solved by slowly deprecating input. Or just left as is. xrange is the same story.
And this is how PHP ended up having three different string escaping functions for SQL statements. The first one (escape_string) was broken, so they added real_escape_string, and then they needed to handle connection-specific quirks so they added mysqli_real_escape_string.
Some people still use escape_string even though it's broken -- and the language devs cannot fix it because "that would break users".
I don’t recall it ever surprising me or behaving poorly.
I know rather too much about how CPython and other VMs work under the hood and am in no mood to try and save the day any more. I still use python, but the latest stuff around MyPy and async io just make me despair frankly. I think rust+go will probably pick up a lot of people who used to care deeply about python. So it is.
Meh, more like a clutch for systems where you couldn't install List::UtilsBy. (One of my favorite Perl modules of all time.)
In retrospect it probably would have been better for the community if they'd given Perl 6 a new name.
The library ecosystem is the problem, and it's what's driving the language churn.
https://www.curiousefficiency.org/posts/2014/08/python-4000....
I would say instead: for any good computer language, new versions need to retain compatibility with old versions. Every single system I run has python 2.7 (including my brand new Macbook running latest OS X). Luckily I don't need numpy, and I can probably do without python at all if I have to.
Compare to perl: I can run old perl scripts on basically any system without having to worry about it breaking. I do all of my server scripting in perl for this reason.