Gribouillis 1,391 Programming Explorer Team Colleague

Notice that

from struct import unpack
s = f.read()
data = list(unpack("%dB" % len(s), s))

is much faster to create the data.

Gribouillis 1,391 Programming Explorer Team Colleague

This code is not indented, so it can't run. Notice that the power operator is **, not ^, python is not latex. Also when there is an error, python outputs a long message, starting with the word Traceback (most recent call last). To find the error, you must analyze this message, and if you want people to be able to help you, you should post the code and the traceback.

Gribouillis 1,391 Programming Explorer Team Colleague

Can you explain me shortly how that if statement works?

When a python file foo.py is executed, a variable __name__ is inserted in its namespace. If foo.py is ran as the main script, the value of this variable is the string "__main__". If instead foo.py is imported from another script with import foo, the value of this variable is the module's name "foo". For example

>>> from xml.dom import minidom
>>> minidom.__name__
'xml.dom.minidom'
Gribouillis 1,391 Programming Explorer Team Colleague

In python 3 it would be

>>> exec(open("test.py").read())

instead of execfile.

Gribouillis 1,391 Programming Explorer Team Colleague

See the light with python guru Mark Hammond.

Gribouillis 1,391 Programming Explorer Team Colleague

The difference is that in your first version, the same list object testarr is appended to finarr at line 13. In the end, all the lines in finarr are a single list object containing the values appended at the last iteration.

Gribouillis 1,391 Programming Explorer Team Colleague

This should work

def funcdist(myvar):
    return [[ sum(1 for (a, b) in zip(line_a, line_b) if a != b)
            for line_b in myarr] for line_a in myarr ]

The problem in your snippet, is that a new testarr needs to be created in the hx loop. Replace line 6 by line 3 and discard line 3.

Gribouillis 1,391 Programming Explorer Team Colleague

Yes it is possible:

a, b = zip(*(((item*10),(item*20)) for item in items))

but it gives tuples instead of lists. If you want lists, you can write

a, b = (list(x) for x in zip(*(((item*10),(item*20)) for item in items)))

another way is

a, b = (list(item * x for item in items) for x in (10, 20))

The last one looks better, but it works only if items is a list or a tuple, not any iterable.

Gribouillis 1,391 Programming Explorer Team Colleague

You can go one step further and write

for i in range(3):
   for w,x,y,z in zip(*(v.values for v in (ar[i+1], br[i+1], ar[i], br[i]))):
        val = (sqrt((w.data**2)+(x.data**2)))-(sqrt((y.data**2)+(z.data**2)))
        files[i].write(('%6.20f\n') % (val))

provided you define lists ar and br containing [ar0, ar1, ar2, ar3] etc instead of variables whith numbered names.

Gribouillis 1,391 Programming Explorer Team Colleague

Your class should read

class Environment(object):
    def __init__(self,rowCount,columnCount):
        self.env = [[ None for i in range(columnCount)] for j in range(rowCount) ]       

    def setElement(self, row, column, value = 0):
        self.env[row][column] = value

    def getElement(self, row, column):
        return self.env[row][column]

myenv = Environment(6, 6) # create an instance
myenv.setElement(2, 2)
myenv.setElement(3, 4, 1000)

The __init__() method never returns anything. Its role is to initialize an instance created dynamically when you call Environment().

Gribouillis 1,391 Programming Explorer Team Colleague

This snippet defines a dir() function which extends python's builtin dir() function by adding options to filter the returned sequence of strings by the means of regular expressions. The main use case is live inspection of python objects and modules during an interactive session with the python interpreter.

The idea of such a function is not new. I remember having met similar functions in old modules by well known python gurus, Reddite Caesari quae sunt Caesaris !

Gribouillis 1,391 Programming Explorer Team Colleague

Well, you have

>>> import os
>>> filename = "foo/bar/baz/qux.naps"
>>> name = os.path.basename(filename)
>>> name
'qux.naps'
>>> base, extension = os.path.splitext(name)
>>> base
'qux'
>>> extension
'.naps'

and also

>>> os.path.exists(filename) # check if file exists
False
# or
>>> os.path.isfile(filename) # check if a regular file with that name exists
False
Gribouillis 1,391 Programming Explorer Team Colleague

