Live data from Hacker News

Python Best Practice Patterns

stevenloria.com

81–90 of 97 posts

Re: Python Best Practice Patterns

#81
post #78

Earlier quoted context omitted.

As yet another change, PEP8 recommends placing comparison operators (and dots, when method chaining) at the beginning of each line to make things a little clearer. def is_file_for(is_nagyker, type): return ((type == KIS_ES_NAGYKER) or (type == KISKER and not is_nagyker) or (type == NAGYKER and is_nagyker))

See, I don't find that clearer; quite the reverse. With trailing 'or' the type variable is nicely lined up, and the pattern matching that is going on is a lot clearer to my eye. With things misaligned, I have to much more carefully parse the text to see what is going on. I sometimes even do something like this (probably overkill in this example, but my aim is to illustrate a concept, not to bicker about the best expr…

    def is_file_for(is_nagyker, type):
         return (   (type == KIS_ES_NAGYKER)
                 or (type == KISKER and not is_nagyker)
                 or (type == NAGYKER and is_nagyker))

Re: Python Best Practice Patterns

#83
post #78

Earlier quoted context omitted.

As yet another change, PEP8 recommends placing comparison operators (and dots, when method chaining) at the beginning of each line to make things a little clearer. def is_file_for(is_nagyker, type): return ((type == KIS_ES_NAGYKER) or (type == KISKER and not is_nagyker) or (type == NAGYKER and is_nagyker))

See, I don't find that clearer; quite the reverse. With trailing 'or' the type variable is nicely lined up, and the pattern matching that is going on is a lot clearer to my eye. With things misaligned, I have to much more carefully parse the text to see what is going on. I sometimes even do something like this (probably overkill in this example, but my aim is to illustrate a concept, not to bicker about the best expr…

Yours is more aesthetically pleasing, but being able to see the "or" quickly helps one understand the nature of the full conditional at first glance.

The other reply to you seems to be the best of both worlds.

Re: Python Best Practice Patterns

#84
post #78

Earlier quoted context omitted.

See, I don't find that clearer; quite the reverse. With trailing 'or' the type variable is nicely lined up, and the pattern matching that is going on is a lot clearer to my eye. With things misaligned, I have to much more carefully parse the text to see what is going on. I sometimes even do something like this (probably overkill in this example, but my aim is to illustrate a concept, not to bicker about the best expr…

def is_file_for(is_nagyker, type): return ( (type == KIS_ES_NAGYKER) or (type == KISKER and not is_nagyker) or (type == NAGYKER and is_nagyker))

Or maybe

    def is_file_for(is_nagyker, type):
         return (
                    (type == KIS_ES_NAGYKER)
                 or (type == KISKER and not is_nagyker)
                 or (type == NAGYKER and is_nagyker)
                )

Re: Python Best Practice Patterns

#85
post #9

Several of those patterns are incomplete or frowned upon: * if a method does not use the object's state (no `self` usage) make it a `class-` or `staticmethod`. * Some magic methods are presented. There's more to them[0]. * one should not write `class MyClass:` but `class MyClass(object):` (new style class[1]) * the last one (`return None`) make me very dubious * Cascading methods: that's a big no . The idiom is that…

Showed this to a senior dev at work and he pointed out another (subtle) error for each in enumerate(items): if each.match(self): # This fails because enumerate yields an (index, value) tuple. # Match isn't a function defined on tuples.

a pretty basic error :(

Re: Python Best Practice Patterns

#86

Having gone through a couple thousand lines of Javascript that adhered to the "keep methods small", I call bollocks on that. Make methods as big as they need to be. function doFooOnList(l) { for (var i=0; i gets old, very quickly. After designing and building code for 20+ years, I can comfortably say that there are no arbitrary rules of software design, and some of the worst code I've seen has been a result of follow…

I'd say methods should be small enough so that their intent is clear. Usually it means that methods should have exactly one responsibility, otherwise they seem bloated.

Re: Python Best Practice Patterns

#87
post #9

Several of those patterns are incomplete or frowned upon: * if a method does not use the object's state (no `self` usage) make it a `class-` or `staticmethod`. * Some magic methods are presented. There's more to them[0]. * one should not write `class MyClass:` but `class MyClass(object):` (new style class[1]) * the last one (`return None`) make me very dubious * Cascading methods: that's a big no . The idiom is that…

Showed this to a senior dev at work and he pointed out another (subtle) error for each in enumerate(items): if each.match(self): # This fails because enumerate yields an (index, value) tuple. # Match isn't a function defined on tuples.

Do you have to show the code to someone before your allowed to run it? Can't see how you wouldn't have spotted this yourself

Re: Python Best Practice Patterns

#88

Having gone through a couple thousand lines of Javascript that adhered to the "keep methods small", I call bollocks on that. Make methods as big as they need to be. function doFooOnList(l) { for (var i=0; i gets old, very quickly. After designing and building code for 20+ years, I can comfortably say that there are no arbitrary rules of software design, and some of the worst code I've seen has been a result of follow…

> Make methods as big as they need to be. Correct, and if you do that, methods will invariably end up small. What you cite above is small no matter how you write it, so that's not the point of the advice to keep methods small. Methods pretty much never need to be long; they're long because they're poorly written code. Well written code tends towards small methods.

Correct, and if you do that, methods will invariably end up small.

If you'd said "usually", I'd have agreed with you, but "invariably" is far too strong. Sometimes the logic you need to implement is fundamentally complicated, and so the code you write to implement it must inevitably be at least that complicated. If that means writing a 100 line function, but the function really is doing one job, at one level of abstraction, in a cohesive way, then so be it.

Re: Python Best Practice Patterns

#89
post #9

Several of those patterns are incomplete or frowned upon: * if a method does not use the object's state (no `self` usage) make it a `class-` or `staticmethod`. * Some magic methods are presented. There's more to them[0]. * one should not write `class MyClass:` but `class MyClass(object):` (new style class[1]) * the last one (`return None`) make me very dubious * Cascading methods: that's a big no . The idiom is that…

> Cascading methods: that's a big no. The idiom is that if a method may change the state of the object then it should return None (eg `set.add`)

So methods that mutate state, and don't return None are un-Pythonic?

What about this example:

  a = [1, 2, 3]
  b = a.pop()
pop() mutates the state of a and returns a value that is not None. Is the Python code language itself un-Pythonic?

Re: Python Best Practice Patterns

#90

Earlier quoted context omitted.

> * the last one (`return None`) make me very dubious I'm curious, as someone who uses this pattern quite a bit, how would you improve on this?

Just speculating here, but a func that just ends without returning, effectively returns None, so that idiom may be considered redundant. IMHO, it's often worth the additional clarity to be redundant in this way.

Yes, but the "Pythonic" way to do things is that "explicit is better than implicit," so I'm not sure what the original poster considers wrong with `return None`.
Post reply on HN