Hacker News new | past | comments | ask | show | jobs | submit login

> Python programmers and companies with python code should spend the time and effort to move to python 3 instead of spending that time and effort to backport stuff to python 2 because python 2 is deprecated and the future is python 3.

I hate Python 3's removal of the (lambda (key, value): blah) tuple unpacking syntax, and the forcing of parentheses for print statements. They might seem minor but they aren't for me. So I'm not at all eager to move to version 3 and don't really see any benefit. Not sure if those who aren't migrating feel the same way, but I wouldn't be surprised if some of them do.

(Edit to address comment below: There are more issues I have with Python 3. It allows more bugs to slip through, for instance. I actually particularly like a comment I just wrote, so I'll link to it here: https://news.ycombinator.com/item?id=13145299 Do note that this was added after the reply below.)




Benefits? Unicode. Async. Extended library. Required keywords. syntax inprovements (lots of m, many more than just the removal of the print statement). Type hinting.


> Benefits?

I meant I don't see any benefits for me, not benefits for other people. I assumed that was clear; sorry if it wasn't.

> Unicode.

Yeah, but some people have still been living without the changes, and it's hardly enough of a reason on its own (for me anyway) when there's other things I hate about the language.

> Async.

It's a nice feature, yeah. I can live without it, as people have for many years. Maybe if I was used to having it around I wouldn't want to go back, but I'm not.

> Extended library.

Cool! I'm not sure what exactly falls under this that I'm supposed to be missing, but pip install has sure been taking care of everything in the blink of an eye in version 2.

> Required keywords.

Cool! I need it about as much as I need a donut.

> syntax inprovements (lots of m, many more than just the removal of the print statement).

nonlocal is literally the only positive one I can think of right now that I'd actually care about. But then again, it comes up maybe 50x less often than the parentheses I have to write for print, or the tuple unpacking that I have to do. So yeah, it's hardly a reason to migrate.

> Type hinting.

Nice to have. I'm living just fine without it. Maybe I'd have migrated if it actually optimized things or did something more useful.


Well, things change, especially in tech. For better or worse, but most of the time for the better.

You should read some changelogs of past python 3 releases. 3.6, for example, has ordered dicts by default. Which is quite convenient when you need to write test testing a small dict with two items for example.

I like driving an old muscle car, most of m look beautiful and bring me everywhere i want. But damn, those new cars changed a lot and are much more comfortable. (But they do break as much ;))


Pretty sure they say NOT to rely on the ordered nature of the new dicts. So definitely not something you want to put in your tests.


The intention is to make the order guaranteed in 3.7 or 3.8, AIUI. There was some desire to prove the new implementation before guaranteeing its behaviours (i.e., in the worst case, if it turned out to be broken, they could revert to the 3.5 code and it would be valid).


No it is in 3.6 already! It used to be not guaranteed.

https://mail.python.org/pipermail/python-dev/2016-September/...

But it is insertion order indeed, not sorting order.


The behaviour is there in CPython, yes. But the language documentation doesn't, deliberately.


People often bring up the unicode thing but tons of Python code is backend glue code that really doesn't care at all about unicode.


So you _hate_ Python 3 because of two changes in syntactic sugar? I would understand if you hated it because of the real breaking changes, but no...

I think you just don't comprehend the multitude of problems that Python 3 fixes by handling strings correctly... Maybe you've never handled Unicode before.


> So you _hate_ Python 3 because of two changes in syntactic sugar?