Line 7 should go before the for loop. When it is executed, scores becomes a new empty list. Also line 10 should be scores[:] = [], otherwise it does nothing.

It is better to write all the function definitions out of the for loop (before the loop). A function definition usually needs to be executed only once.

Gribouillis 1,391 Programming Explorer Team Colleague

One way to use class 1's methods in class 2 is to have a class 2 object aggregate a class 1 instance. It is a standard pattern in OOP, called composition, which is often used as an alternative to inheritance

class Class1(object):
    def method(self):
        print(self)


class Class2(object):
    def __init__(self):
        self.obj1 = Class1()

    def foo(self):
        self.obj1.method()

c2 = Class2()
c2.foo()
Gribouillis 1,391 Programming Explorer Team Colleague

makedirs() fails if the directory already exists. In this case you don't need to create the directory: simply catch the exception

try:
    os.makedirs(mypath)
except OSError:
    # either dir already exists or can't create.
    # we can check
    if not os.path.isdir(mypath):
        # dir doesn't exist, propagate the exception
        raise
# if we're here, the directory exists
Gribouillis 1,391 Programming Explorer Team Colleague

You could add a 'mock section' and still use ConfigParser

# tested with python 2.7.2
import ConfigParser
from functools import partial
from itertools import chain

class Helper:
    def __init__(self, section, file):
        self.readline = partial(next, chain(("[{0}]\n".format(section),), file, ("",)))

config = ConfigParser.RawConfigParser(allow_no_value=True)
with open("essconfig.cfg") as ifh:
    config.readfp(Helper("Foo", ifh))
print(config.get("Foo", "old_passwords"))

The config file was

user = mysql
pid-file = /var/run/mysqld/mysqld.pid
skip-external-locking
old_passwords = 1
skip-bdb
skip-innodb
Gribouillis 1,391 Programming Explorer Team Colleague

The third item in os.walk is a list of filenames. Otherwise, the md5 of a file refers to the content of the file, not to the filename. Run your code before posting issues!

Gribouillis 1,391 Programming Explorer Team Colleague

According to wikipedia, ironpython is entirely written in C#.

TrustyTony commented: Thanks for checking it out! +12
Gribouillis 1,391 Programming Explorer Team Colleague

Yes, you can browse the code online

Gribouillis 1,391 Programming Explorer Team Colleague

The default implementation is called C python. It is the main flavor of python, compiled from C. I would recommend C python unless you have specific needs in your apps.

In practice, code written for IronPython will access microsoft .net classes, code written for Jython will access java classes, code for Stackless python will use microthreads, so it all depends on which libraries your python code is using. In the same way, some libraries are available in C python and not in the other pythons.

General python code using standard libraries should run in all versions (however, read the docs).

Gribouillis 1,391 Programming Explorer Team Colleague

Your triangle condition is false as (-1, 4, 2) would be a triangle. A correct condition is simply abs(b-c) < a < b+c. I would check 'triangulity' at object creation and raise ValueError if it fails

#from math import*

class Triangle(object):
    """Checks if given sides can make a Triangle then shows the Angles."""
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
        self._check_triangle()

    def _check_triangle(self):
        """Checks if given sides can make a Triangle"""
        if not(abs(self.b - self.c) < self.a < self.b + self.c):
            raise ValueError("Not a triangle")

    def get_angles(self):
        """Calculates the Angles based on the Cosine Rule."""
        A = degrees(acos((self.b**2+self.c**2-self.a**2)/float(2*self.b*self.c)))
        B = degrees(acos((self.a**2+self.c**2-self.b**2)/float(2*self.a*self.c)))
        C = 180 - (self.A+self.B)
        return A, B, C

Also with a method name like get_angles(), one expects that the method computes and returns a tuple of angles, and not that it prints something. Usable methods don't print anything, they return values.

M.S. commented: Thanks for this:) +4
Gribouillis 1,391 Programming Explorer Team Colleague

This snippet allows one to implement an equivalent of a __getattr__() function in a python module. The module can then define its own way to lazily import abitrary symbols. For example the module can contain infinitely many names or load values from other modules on demand.

There are many implementations of lazy imports in python, this is a simple one which doesn't interfere with python's import mechanism.

Gribouillis 1,391 Programming Explorer Team Colleague

