Hacker News new | ask | show | jobs
by pfarnsworth 3439 days ago
I've been programming for 20+ years, and recently moved over to Python. Sure, I could code on day one and figure out how to get programs working pretty easily. But the nuances with it are still things I need to work on a lot. I still don't program Pythonicly, I program like a C programmer writing Python. In fact, I probably program in all languages like I would a C programmer, and that's not good enough, in my opinion.

I have fallen in love with Python because it's so damn easy to get productive, and I really want to be a great Python programmer. That takes a lot more time than the OP suggests, and requires you to immerse yourself in the patterns of the language and in the community, in my opinion. Not just dabble a bit and then check a box saying "I'm a polyglot!"

9 comments

May I suggest this book specifically tailored for python best practices? https://jeffknupp.com/writing-idiomatic-python-ebook/

Its a wonderful read. Will really unleash the pythonista inside of all us!

If you really want to go deeper, I suggest these as well:

https://goo.gl/CY6zPu https://goo.gl/UbMrTb

Those shortened links take you to amazon (not affiliated in any way, FYI, just though the length of the URLs was obnoxious)

Those are the definitive python programming books I came up with anyway.

While we are at, I have to say once I learned to really code Pythonically I find that I can apply the PEP8 standards to almost any language. Admittedly, I, like John Siracusa, am a top level language debutante and don't live in C or C++ production code (I sometimes use objc but swift is...easier :). I remember learning C, and thanks to arduino I certainly using some varient of C/c++ there more heavily, but my coding style follows more or less the pythonic standard (with PEP8 being the backbone of that).

food for thought, people of hacker news!

> Those shortened links take you to amazon

Just FYI: Hacker News already shortens links, no need to pass them through a 3rd party service. I personally prefer seeing a readable domain name before clicking (as I'm sure many others do as well).

Had no idea. I do appreciate this. I must of missed the 'splainer. I'll remember that for next time.
Just FYI, you can remove all the parameters from Amazon URLs and they still work. EG: https://www.amazon.com/Fluent-Python-Concise-Effective-Progr...

You can also emit the title: https://www.amazon.com/dp/1491946008/ works fine.

And yet another trick for shortening Amazon links: http://amzn.com/1491946008
But then the same question as with other short URLs appears: Does amzn.com really belong to amazon.com, or is it a third-party service that may redirect you somewhere else at will?

The point is, I don't care whether amzn.com really belongs to amazon.com or not. I want to check a domain quickly without having to research that kind of stuff.

Thanks for sharing these. I've been writing a lot of python code solo lately and have started to worry about how to make it more pythonic so it's maintainable and comprehensible to any future collaborators.
> I probably program in all languages like a C programmer

As the old "Real Programmers Don't Use PASCAL" article says,

> The determined Real Programmer can write FORTRAN programs in any language.

Real Programmer can write FORTRAN programs in any language.

That's why Haskell exists. It's the computer scientists' best attempt so far to create a language in which it's impossible to write FORTRAN programs.

I dunno, combining the do statement, the <- assignment operator that I learned from R, and the forM_ monad, I think I could write some good Fortran.

Haskell also appears to have a very interesting form of goto:

https://wiki.haskell.org/Compose#Using_Cont

With Haskell's advanced type system, could we recreate implicit int/real typing, and perhaps even EQUIVALENCE?

Hat tip for anybody that pushes a MonadGoto into hackage, with the obvious Goto and GotoT implementations :)

Bonus points for also implementing the ComeFrom interface from Python's comefrom joke package!

They accomplished that by creating a language in which it's impossible to write programs in general ;)
For what definition of "impossible". All I need is Turing completeness and time.. ;)
Ladies and gentlemen, this is a real programmer :).
As a Python programmer of 10+ years, here's the most Pythonic tip you can get:

Don't try to be clever, do the simplest (and most readable) thing that will work.

Try "import this" in an interpreter to read a bit more on the above.

