
Python Shortcuts for the Python Beginner - mburst
http://maxburstein.com/blog/python-shortcuts-for-the-python-beginner/
======
someone13
Another method that I find isn't used enough: dict.setdefault. Instead of
doing this:

    
    
        if 'key' in d:
            val = d['key']
        else:
            val = d['key'] = 'some default value'
    

You can do this:

    
    
        val = d.setdefault('key', 'some default value')
    

This is super-useful for configuration in frameworks, for example - it's a
one-liner to set a default config value if the user didn't provide one.

~~~
Erwin
I find I use it most in multi-level data structures, not unlike Perl's auto-
vivification system:

    
    
        logins = {}
        for user, date in getLogins():
          logins.setdefault(user, []).append(date)
    

Here you login ends up having one key per "user" with a list of "date".

~~~
thezilch
Probably better done with a defaultdict:

    
    
      from collections import defaultdict
      logins = defaultdict(list)
      for user, date in getLogins():
        logins[user].append(date)

~~~
gbog
if you have a lot of them, plain dict may prove faster.

~~~
thezilch
Not likely. Proof?

I'd agree if you'd said "not a lot of key/values," as the setup could
supersede the subsequent speedups. However, in that case, the difference is
negligible, and we should do what is "pythonic."

~~~
gbog
Yes, I meant a myriad of very small dicts. In this case a plain built-in is
faster.

------
CodeMage
Nice list. I only wish the author warned the readers that using the "get"
method to get an item from the dictionary is not 100% equivalent to using
try/except.

When using the method, the default value argument will always be evaluated,
regardless of whether the dictionary key exists. If the expression that
produces the default value is an expensive one or has side effects, the
programmer might want to use the try/except variant instead.

------
shoo
Nice tips. One nitpick: the "inline if statement" is handy because it works as
an expression, not just as a statement.

A few more useful things:

frozenset: immutable set values. these can be hashed, so you can use them as
keys in dicts or put them in sets.

poor-man's transpose via zip:

    
    
      >>> x = [('a', 'b'), ('c', 'd')]
      >>> zip(*x)
      [('a', 'c'), ('b', 'd')]
    

slices can be constructed with the "slice" function and passed around as
values:

    
    
      >>> f = lambda x, s : x[s]
      >>> first3 = slice(3)
      >>> last3 = slice(-3, None)
      >>> rev = slice(None, None, -1)
      >>> f('hello', first3)
      'hel'
      >>> f('hello', last3)
      'llo'
      >>> f('hello', rev)
      'olleh'

------
shadowmatter
Good list. My only thoughts:

Prefer itertools.izip instead of zip to avoid materializing a new list.

Appending the comma operator to the print statement suppresses the newline
character and appends a space instead, which is how print 1, "world" works.

The only tip I'd add is using mapping keys in string formatting operations:

    
    
        >>> d = {'cow': 'moo'}
        >>> print 'the cow says %(cow)s' % d
        the cow says moo

~~~
buster
For python beginners i would not mention the print statement. It won't work
for python 3.x.

So, beginners: Please use print() instead of print, to save you some hazzle
when using python3 :)

~~~
ch0wn
Without `from __future__ import print_function`, print doesn't work the same
way in Py2k, though.

~~~
mahmoudhossam
In 2.7, it does.

~~~
jau
In 2.6.6 also works.

~~~
ch0wn
If you use print() in py2k, you're still using the print statement and group
the argument in parentheses. It falls apart, if you try to use more than one
argument, because it's interpreted as a tuple then.

Python3:

    
    
        >>> print("hello", "world")
        hello world
    

Python2:

    
    
        >>> print("hello", "world")
        ('hello', 'world')

------
cnlwsu
I actually would prefer people on my team NOT use these shortcuts. For
example:

    
    
      numbers = [1, 2, 3, 4, 5, 6]
      even = []
      for number in numbers:
          if number % 2 == 0:
              even.append(number)
    

is much easier to read and maintain imho then

    
    
      numbers = [1, 2, 3, 4, 5, 6]
      even = [number for number in numbers if number % 2 == 0]
    

Also:

    
    
      for x in range(1,101):print"Fizz"[x%3*4:]+"Buzz"[x%5*4:]or x
    

is a piece of code I never want someone else to write that I may someday have
to maintain. Write it out the long way and make your teams lives easier.

~~~
thezilch
While it's OK for you to enforce not using trivial list-comprehensions on your
team, I think you'll find the majority of Python's community disagreeing. Your
example is really tame as far as comprehensions are concerned, and "beginners"
are going to need these basics to comprehend more advanced patterns.

~~~
brown9-2
It's especially tame given the friendly variable name chosen.

------
verroq
Slicing a list is not the same as taking subsets, the examples he provides are
also misleading in this context.