try

print('Player %s:' % x)
Gribouillis 1,391 Programming Explorer Team Colleague

BeautifulSoup 4.1.3 is out since August 20, 2012. It is compatible with python 2.6+ and python 3 !

Gribouillis 1,391 Programming Explorer Team Colleague

It seems that you can change the cmd console encoding to utf8 with the command chcp 65001. See here and here.

Gribouillis 1,391 Programming Explorer Team Colleague

Here is an implementation with the WeakValueDictionary. It has the same result as the __del__ method, but, as far as I know, there is no garbage collection issue.

#!/usr/bin/python3
# -*-coding: utf8-*-

from functools import partial
import weakref

def del_robot(name, wref):
    '''A robot is dying'''
    print("{0} is being destroyed!".format(name))
    population = len(Robot._living_instances)
    if population:
        print("There are still {0:d} robots working".format(population))
    else:
        print("{0} was the last one".format(name))

class Robot:
    '''Represents a robot, with a name.'''

    #A class variable, counting the number of Robot
    _living_instances = weakref.WeakValueDictionary()

    def __init__(self, name):
        '''Initializes the data'''
        self.name = name
        self._wref = weakref.ref(self, partial(del_robot, self.name))
        self._living_instances[id(self)] = self
        print("(Initializing {0})".format(self.name))

    def sayHi(self):
        '''Greeting by the robot

        yeah, they can do that.'''
        print("Greetings, my masters call me {0}".format(self.name))

    @classmethod
    def howMany(cls):
        '''Prints the current population'''
        print("We have {0:d} Robots (some of them may be dead already, but it is unlikely).".format(
            len(cls._living_instances)))

    @classmethod
    def reliable_count(cls):
        return len(cls._living_instances.values())

droid1 = Robot("r2-d2")
droid2 = Robot("c-3po")
droid3 = Robot("SAL")

droid1.sayHi()
droid2.sayHi()
droid3.sayHi()

del droid1
Robot.howMany()

"""My output -->
(Initializing r2-d2)
(Initializing c-3po)
(Initializing SAL)
Greetings, my masters call me r2-d2
Greetings, my masters call me c-3po
Greetings, my masters call me SAL
r2-d2 is being destroyed!
There are still 2 robots working
We have 2 Robots (some of them may be dead already, but it is unlikely).
c-3po is being destroyed!
There are still 1 robots working
SAL is being destroyed!
SAL was the last one
"""
Gribouillis 1,391 Programming Explorer Team Colleague

Yes, but since his robots don't contain references to each other, that can't happen here.

I agree with that, but may be next year he will want to add a list to the robots instances, which contains Foo instances which in turn refer to other Robots, and here is the memory leak. It's almost impossible to ensure that there are no cyclic references in a python program :) . My rule is safer, one can live without del methods.

Gribouillis 1,391 Programming Explorer Team Colleague

I couldn't find the error, but I changed the code a little bit, this one works

#!/usr/bin/env python
# -*-coding: utf8-*-

import math

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

def series_term(k):
    a=factorial(4*k)
    b=(1103+26390*k)
    c=factorial(k)
    d=c**4
    e=396**(4*k)
    return float(a*b)/(d*e)

def estimatePi():
    k=0
    final=0
    while True:
        print "k: ", k
        term = series_term(k)
        final += term
        if term < 1.0e-15:
            break
        else:
            k += 1
    f=2*math.sqrt(2)/9801 # compute this only once
    pi = 1.0/(final * f)
    return pi

if __name__=="__main__":
    print(repr(estimatePi()))

""" my output -->
k:  0
k:  1
k:  2
k:  3
3.141592653589793
"""

I had to explicitely use float() to avoid an integer division issue which led to the same result as yours. Notice that your result is obtained with k=0 only.

Edit: rewrite your factorial function in a non recursive way. It's much better.

Lardmeister commented: great +10
Gribouillis 1,391 Programming Explorer Team Colleague

What is the type of the variable config_file ?

3e0jUn commented: A string. +1
Gribouillis 1,391 Programming Explorer Team Colleague

Add a few print statements to see what's going on