... Except generators and comprehensions are often faster than for loops in your hot path.

Apart from that... What's readable tends to be the best option.

I think the Python community considers list comprehension more readable than loops.

And writing generators allows you to write simple code with them. I don't consider generators to be fancy - just a tool to pull out complexity into a small area and make the rest of the code readable.

Would highly recommend Fluent Python.

http://shop.oreilly.com/product/0636920032519.do

A thousand times yes.
It takes a while to get used to the idiomatic constructs of a language. Luckily it's much easier than with natural languages.

My first Ruby programs were very Java like. I doubt that my first Java programs were C like, if you use classes and methods it just can't be. No problem with using Python and Ruby together. They are maybe like German and English, close but clearly distinguishable. And Javascript, Perl, PHP, Elixir... too long to write about.

A consequence of multilingualism is that one starts noticing the differences in the implementation of the same features in different languages. Some are smooth, others are frustratingly hard to use or to remember. A quick test on a trivial nuisance, you must not Google it: in Python it's array.join(",") or ",".join(array)? And "1,2,3".split(",") or ",".split("1,2,3")? I remember only that "," goes to the opposite ends in the two expressions and I can't understand why that should be good.

The first one is neither - it's string.join(iterable). If you keep that in mind then the design becomes clear - it would have been weirder to force every iterable to have some string-related method. Better to put it on string, where it more reasonably belongs.

The second one is the typical OO pattern where you ask an object to perform some operation on itself. This is how split works in just about every OO language - if you have trouble remembering it, it might be helpful to remember split can be called without any parameters - in that case your alternative variant won't make any sense.

It makes more sense now, thanks. I missed that the argument is an iterable. Ruby's join is a method of Array and of nothing else. Examples with ranges:

Ruby's range must be converted to Array.

    > (1..20).to_a.join(",")
    "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20" 
Python's range must be converted to a list of strings.

    > ",".join([str(i) for i in range(1,21)])
    '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20'
I've noticed my Elixir experience bleed into how I write Ruby. I'm much more likely to avoid creating objects if I can solve things with a pure function in Ruby now.

And for things like pattern matching, I've played around with doing similar things in Ruby, too. For example, in Elixir you might write a method that should only ever return `:ok`, and a pattern match like this...

    # if :ok, nothing special happens
    # if not :ok, "MatchError" is raised
    :ok = Fooer.foo(foo)
So in Ruby, I played around a watered down equivalent like this

    def ok!(obj)
      raise "match error" unless obj == :ok
    end

    # if :ok, nothing special happens
    # if not :ok, "match error" is raised
    ok! fooer.foo
One day I wrote a bunch of Ruby code of 'ok! <arg>` all over the app, and it made getting the program to run correctly a lot easier (at a time my brain was acclimated to Elixir). I don't know if I'd ever try getting developers on a Ruby project to embrace Erlang/Elixir's "let it crash" mentality, which might not be a great idea for a number of reasons, but it was interesting to me that I had even considered it as an option. Before writing Elixir code, writing a program that crashed on purpose was an alien concept to me.
If you want to create a string from a bunch (iterable? tuple? list?) of smaller strings - shouldn't that be a string method?

If you want to split a given string into smaller strings with an arbitrary delimiter, which instance should you call the method on?

What I love about Python is that it's so similar to how I've written pseudocode over the years. So, I often do quick prototypes of ideas in it, even if the final product isn't in Python.

Like you, I'm basically a C programmer at heart. But, to get efficient at some of the Maple code I had to write for my graduate work, I learnt a number of their functional tools so I now think quite a bit about using some of those as part of my toolset. I'm still largely a C-style programmer, though.

Working with the SymPy project helped me in my Python style.

Additionally, if you really want to get productive, you'll also need to get to know which libraries/frameworks to use, and how to use them (idiomatically). This is the most time-consuming tasks, I think.
Been wanting to move over to python myself. Love the language but don't feel I write pythonic code, so I appreciate your comment.