

A Hodgepodge of Python - donmcc
http://blog.adku.com/2011/09/hodgepodge-of-python.html

======
lysium
Didn't know the timeit module. However, the presented usage to time list
reversing is ill: The timing is dominated by the list creation, which should
go into setup. Then I'll get:

    
    
        $ python -mtimeit -s'l=range(1000)' 'l[::-1]'      
        100000 loops, best of 3: 3.05 usec per loop
        $ python -mtimeit -s'l=range(1000)' 'l.reverse()'  
        1000000 loops, best of 3: 0.535 usec per loop
        $ python -mtimeit -s'l=range(1000)' 'a=reversed(l)' 
        1000000 loops, best of 3: 0.39 usec per loop
    

So, instead of reversing the list in place, creating a new, reversed list
seems to be faster.

~~~
Sharlin

      >>> reversed([])
      <listreverseiterator object at 0xb73ff7cc>
    

reversed() does not create a new list, it just returns a reverse-order view of
the same list. Of course, often this is exactly what is needed.

~~~
akx
And more often than not `xrange` is what one needs, not `range`. (Not relevant
with Py3k though, but everyone is still in 2.x-verse.)

~~~
lysium

        >>> xrange(13)[::-1]
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: sequence index must be integer, not 'slice'

~~~
akx

      >>> list(range(13)[::-1]) == list(xrange(12, -1, -1))
      True

------
balbeit
I always love learning little tidbits about Python like these. Thanks!

Another I found quite useful: instead of collections.defaultdict, you can use
the dict's get() method to set a default value if the key doesn't exist. get()
takes the key and a default value, and if the key doesn't exist it creates one
with the default value provided.

    
    
      a = {}
      a['foo'] = a.get('foo',0) + 1
      # a = {'foo':1}
      a['foo'] = a.get('foo',0) + 1
      # a = {'foo':2}
    

It can be very useful for incrementing keys in a dict, even if they did not
exist previously.

~~~
randlet
You can use the Counter class from the collections module[1] for that as well.

    
    
      >>> from collections import Counter
      >>> c = Counter()
      >>> c['foo']
      0
      >>> c['bar'] +=1
      >>> c['bar']
      1
      >>> 
    

[1]
[http://docs.python.org/dev/library/collections.html#collecti...](http://docs.python.org/dev/library/collections.html#collections.Counter)

------
BrandonM
I use defaultdict a lot. It's useful not only for counters, but also for sets,
lists, dicts, and even other defaultdicts. It usually results in very succinct
code compared to alternatives:

    
    
      occurrences = defaultdict(int)
      digraphs = defaultdict(lambda: defaultdict(int))
      
      prev_ch = None
      for ch in long_text:
        occurrences[ch] += 1
        if prev_ch is not None:
          digraphs[prev_ch][ch] += 1
        prev_ch = ch
    
      print "Occurrences:"
      for ch, count in sorted(occurrences.iteritems()):
        print "  %s: %i" % (ch, count)
    
      print "Digraph occurences:"
      for ch1, counts in sorted(digraphs):
        for ch2, count in sorted(counts):
          print "  %s%s: %i" % (ch1, ch2, count)
    

(I'm aware that digraphs could be done as a single flat dict; it's just a
trivial example to show defaultdict nesting.)

------
notaddicted
I'm still on the fence as to whether this is _acceptably ugly_ or
_unacceptably ugly_ , but it does make use of a python feature:

    
    
      >>> 
      >>> class PrefixStr:
      ...   def __init__(self, prefix):
      ...     self.prefix = prefix
      ...   def __getattr__(self, s):
      ...     return self.prefix+s
      ... 
      >>> 
      >>> q = PrefixStr('xyz_')
      >>> 
      >>> { q.height:11, q.width:7, q.depth:3 }
      {'xyz_width': 7, 'xyz_depth': 3, 'xyz_height': 11}
      >>>

~~~
Estragon
The main question is whether it increases the clarity and flexibility of the
code. I can't think of any contexts where it would, but I wouldn't rule it
out.

------
gbog
The more I use Python the more I like it. It allows a lot of the early
refactorings needed for a proof of concept prototype. Playing with it feels
like playing with a well lubrificated rubix cube, it rotates well in all
directions, allowing quick changes in the code's structure. I can't tell
exactly why but I think the use of "self" in object methods, while a bit weird
in the begining, is one of the best part. Eg morphing a helper function into a
method is just a matter of one search and replace.

------
ashrust
This is the stuff that brings me back to hacker news everyday. So helpful.

------
mumrah
_izip_ is the super useful generator counterpart of _zip_

Also, 2.7 introduced a couple of cool things in collections: _OrderedDict_ and
_Counter_

------
skrebbel
> _In my mind, dynamic typing = bugs, interpreted language = slow. Ahhhhh!_

He explained why he changed his mind on performance, but not whether or not
"dynamic typing = bugs". This would've been interesting to read about from a
recent convert.

------
grantjgordon
Thanks for posting these tips!