def tictactoe(moves):
    for r in range(len(moves)):
        for c in range(len(moves[r])):
            print("(r, c) =", (r, c))
            if moves[0][c]==moves[1][c]==moves[2][c]:
                a="'%s' wins (%s)."%((moves[0][c]),'vertical')
            elif moves[r][0]==moves[r][1]==moves[r][2]:
                a="'%s' wins (%s)."%((moves[r][0]),'horizontal')
            elif moves[0][0]==moves[1][1]==moves[2][2]:
                a="'%s' wins (%s)."%((moves[0][0]),'diagonal')
            elif moves[0][2]==moves[1][1]==moves[2][0]:
                a="'%s' wins (%s)."%((moves[0][2]),'diagonal')
            else:
                a='Draw.'
            print("currently, a =", repr(a))
    print(a)
fasna commented: thank you +0
Gribouillis 1,391 Programming Explorer Team Colleague

You can get a list of indexes for which there is more than 1 item

>>> available_troops = [[1, 0, 1], [2, 0, 1], [3, 0, 1], [4, 0, 1], [5, 0, 1], [6, 0, 1], [7, 0, 1], [8, 0, 1], [9, 0, 1], [10, 0, 1], [11, 0, 1], [12, 0, 1], [13, 0, 1], [14, 0, 1], [15, 4431, 1], [16, 0, 1], [17, 0, 1]]
>>> 
>>> indexes = [i for (i, triple) in enumerate(available_troops) if triple[1] > 1]
>>> indexes
[14]

so you know that available_troops[14][1] > 1.

>>> print available_troops[indexes[0]][1]
4431
valorien commented: Beautiful Pythonic code +0
Gribouillis 1,391 Programming Explorer Team Colleague

It doesn't work, look at this

>>> eval("eval('__imp' + 'ort__(' + '\\'o' + 's\\')').unlink('foo')")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
OSError: [Errno 2] No such file or directory: 'foo'

python is too talented for symbolic manipulations.

Gribouillis 1,391 Programming Explorer Team Colleague

This project needs more than a badly put together code snippet. Learn about xmlrpclib first, by running the examples in the documentation. Your program needs a thread to start the xmlrpc server to receive the other side's messages and a user interface to forward your messages to xmlrpc calls and to display both sides messages. This interface could a simple terminal interface to start with.

Gribouillis 1,391 Programming Explorer Team Colleague

A simple way to communicate is to use the standard module xmlrpc. This is very easy to use on your local network.

Gribouillis 1,391 Programming Explorer Team Colleague

What is cms detector?

It seems that cms detector means Compact Muon Solenoid.

Gribouillis 1,391 Programming Explorer Team Colleague

Vegaseat wrote this great example 7 years ago, and it still works out of the (list) box !

Gribouillis 1,391 Programming Explorer Team Colleague

There is also numpy.loadtxt() to read the file

    import numpy
    with open("numfile.txt") as ifh:
        arr = numpy.loadtxt(ifh, usecols = (2, 3), dtype=float, delimiter=" , ", skiprows = 2)
    print arr

""" my output -->
[[  2.00000000e+00  -1.00000000e-04]
 [  2.00000000e+00   1.69973300e-01]
 [  2.00000000e+00   3.36706700e-01]
 [  2.00000000e+00   5.00040000e-01]]
"""

Use matplotlib to plot the curves.

ceck30s commented: Thank you for letting me know about numpy.txt(). It works! +0
Gribouillis 1,391 Programming Explorer Team Colleague

I received the files, but I can't reproduce the same issue. Everything works fine in this code

import pickle
import zipfile
from xml.etree.ElementTree import ElementTree

def load(zipname):
    with zipfile.ZipFile(zipname, 'r') as myzip:
        return pickle.loads(myzip.read("elt"))

zipnames = "PickledElement160.zip PickledElement161.zip".split()
a, b = (load(zipname) for zipname in zipnames)

print(a, b)
print(type(a.attrib), type(b.attrib))
print(a.attrib)
print(a.attrib['{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name'])
print(b.attrib)
print(b.attrib['{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name'])

""" my output -->
<Element '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p' at 0x7fddfb8be490> <Element '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}span' at 0x7fddfb8be0d0>
<class 'dict'> <class 'dict'>
{'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'P5'}
P5
{'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'T1'}
T1
"""

I'm using python 3.2.1. What is your output for the same code ?

