1

I am trying to write a decorator accepting an argument with the syntax:

@random(0.5)
def func1():

So the probability indicates how likely is the function to be executed.

For example:

@randomly(0.6)
def fa():
  return "abc"
 
@randomly(0.4)
def da():
  return "def"

When running:

for i in range(5):
  print(da())

it will print the sentences based on probability (3 times 'abc' and twice 'def'):

abc
def
abc
abc
def

Any ideas how it should work? I haven't found anything like that.

martineau
  • 119,623
  • 25
  • 170
  • 301

2 Answers2

1

The following will work with the API you described:

from functools import wraps
from random import choices

functions, weights = [], []

def randomly(probability):
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            fn ,= choices(functions, weights=weights)
            return fn(*args, **kwargs)
        functions.append(fn)
        weights.append(probability)
        return wrapper
    return decorator

In this implementation, you'll have to make sure yourself that the probabilities add up to 1, otherwise they will be scaled automatically.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
0

Something like this will work:

from random import random


def randomly(prob):
    def decorator(function):
        def wrapper(*args, **kwargs):
            if prob > random():
                return function(*args, **kwargs)
        return wrapper
    return decorator
@randomly(0.8)
def func():
    return "hello"

print([func() for _ in range(10)])

['hello', 'hello', None, 'hello', 'hello', 'hello', 'hello', 'hello', None, 'hello']

You can see more information about this topic here.

Roman Ferenets
  • 374
  • 2
  • 5