Dispatching functions from a dictionary

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • tkpmep@gmail.com

    Dispatching functions from a dictionary

    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.betavari ate(1,1), '2': random.expovari ate(1),
    '3': random.gammavar iate(1,1), '4': random.gauss(0, 1),
    '5': random.lognormv ariate(1,1), '6':
    random.paretova riate(1),
    '7': random.uniform( -1,1), '8':
    random.weibullv ariate(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

  • Paul Rubin

    #2
    Re: Dispatching functions from a dictionary

    tkpmep@gmail.co m writes:
    RVDict= {'1': random.betavari ate(1,1), '2': random.expovari ate(1), ...}
    This actually calls the functions random.betavari ate, 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.betavari ate(1,1),
    '2': lambda: random.expovari ate(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.expovari ate(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().

    Comment

    • George Sakkis

      #3
      Re: Dispatching functions from a dictionary

      On Mar 30, 5:06 pm, Paul Rubin <http://phr...@NOSPAM.i nvalidwrote:
      tkp...@gmail.co m writes:
      RVDict= {'1': random.betavari ate(1,1), '2': random.expovari ate(1), ...}
      >
      This actually calls the functions random.betavari ate, 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.betavari ate(1,1),
      '2': lambda: random.expovari ate(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

      Comment

      • tkpmep@gmail.com

        #4
        Re: Dispatching functions from a dictionary

        Paul, George,

        Thanks a mill - the help is greatly appreciated.

        Thomas Philips

        Comment

        Working...