Gribouillis 1,391 Programming Explorer Team Colleague

Perhaps you could upload the element using this function

import pickle
import zipfile

def save(obj):
    s = pickle.dumps(obj, 0)
    with zipfile.ZipFile('spam.zip', 'w') as myzip:
        myzip.writestr("elt", s)

save(element)

then attach the file spam.zip to a post, so that we can read it and study the element. You must also tell us which version of python you are using ...

We could read the element with

def load():
    with zipfile.ZipFile('spam.zip', 'r') as myzip:
        return pickle.loads(myzip.read("elt"))
element = load()
Gribouillis 1,391 Programming Explorer Team Colleague

You can change to another port, perhaps avoiding well known ports 0 - 1023. For example, port 23 is normally used for a telnet service. I don't think there is a limit on the data files (either the number of files or their size) but if you have a huge file, read it by chunks !

Gribouillis 1,391 Programming Explorer Team Colleague

This will work

from easygui import passwordbox
password = passwordbox("What is your password ?")

You must install easygui first (pip install easygui in a terminal).

TrustyTony commented: Don't reinvent the wheel hacker ;-) +12
Gribouillis 1,391 Programming Explorer Team Colleague

In linux, you can clear the screen with

def clear():
  print("\x1B[2J")

clear()

This uses the ANSI escape sequences which work in a linux terminal. This may work in windows too if you import module colorama which implements ansi sequences for all OSes

from colorama import init
init()

it will also allow you to print in colors.

You can also browse colorama's source code to see how it uses module ctypes and windows libraries to clear the screen. The drawback of clearing the screen is that it usually doesn't work in the various python IDE's. Ideally, your code should check if it is running in a terminal.

By the way, the statement SystemExit() does nothing significant. You probably meant raise SystemExit.

Gribouillis 1,391 Programming Explorer Team Colleague

In python 2, there is no difference between

print "foo"
print ("foo")

because print is a statement and the expression ("foo") has the same value as the expression "foo". On the other hand the statements

print "foo", "bar"
print ("foo", "bar")

are not equivalent because ("foo", "bar") is a single expression which value is a tuple of length two, so the first statement prints two strings while the second statement prints a tuple containing two strings.
In python 3, print() is a function, so print "foo" and print "foo", "bar" are syntax errors. The parenthesis in print ("foo", "bar") are ordinary function call parenthesis, they don't mean build a tuple and two strings are printed. To print the same tuple in python 3, one must write print(("foo", "bar")).

Gribouillis 1,391 Programming Explorer Team Colleague

Adding a call to select.select() with a timeout works for me

import select
import sys
import termios

class TimeoutError(Exception):
    pass

TERMIOS = termios
def getkey():
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO
    new[6][TERMIOS.VMIN] = 1
    new[6][TERMIOS.VTIME] = 0
    termios.tcsetattr(fd, TERMIOS.TCSANOW, new)
    c = ''
    try:
        r, w, x = select.select([fd], [], [], 2.0)
        if r:
           c = repr(sys.stdin.read(1))
        else:
            raise TimeoutError
    finally:
        termios.tcsetattr(fd, TERMIOS.TCSAFLUSH, old)
    return c

if __name__ == "__main__":
    print getkey()

All this code is linux only! Please, indent python code with 4 spaces instead of 3, as most people do (read PEP 8).

Gribouillis 1,391 Programming Explorer Team Colleague

It seems to me that

MyList = custom_list_type("Mylist", (check_int, check_int, check_str))

is not more difficult to write than

Mylist = List(Int,Int,Str)

This feature may be part of the enthought tool suite, but it's not included in python. The pythonic way of thinking is to avoid type checking.

snippsat commented: The pythonic way of thinking is to avoid type checking. +1 +9
Gribouillis 1,391 Programming Explorer Team Colleague

Well, here is how you could use the abstract base classes in module collections to implement such custom types. Here a list type which item types are given. Notice that this class uses 'converters' instead of types, which means that complex behavior can be implemented whith regards to the conditions on items, for example one could ask that an item be a floating number between 0 and 1, etc

#!/usr/bin/env python
# -*-coding: utf8-*-
# Title: customtp.py
# Author: Gribouillis
# Created: 2012-07-06 09:17:00.649267 (isoformat date)
# License: Public Domain
# Use this code freely.