------
gamegoblin
Great post! For those who know Python, this may be common knowledge, but for
the uninitiated, this is a great showcase of some simple ways that Python
makes coding more intuitive and enjoyable.

You might also consider mentioning both dictionary and set comprehensions
along with list comprehensions, as they are the exact same concept, yet even a
lot of intermediate Python programmers don't know about them!

~~~
Luyt
Except the silly 'False = True' at the end. How's that useful?

~~~
gamegoblin
I think it's just demonstrating how its possible to redefine even Python
keywords.

------
venomsnake
The last one is terrible ... I have seen

#define TRUE 0 #define FALSE 1

back in the day.

Too bad there was no source control in the company then, so I could not find
out who was responsible for that travesty and "talk calmly" some sense into
them.

~~~
mappu
Processes (and a common design for c functions) return zero on success and an
error code otherwise. Although it might be unexpected (and certainly breaks
flow constructs), it's probably not so bad with some context.

Worse, though, Windows defines TRUE and FALSE for you somewhere in windef.h -
so you would have to be careful about where your code was included..

------
bsaul
Shouldn't "the last 3" be [-3:] instead of [3:] ? Inyour case it gives the
correct result, but that's because your list has 6 elements i think. ( note :
typing on my phone so i can't verify).

------
saurabh
Don't forget itertools.product

[http://stackoverflow.com/questions/13885234/python-nested-
lo...](http://stackoverflow.com/questions/13885234/python-nested-looping-
idiom)

------
chmike
Could it be possible to explain what does

    
    
        Print "Fizz" [x%3*4::]
    

Since range is going from 0 to 101 I have the impression the result won't
match the directive.

~~~
lifeisstillgood
"fizz" is a string - treated as a list in python

"fizz"[0] is the zeroth character in the list / string

Note "fizz"[:] will output all chars in the string (implicitly it's [0:] -
from zeroth string to end

X % 3 is x modulo 3, producing 0 only if x is divisible by three - so we want
to print fizz here. 4 is the number of chars in both fizz and buzz - so the
meat is

"fizz"[x%3*4:] is "fizz"[0:] if x%3 is 0 - when we want tp print fizz,
otherwise it's [somevaluegreaterthan4: to the end of the list (ie nothing).
The extra : stops index error

~~~
chmike
Now I understand it. I wasn't aware one could append a subscript operator
after a litteral string. I also didn't know of the second : role. Thank you.

But what do you get if x is 0 ? As I now uneerstand it, you would get
"fizzbuzz". Shouldn't the list start at value 1 ? So shouldn't the range be
(1, 101) instead of (101) ?

~~~
mburst
You're correct. That was my mistake. Here's the updated version:

for x in range(1,101):print"Fizz"[x%3 _4:]+"Buzz"[x%5_ 4:]or x

I basically just removed the extra colons and added 1, to the range so that it
starts at 1. lifeisstillgood was spot on with the reasoning that this works.

------
gingerlime
nice list, agree with the other comments that the Fizzbuzz example is cool,
but can be confusing to work out what it does, especially since this post is
aimed at beginners.

I would also mention `getattr` similarly to `get`.

------
Scaevolus
It's confusing that output is on the >>> lines while input is not -- backwards
from the REPL.

More things to consider: dict.iteritems, collections.defaultdict,
enumerate(seq, 1)

------
sadmysqluser
Somethings's up with your site. All I see are black boxes where your examples
should be: <http://imgur.com/N8vdzGX>

~~~
Wicher
You need to allow some JS from other domains for it to work.

------
daGrevis
Expression `False = True` reminds me of
<http://stackoverflow.com/a/771974/458610>.

------
__sb__
Are inline if statements considered good form? I rarely see them in use and
I've heard people complain about them before.

------
nu2ycombinator
Very good list except the fizzbuzz example. It solves the problem but not easy
to read, which is not python way.

------
klapinat0r
Also good read for seasoned pythonistas, nice work, mburst

------
fijal
you should always check the length of lists before zip, otherwise you end up
with surprises (try running zip with unequal lengths)

------
chromejs10
I didn't know about some of these. Nice!

------
Hyrum_Graff
Sharing this with my AS Computer Science students. Very clear explanations.

~~~
d0mine
The article requires some corrections if presented to beginners.

`something` should be written as repr(something). `` (backticks) are gone in
Python 3.

if 0 < x > 1: is syntactically correct but it should be written as: if x > 1\.
The combining syntax could be used for the same direction e.g., if -1 < x < 1.

Code golf is not the strong side of Python and it is not the point of
FizzBuzz. Code golf might demonstrate language features but it doesn't provide
the correct context for their usage i.e., code golf doesn't show to a beginner
how something should be used correctly.

True/False are keywords Python 3 (you can't assign to them).

