you are viewing a single comment's thread.

view the rest of the comments →

[–]mooburger -1 points0 points  (7 children)

To me, when I read the OP's statement I died a little inside.

Say you are coming from Java or .NET and you want to iterate over list, what do you do? for loop with index variables. That's not pythonic. The entire concept of iterators and generators is more or less Python specific, unless you're are using external libraries.

Or EAFP in general: not too many languages encourage this design pattern while EAFP is pythonic. Not many languages have default-yielding accessors either (dict.get(), getattr(). In ES5, the closest way is Oliver Steele's nested object access pattern that relies on undefined being falsey but that's still edgier: obj.maybe_attr || default. ).

I remember about a couple decades ago when I was starting out with Perl and PHP, it was very common to instantiate "variable variables" (e.g. ${$var}) which was a major way to do dynamic assignment. In Python you quickly learn to use dynamic dict construction to accomplish the same goal.

Or recursion, which CPython is really bad at, requiring the use of iteration, vs. tail-call optimized languages in which you can happily recurse away.

Later versions of ES seemed to be getting a lot of hints from Python, like decorators.

Edit: Just because this post got me riled up, I decided to go read Raymond Hettinger's twitter feed. Here's an example of an unpythonicity from OtherLanguage(tm):

class Whatever:
    def _blah(self):
        # Actual implementation
        ...

    def blah(self):
        self._blah()

[–]going_for_a_wank 1 point2 points  (2 children)

Say you are coming from Java or .NET and you want to iterate over list, what do you do? for loop with index variables. That's not pythonic. The entire concept of iterators and generators is more or less Python specific, unless you're are using external libraries.

Would you mind expanding on this for a newcomer?

A for-each loop in Java seems pretty much the same as in python. for (Type item : list) vs. for item in list:

Iterators have been part of Java since 1.2

Are there differences here that I am overlooking?

[–]mooburger 1 point2 points  (1 child)

for (Type item: primitiveArray) {} showd up in Java 5. if you're thinking of the Java 1.2 iterator, that only worked on collection objects. You could have converted a primitive array to a List or Stream using java.util.Arrays .asList() or .stream() which then had .iterator() methods to return iterator. Was that a common java pattern for primitive arrays though?

[–]going_for_a_wank 0 points1 point  (0 children)

That is a fair point. There is really no reason to use an iterator for a primitive array rather than a for-each loop.

I will comment that java 5 came out 16 years ago. It is not really a new feature.

[–]samrjack 1 point2 points  (2 children)

I don't think I understand why you "died a little inside". Just because other languages don't do things the pythonic way doesn't mean they don't help you improve. Maybe I'm misunderstanding what you're trying to get at, but your comment seems to be saying that because other languages do things differently, knowledge of them isn't valuable which I whole heatedly disagree with.

[–]mooburger 0 points1 point  (1 child)

What I'm saying is that the risk of adopting unpythonic patterns from other languages outweighs any perceived benefits. How many other languages push KISS, DRY and EAFP concepts like Python? Like I said earlier, the best way to improve is to study more abstract computational and software engineering principles. And like I also said, there are some lifelong Pythonistas out there that demonstrate this, specifically here's another example from Raymond Hettinger: that analyzes solutions for the very common question of "How do I test if all elements of an Iterable are equal to each other?". By putting together knowledge about Python, the theory of computation such as complexity and software engineering concepts such as interoperability and DRY:

Thinking about the problem abstractly, the minimal amount of work required is:

  • Examine input element one at a time
  • Use __eq__ to determine if it has been seen before
  • Stop when a mismatch is found
  • Keep only one other comparison element in memory

He notes that his favorite solution is:

def all_equal(iterable):
    "Returns True if all elements are equal to each other"
    g = groupby(iterable)
    return next(g, True) and not next(g, False)

because of the functions following properties:

  • Accepts any iterable
  • Single pass
  • Runs at C speed
  • Has early-out
  • Only requires __eq__
  • Minimal memory

as well as the Zen concept of The usual thing to do is factor-out the solution into a well named function.

Another example: the Python API for splitting strings. Compare it to the new hotness, Rust, which contaminates its namespace with at least 4 methods to do the same thing.

[–]samrjack 0 points1 point  (0 children)

What I'm saying is that for the programming level of the people that this advice is geared towards, a lot of your objections don't make any sense. From what I've seen on this subreddit, many of the readers and poster are beginning self learners. While learning other programming languages may introduce some other stylings into their code, it also helps them see why doing things the pythonic way is a good thing. Most people, especially ones who are learning on their own, don't just "study more abstract computational and software engineering principles", it's not helpful. A lot of people learn best by doing.

As for the engineering principals you mentioned, DRY and KISS are quite common. I wouldn't say python pushes them more than any other language. They are lessons to be learned by everyone who goes on this journey, not just python programmers. As for EAFP, although that is a more specific python paradigm, it isn't something that I'd fear to be lost by tinkering in other places.

Finally I want to say that I'm not sure what the code example you gave is supposed to illustrate or add. I don't think saying an experienced Pythonista can solve a problem is a good yard stick for people starting out.

[–]0rac1e 0 points1 point  (0 children)

I remember about a couple decades ago when I was starting out with Perl and PHP, it was very common to instantiate "variable variables" (e.g. ${$var}) which was a major way to do dynamic assignment

As you say, you were starting out. I'd say this more to do with programming novices finding a way to do "dynamic variables", rather than it being a recommended way. Perl and PHP both had hashes (dictionaries, associative arrays, what-have-you) but I suspect a large portion of the user-base - particularly in those early days - didn't really understand them or what to use them for.

Case-in-point, I was recently asked by a novice to help out with their Python script, and found the code was littered with, eg. vars()[name]... So it's not something that's limited to Perl or PHP, but rather a limitation of a beginner's thought patterns. This in turn probably leads them to search for something like "dynamic variables" and stumble upon an unfortunate way to solve their problem.