Dispatching functions from a dictionary

Discussion in 'Python' started by tkpmep@gmail.com, Mar 30, 2008.

  1. Guest

    To keep a simulation tidy, I created a dispatcher that generates
    random variables drawn from various distributions as follows:

    import random

    RVType = 1 #Type of random variable - pulled from RVDict

    RVDict= {'1': random.betavariate(1,1), '2': random.expovariate(1),
    '3': random.gammavariate(1,1), '4': random.gauss(0,1),
    '5': random.lognormvariate(1,1), '6':
    random.paretovariate(1),
    '7': random.uniform( -1,1), '8':
    random.weibullvariate(1,2) }

    x = []
    y=[]

    rv = RVDict[str(RVType)]
    for i in range(N):
    x.append(rv)
    y.append(rv)


    Oddly, x and y get filled with a single value repeated N times. I
    expected to get a different random number appear each time I called
    rv ,but this does not happen. Instead, my first call to rv generates a
    random number from the appropriate distribution, while subsequent
    calls simply repeat the random number generated in the first call.
    Where am I going wrong?

    Thanks in advance for your help.

    Sincerely


    Thomas Philips
     
    , Mar 30, 2008
    #1
    1. Advertising

  2. Paul Rubin Guest

    writes:
    > RVDict= {'1': random.betavariate(1,1), '2': random.expovariate(1), ...}


    This actually calls the functions random.betavariate, etc. when
    initializing RVDict. If you print out the contents of RVDict you'll see
    that each value in it is just a floating point number, not a callable.

    You want something like:

    RVDict = {'1': lambda: random.betavariate(1,1),
    '2': lambda: random.expovariate(1), etc.

    The "lambda" keyword creates a function that when called evaluates the
    expression that you gave it. For example, lambda x: x*x is a function
    that squares its argument, so saying

    y = (lambda x: x*x) (3)

    is similar to saying:

    def square(x): return x*x
    y = square(3)

    Both of them set y to 9. In the case of lambda: random.expovariate(1)
    you have made a function with no args, so you'd call it like this:

    > rvfunc = RVDict[str(RVType)]
    > for i in range(N):
    > x.append(rvfunc())
    > y.append(rvfunc())


    rvfunc (the retrieved dictionary item) is now a callable function
    instead of just a number. It takes no args, so you call it by saying
    rvfunc().
     
    Paul Rubin, Mar 30, 2008
    #2
    1. Advertising

  3. On Mar 30, 5:06 pm, Paul Rubin <http://> wrote:
    > writes:
    > > RVDict= {'1': random.betavariate(1,1), '2': random.expovariate(1), ...}

    >
    > This actually calls the functions random.betavariate, etc. when
    > initializing RVDict. If you print out the contents of RVDict you'll see
    > that each value in it is just a floating point number, not a callable.
    >
    > You want something like:
    >
    > RVDict = {'1': lambda: random.betavariate(1,1),
    > '2': lambda: random.expovariate(1), etc.


    In Python 2.5, you can also write this as:

    from functools import partial

    RVDict = {'1': partial(random.betavariate,1,1),
    '2': partial(random.expovariate,1),
    etc.


    George
     
    George Sakkis, Mar 30, 2008
    #3
  4. Guest

    Paul, George,

    Thanks a mill - the help is greatly appreciated.

    Thomas Philips
     
    , Mar 31, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark
    Replies:
    4
    Views:
    2,961
    scoude
    Jan 12, 2011
  2. umer
    Replies:
    0
    Views:
    432
  3. Replies:
    4
    Views:
    11,848
    Nigel Wade
    Jul 20, 2005
  4. Terry
    Replies:
    1
    Views:
    366
    John Harrison
    Aug 31, 2003
  5. Eric
    Replies:
    0
    Views:
    398
Loading...

Share This Page