First of all, the tuple unpacking one is a HUGE readability AND maintainability issue; it's not just syntactic sugar. var[0][1][2] is not only far less readable than the unpacking notation, it doesn't even have the same semantics (doesn't enforce the structure of the tuple).

That means Python 2.7 helped me catch more bugs. Think about that!

Second, no, I just listed the two that irritated me the most every time I tried to switch, because they were the first things that came up by far the earliest and most frequently. Small inconveniences can be amplified through their frequencies. There are lots of things I don't like about it though... division becoming floating point division, having to say list(foo.items()) or list(map(...)) instead of just foo.items(), etc... again, more verbosity and typing for common cases where I really didn't mind the old way. If I wanted imap(), I could've just used imap; they could've just moved that to __builtin__ and made my life easier that way.

By the way -- the lazy nature of map(), etc. also means you catch fewer bugs now. Again, think about that! Just because it looks more efficient, that doesn't mean it's actually better. If there's anything I've learned, it's that even the smallest things tend to come with non-obvious tradeoffs.

Finally, regarding strings: if you look at my earlier comments, yes, I already acknowledged the Unicode changes were for the better. Awesome. I agree. Cool? OK, but there are other things in the language besides Unicode though, and they're not as awesome. I don't spend my entire programming life dealing with Unicode strings, so I care about other things too, and they make my life harder. Simple as that.


If your needs are for static analysis and type checking at compile-time, you are using the wrong language.

I'm a huge lover of Python, but I drop into C# when I need stuff like that. Or Go. Or Rust. Or something.

You're just making bad decisions here.

If you're looking to catch bugs in your code before you test or deploy it, don't use a dynamic language.

Python has never been and probably never will be a language with declarative types and the checking that allows.

Pick a different hammer if that's the nail you need to hit. Don't complain about the hammer you want to use not being a screwdriver.


Regarding tuple unpacking, instead of writing, say:

    def foo((birthname,surname)):
        ...
you can write in Python 3:

    def foo(name):
        birthname, surname = name
        ...
It's not less readable. I also missed it in the beginning, but it's not really a big deal. (I think they couldn't keep the feature because of how '*' is used, but I am not sure.)

Edit: If you have problem with this in lambda expression, just create a named inner function. It's a feature/shortcoming (depends on POV) of Python that you cannot bind variables in an expression. I hope you understand that they couldn't keep the feature in lambdas if they didn't keep it in proper functions.

I am sure if you think about other things, there are good reasons to do it the way Python 3 does it, usually there is a hidden case where things need to be disambiguated (like your list() examples).


I wish I could downvote. I specifically said I hate the tuple unpacking syntax change in lambdas. That's where I used it so much to begin with, not in defs! I obviously can't put statements like that in lambdas, and until now I didn't need to do that to make my code readable. Now I have to name all of my lambdas just to make this syntax work, which is nonsense. It used to be there and it worked perfectly fine.


Why would you want to downvote somebody trying to help you?

In any case, I think I see your problem. You are not the sole user of Python language. There are features that other people like (such as using '*' in unpacking), and so features you like are weighted against their use cases, and a reasonable compromise is made.

And frankly, I think if you like to use lambdas that much, you really want to program in a language where everything is an expression, such as Lisp or Haskell.


> In any case, I think I see your problem. You are not the sole user of Python language.

I'm glad I'm not. Otherwise I probably wouldn't be using it either. Not sure how that is my "problem".

> There are features that other people like (such as using [asterisk] in unpacking), and so features you like are weighted against their use cases, and a reasonable compromise is made.

I like that [asterisk] syntax too.

> And frankly, I think if you like to use lambdas that much, you really want to program in a language where everything is an expression, such as Lisp or Haskell.

Or I could just keep using Python 2.7 which works just fine, and not move to version 3 where I'm not welcome.


> Not sure how that is my "problem".

It's your problem in e.g. where you want list returned by default where Python 3 returns an iterator by default. Why is that useful for many people was already explained.

> I like that [asterisk] syntax too.

Funny, AFAIK it is Python 3 only.. https://www.python.org/dev/peps/pep-3132/

> Or I could just keep using Python 2.7 which works just fine, and not move to version 3 where I'm not welcome.

You are welcome to use Python 3, but - suit yourself. :-)


> Why would you want to downvote somebody trying to help you?

Misreading comments is not helping.


That's why I used the word "trying". Maybe you should read more carefully before you want to accuse others from misreading something. ;-)

I think it's unfair to say that I misread his comment - he doesn't explicitly mention he is aware of the workaround I outlined for the functions, and that he is bothered with lack of tuple unpacking in lambda expressions only, not in ordinary functions.

Regardless, I still think it's quite impolite to downvote somebody who wants to help you and misunderstands you, if they are not e.g. factually incorrect. If you don't actually tell me where I am wrong, I cannot improve my answer. Also, this is not Stackoverflow, where that could be marginally acceptable (I am very strongly against downvoting without explanation).


> Regardless, I still think it's quite impolite to downvote somebody who wants to help you and misunderstands you

Well, I don't consider it a "misunderstanding" when there are literally just 2 things to note in my comment that you're replying to ("lambda" and "tuple unpacking") and you still somehow miss 1 of them. I think it totally deserves a downvote, because it makes me look stupid when you present a reasonable solution to a non-problem and make readers assume I was saying something other than I was, and on top of that I have to waste some 5-10 minutes of my time replying. That's not something I appreciate.

That said, like I said, I never actually downvoted that comment (because I obviously couldn't). So you don't need to worry about the internet points.


If you weren't busy taking things so personally, you could note that I already hinted in my comment on why I made it - I missed the feature of unpacking within function arguments myself at first too, until I realized that unpacking within the body isn't really less readable. (And please - do not waste time replying.)

I admit I don't use lambdas that much, since generator expressions (which is like Python 2.3) they aren't really needed too frequently. And in most cases you're better off using function anyway, because in Python statements are not expressions, as I already also stated. For example, I use print() for debugging frequently and this is tough to insert into lambda. (And even in Haskell I prefer to name subexpressions to lambda syntax.)

> That said, like I said, I never actually downvoted that comment (because I obviously couldn't). So you don't need to worry about the internet points.

I am not worried about internet points (I actually got about 80 of them on this discussion alone, which is frankly ridiculously too much, and in practice, I find that comments I personally find to be the most insightful only rarely get most points), I am just really annoyed when somebody downvotes my comments without any explanation, because I am a very curious person and in most cases it's just a honest misunderstanding, which could be cleared up with, I don't know, actual communication?

And at least two or three other people actually downvoted my original comment, so I would like to use this opportunity to invite them to come forward with an explanation what they found so wrong about it.


Lambdas are not really pythonic these days anyway

  list(map(lambda (some, thing): some + thing, everything))
  # better
  list(some + thing for (some, thing) in everything)
Or, as the parent suggests, just create helper function, preferably one your python environment doesn't need to set up every time your outer function is called

  # okish, "verbose lambda"
  def compute(everything):
    def magic(elem):
      some, thing = elem
      return some + thing
    return list(map(magic, everything))

  # probably better
  def magic(some, thing):
    return some + thing
  def compute(everything):
    return list(magic(some, thing) for (some, thing) in everything)


> Lambdas are not really pythonic these days anyway

Too much nonsense in your comment. Really now? How about you give a realistic example where syntactic sugar doesn't substitute for it? Like what am I supposed to pass to sort(key)? And incidentally, this tuple unpacking problem comes up when sorting frequently... and that's the prime example on their web page (and a realistic one at that) for where you're supposed to use lambdas: https://docs.python.org/3/tutorial/controlflow.html#lambda-e... If you're telling me this isn't Pythonic, you're really just not being sensible.


Yes, Really Now! Your disdain for the answers people are giving you, and your abrasive demeanor tell me I can spend my time better than to discuss this further with you.


> Like what am I supposed to pass to sort(key)? And incidentally, this tuple unpacking problem comes up when sorting frequently...

I suggest you look at namedtuple: https://docs.python.org/3/library/collections.html#collectio...

I think you should watch some Raymond Hettinger's talks, he is discussing many little things like this.


Regarding laziness of map() - lazy is a good default, because you can always make eager out of lazy, but not the other way around. Lazy is also more general, because it can handle both lazy and eager inputs, while eager will always force a lazy input.

This has been the general trend in mainstream languages lately, not just in Python. E.g. in C#, all LINQ operations are lazy. in Java, the new stream API, to be used with lambdas, is lazy.


Notice in said languages they added lazy APIs. They did not remove eager APIs. Python already had imap, ifilter, izip, etc... I already said this and I'll repeat: I would've been just fine if they made those easier to use (e.g. no import). There was no need to change the behavior of existing APIs.


There were generally no map/filter/fold APIs in those languages, eager or lazy.

In cases where the APIs were there, they were generally not as easily accessible (i.e. they were the equivalent of imap etc, with some hoops to jump before you could use them). The new APIs are more straightforward to use.

The reason to change the behavior of an existing API is because the default (i.e. most obvious) API should also be the most flexible, and do the right thing in as many cases as possible. This was not the case with map etc in Py2.

The disadvantage of changing an existing API like that is that it breaks code. But Py3 broke code anyway, so it was a good time to introduce breaks like that for the sake of better defaults.


> There were generally no map/filter/fold APIs in those languages, eager or lazy.

Array.FindAll, Array.Convert, etc. all existed in C# beforehand. Though maybe this is what you meant in the next sentence.

> In cases where the APIs were there, they were generally not as easily accessible (i.e. they were the equivalent of imap etc, with some hoops to jump before you could use them).

This is going on a tangent but LINQ still has hoops to jump through. You have to say "using System.Linq;" at the top if you want to use the new syntax. That's like saying "from itertools import *" and then using imap, which you could've always done.


> Array.FindAll, Array.Convert, etc. all existed in C# beforehand. Though maybe this is what you meant in the next sentence.

Yes, it's what I had in mind. I have to admit that I completely forgot about ConvertAll (and so assumed there was no map).

I think the biggest reason why those weren't all that commonly used in practice, is because in .NET you often deal with opaque collection types (like ICollection<T>, or ReadOnlyCollection<T>, or even custom-made collections pre-generics) that are usually exposed on properties of objects. Since the concrete type is not known, you can't do List.ConvertAll etc.

This, by the way, is another point in the favor of lazy implementations - they don't care about input type, because the output type is always "lazy sequence". Of course, you can have an eager map similarly not care about input, but then what should be the type of its output collection by default? No matter what type you choose, someone will complain that they wanted someone else. Given Python's preference for explicitness, such design would warrant several functions like map_to_list, map_to_tuple, map_to_set etc. But, of course, if you have a lazy map, you might as well just write list(map(...)) etc.

> You have to say "using System.Linq;" at the top if you want to use the new syntax. That's like saying "from itertools import " and then using imap, which you could've always done.

It's a bit different, though. When you import itertools, it brings all those functions into your global namespace. But when you import System.Linq, it only brings one static class into your global namespace; the actual functions are extension methods that only show up on the types to which they are applicable. So the resulting namespace pollution is far less in C#.

There's also the issue of import being generally frowned upon in idiomatic Python, largely because the way conflict resolution works there (silent override). In C#, if you happen to have clashing identifiers from usings, it'll prevent you from using them unqualified, so there's no good reason to avoid it.


> and the forcing of parentheses for print statements

You mean print functions. I love the new change because you can pass "print" around like any other function now, letting you write code like:

  def my_map(data, func):
      for item in data:
          func(item)

  my_map(dataset, insert_into_database)

  # For testing
  my_map(dataset, print)


That seems kinda petty. Surely you can work around that. If they really were killer features that many devs used I doubt they'd have been deprecated and removed in python 3. I do agree that though I wish lambdas could be more useful instead of one liners.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: