Earlier quoted context omitted.
The l (lowercase L) and the 1 (one) look really similar. Could that be the cause of some confusion? Of course, the function name helps, but most developers have learned not to trust function names to be an accurate description of what the function does, especially in tricky interview questions. Still, I'd change this to something like: def append_five(l=[]): l.append(5) return l It tests the same thing (knowledge of…
I'm not a Python expert, but iirc from various blog posts the "l" variable does not get reset between function calls which will cause undesired behavior. So calling the function 3 times without argument would produce a list of size 1,2, and 3 with the third call rather than 3 lists of size 1. Can any Python guru's confirm?
Anti-Patterns in Python Programming
61–70 of 242 posts
Re: Anti-Patterns in Python Programming
#62> write a list comprehension (...) code just looks a lot cleaner and what you're doing is clearer. I know how to use list comprehensions, but often avoid using them and use the standard for loops. List comprehensions look nice and clean for small examples, but they can easily get long and become mentally hard to parse. I would rather go for three 30 character lines instead of one 90 character line.
Depends on how you want to program: imperative vs functional. Personally I think list comprehensions are the most beautiful part of Python, though sometimes I use map() when I'm trying to be explicitly functional (I realize it's allegedly slower, etc). Generally I think list comprehensions are cleaner and allow you to write purer functions with fewer mutable variables. I disagree that deeply nested for loops are nece…
However, I think he was referring to if the conditionals/additional modifications needed to build your list get a bit excessive, so you'd have a like... [dostuffto(A) for A in alsodostuffto(LIST) if conditional(A)] (but with more complex operations at each step).
Granted at that point you can argue that you should do just as my example shows and put the "dostuffto" into more encapsulated functions, but sometimes that doesn't seem like the right choice.
Re: Anti-Patterns in Python Programming
#63The more frequent and dangerous pitfalls are, in my humble opinion: - Bare except: statements (that catches everything , even Ctrl-C) - Mutables as default function/method arguments - Wildcard imports!
Agreed on all counts. However I do find myself using mutables as default arguments sometimes because the generated documentation is clearer. For example, this is a real method in one of my projects: def listen(self, address, ssl=False, ssl_args={}): pass I like the way this turns up in the docs because it's immediately clear that ssl_args needs to be a dict. Otherwise I have to describe it in words.
Why not just add @param annotations in your docstrings instead?
Re: Anti-Patterns in Python Programming
#64The more frequent and dangerous pitfalls are, in my humble opinion: - Bare except: statements (that catches everything , even Ctrl-C) - Mutables as default function/method arguments - Wildcard imports!
Agreed on all counts. However I do find myself using mutables as default arguments sometimes because the generated documentation is clearer. For example, this is a real method in one of my projects: def listen(self, address, ssl=False, ssl_args={}): pass I like the way this turns up in the docs because it's immediately clear that ssl_args needs to be a dict. Otherwise I have to describe it in words.
Re: Anti-Patterns in Python Programming
#65Earlier quoted context omitted.
alist = [foo(word) for word in words if word.startswith('a')] alist = map(foo, filter(lambda word: word.startswith('a'), words)) Which reads better?
Map and filter, of course; less syntactical noise, simple function semantics, and plenty of precedent and equivalents in all other languages.
(as it is now, list comprehensions requiring various references to result of a function call evaluate the function each time it's used)
Re: Anti-Patterns in Python Programming
#66Earlier quoted context omitted.
...because it's a list? Tuples were supposed to have a structure (at least that's what all the rest of the world thinks of them), so iterating through combination of apples, cars and languages makes no sense whatsoever. But yes, Python misses entirely the point of tuples, treating them as read-only lists. http://dozzie.jogger.pl/2014/04/11/python-tuples-the-useless...
I'm not sure what you're getting at here, or what you are expecting tuples to be like. They can have as much "structure" as you need--they're just a collection. Lighter-weight, immutable collections have a use case. The code in OP appears to be one where it makes sense. I follow the rule where variables are mutable IFF they need to be mutable.
For the rest of the world, tuples are not immutable lists. They are tuples, i.e. collections of "objects" that could share nothing about their type. Tuples often are not even iterable! (Erlang, Haskell)
The fact that tuples in Python can have as much structure as one wants is derived from dynamic typing, not from the tuples' nature. The same you could say about Python's lists.
This is a really subtle issue. It takes to know more languages to see it clearly.
Re: Anti-Patterns in Python Programming
#67Earlier quoted context omitted.
> Mutables as default function/method arguments It would really make sense to change the semantics of Python to fix this issue.
Change them how, to no longer have functions be first class objects? The behavior of mutable default arguments is clear if you know how Python treats function objects. Any "fix" would handicap the language.
Re: Anti-Patterns in Python Programming
#68Re: Anti-Patterns in Python Programming
#69Earlier quoted context omitted.
Change them how, to no longer have functions be first class objects? The behavior of mutable default arguments is clear if you know how Python treats function objects. Any "fix" would handicap the language.
Can you clarify? def foo(default_arg = []): Why can't that just be shorthand for: def foo(default_arg = ParamNone): if default_arg == ParamNone: default_arg = [] How would that break first class functions?
What breaks is something like:
def foo(default_arg = slow_f()):
pass
Under the shorthand gets turned into: ParamNone = object()
def foo(default_arg = ParamNone):
if default_arg is ParamNone:
default_arg = slow_f()
pass
This is fine, since everyone would know that the shorthand means to not put slow code there. Instead, people will start writing it as: _foo_arg = slow_f()
def foo(default_arg = _foo_arg):
pass
Of course, then what happens with: _foo_arg = slow_f()
def foo(default_arg = _foo_arg):
_foo_arg = 5
? Under expansion it becomes: _foo_arg = slow_f()
def foo(default_arg = ParamNone):
if default_arg is ParamNone:
default_arg = _foo_arg
_foo_arg.add(5)
This violates Python's scoping rules, because _foo_arg is now being used in local scope instead of global scope. Eg: >>> def f(x=None):
... if x is None:
... x = spam
... spam = 3
...
>>> spam = 9
>>>
>>> f()
Traceback (most recent call last):
File "", line 1, in
File "", line 3, in f
UnboundLocalError: local variable 'spam' referenced before assignment
Which means you now need a new scoping rule, just to handle default parameters without making things more confusing.It also turns what was a simple O(1) offset into a precomputed list into a globals() lookup for many cases.
Re: Anti-Patterns in Python Programming
#70> write a list comprehension (...) code just looks a lot cleaner and what you're doing is clearer. I know how to use list comprehensions, but often avoid using them and use the standard for loops. List comprehensions look nice and clean for small examples, but they can easily get long and become mentally hard to parse. I would rather go for three 30 character lines instead of one 90 character line.