ActiveState Code

Recipe 271669: Ruby like syntactic sugar


Ruby offers very nice language constructs for loops or for iterating over lists like the following: 5.times { print "Hello World" }. This recipe shows a hack how to implement these features in python.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Times:
    def __rmul__(self,n):
        for i in range(n):
            self.func()
    def __call__(self,func):
        self.func=func
        return self
times=Times()

class Each:
    def __rmul__(self,L):
        return map(self.func,L)
    def __call__(self,func):
        self.func=func
        return self
each=Each()

class Length:
    def __rmul__(self,L):
        return len(L)
length=Length()

def printf(x):
    print x

5 *times(lambda: printf("Hello"))
[1,2,3,4] *each(lambda x: printf("Count:"+str(x)))
print [1,2,3,4,5] *length
['a','b','c','d','e'] *each(lambda char: char+'!')

Discussion

This is only a fun recipe and you should not use this programming style because it can lead to a lot of confusions. Using this style you can define methods for classes that are normally capsuled like numbers and lists. I would wish python would provide a nicer way to do this.

Comments

  1. 1. At 12:45 p.m. on 4 mar 2004, Paul Reznicek said:

    Some improvements. Nice (although map can do nearly the same), here a small improvement:

    class Repeat:
        def __rmul__(self,n):
            for i in range(n):
                if self.passCurrentIndex:
                    self.kwargs.update({'currentIndex':i})
                    self.func(*self.args,**self.kwargs)
                else:
                    self.func(*self.args,**self.kwargs)
        def __call__(self,func,*args,**kwargs):
            self.func=func
            self.args=args
            self.passCurrentIndex=kwargs.pop('passCurrentIndex',None)
            self.kwargs=kwargs
            return self
    repeat=Repeat()
    
    # PRINT usable as FUNCTION
    def printf(*args):
        print ' '.join(args)
    
    # usage:
    5 * repeat(printf, 'Hello', 'World')
    
    # test index argument
    def testRepeat(*args,**kwargs):
        print ' '.join(args), 'index=',
        print kwargs.get('currentIndex','USE passCurrentIndex=True TO ACTIVATE')
    
    5 * repeat(testRepeat, 'Hello', 'World')
    5 * repeat(testRepeat, 'Hello', 'World', passCurrentIndex=True)
    

    Frankly, Python is the best for me and I can't imagine a

    better way to do language wraps like in Python.

    Paul

Sign in to comment