import collections

def custom_list_type(name, converters):

    class tp(collections.MutableSequence):

        def __init__(self, iterable):
            L = list(iterable)
            if len(L) != len(self.converters):
                raise TypeError(("Invalid number of items", len(L)))
            self.data = list(c(x) for c, x in zip(self.converters, L))

        # sized methods
        def __len__(self):
            return len(self.data)

        # iterable methods
        def __iter__(self):
            return iter(self.data)

        # container methods
        def __contains__(self, value):
            return value in self.data

        # sequence methods
        def __getitem__(self, index):
            return self.data[index]

        # mutable sequence methods
        def __setitem__(self, index, value):
            self.data[index] = self.converters[index](value)
        def __delitem__(self, index):
            raise TypeError("Can not remove item")
        def insert(self, index, item):
            raise TypeError("Can not insert item")

        # repr
        def __repr__(self):
            return "{name}({items})".format(name = self.__class__.__name__, items = repr(list(self)))

    tp.converters = tuple(converters)
    tp.__name__ = name
    return tp

if __name__ == "__main__":

    # the first custom type attempts to convert invalid values (for example str to int)

    cuslist = custom_list_type("Mylist", (int, int, str))

    L = cuslist([3, "4", "hello"])
    L[1] = 39.14
    try:
        L[0] = "joe"
    except ValueError:
        print "test joe passed" …
TrustyTony commented: Neat! +12
Gribouillis 1,391 Programming Explorer Team Colleague

Also

'\t'.join(str(x) for x in mylist)
Gribouillis 1,391 Programming Explorer Team Colleague

I don't understand why you open the logfile in read mode in the first case. You can try the following, which should create an error file with a traceback if the logfile does not open

from datetime import datetime
import os
import traceback

logfilename = os.path.join('C:\\', 'Dir1', 'Sub One', 'Sub3', 'Sub4', 'Sub Five', 'logfile.txt')
mode = 'a' if os.path.exists(logfilename) else 'w+'
try:
    log = open(logfilename, mode)
except Exception:
    with open(os.path.join('C:\\', 'ERROR.txt'), 'w') as ofh:
        traceback.print_exc(file = ofh)
Gribouillis 1,391 Programming Explorer Team Colleague

You must not compare strings but datetime instances

now_date = datetime.now()
dir_date = datetime.strptime(fname, fm)
del_date = now_date - timedelta(days = 14)

if  dir_date <= del_date :
    print "Folder %s is older than 14 days" % fname
vegaseat commented: nice +14
Gribouillis 1,391 Programming Explorer Team Colleague

I tried to do it using itertools.groupby(), but hihe's method is faster. The reason is probably that groupby() needs an initial sort, while filling a dict doesn't. Here is the comparison

#!/usr/bin/env python
# -*-coding: utf8-*-
# compare two implementations of creating a sorted index list

data_list = ['the', 'house', ',', 'the', 'beer']

from itertools import count, groupby
from operator import itemgetter
ig0 = itemgetter(0)
ig1 = itemgetter(1)

def score(item):
    return (-len(item[1]), item[0])

def grib_func(data_seq):
    L = sorted(zip(data_seq, count(0)))
    L = ((key, [x[1] for x in group]) for key, group in groupby(L, key = ig0))
    return sorted(L, key = score)

# hihe's code    
def create_index_dict(data_list):
    index_dict = {}
    for ix, word in enumerate(data_list):
        index_dict.setdefault(word, []).append(ix)
    return index_dict

def hihe_func(data_seq):
    return sorted(create_index_dict(data_seq).items(), key = score)

# comparison code

print grib_func(data_list)
print hihe_func(data_list)

from timeit import Timer
for name in ("hihe_func", "grib_func"):
    tm = Timer("%s(data_list)"%name, "from __main__ import %s, data_list"%name)
    print "{0}: {1}".format(name, tm.timeit())

""" my output -->
[('the', [0, 3]), (',', [2]), ('beer', [4]), ('house', [1])]
[('the', [0, 3]), (',', [2]), ('beer', [4]), ('house', [1])]
hihe_func: 11.2509949207
grib_func: 18.3761279583
"""
HiHe commented: thanks +6
vegaseat commented: thanks fortiming this +14