Don't forget to also checkout my second blog containing articles to all other related ICT topics!!

Thursday, May 17, 2012

Using Dependency Injection

Take a good look at the current implementation below for expectedvalue. There is no way to write a proper test for this function as it involves randomness. So how do we work our way around this? We can parameterize the random part of our implementation and pass in a non-random implementation in order to test. This principle of switching components at runtime is called Dependency Injection.
import random

def cointoss(n):
    for i in range(n):
        yield random.choice(['head', 'tail'])

def expectedvalue(n):
    #Returns our win or loss after tossing coin for n times
    #head: we win 1 dollar, tail: we loose one dollar
    returnvalue = {'head': 1, 'tail': -1} 
    return sum([returnvalue[coinflip] for coinflip in cointoss(n)])

print expectedvalue(100)
print expectedvalue(100)
print expectedvalue(100)
print expectedvalue(100)

-2
14
16
4

Now let's take a look how we can do this in Python. We see that cointoss is the random part so we parameterize it as a function parameter.
import random

def cointoss(n):
    for i in range(n):
        yield random.choice(['head', 'tail'])

def expectedvalue(n, tossing_func=cointoss):
    #Returns our win or loss after tossing coin for n times
    #head: we win 1 dollar, tail: we loose one dollar
    #default tossing_func = cointoss
    returnvalue = {'head': 1, 'tail': -1} 
    return sum([returnvalue[coinflip] for coinflip in tossing_func(n)])

def always_loose(n):
    for i in range(n):
        yield 'tail'

def always_win(n):
    for i in range(n):
        yield 'head'


assert expectedvalue(100, always_loose) == -100
assert expectedvalue(100, always_win) == 100
print expectedvalue(100)

-22

2 comments:

  1. 1. It doesn't work on codepad.org. Does it require some specific Python version?

    2. Even if it worked, couldn't you write like this and remove condition from inside the function?
    def expectedvalue(n, tossing_func=cointoss):

    ReplyDelete
  2. Hi Ivan,

    you're right about your remark. I tested the same code in codepad where it fails. I modified the sample code and it should work in codepad as well now.

    Thx for the remark !!

    ReplyDelete