0

I want to implenent a decorator accepting a probability as an argument with the following syntax:

@trigger_randomly(0.5)
def func():

Using only the numpy library.

The probability indicates how likely is the function to be executed when any of the decorated functions are being called.

It's should support also initialization without providing a probability. In that case the probability should be the complement of initialized probabilities.

Example:

@trigger_randomly(0.5)
def first():
  return "good person"

@trigger_randomly(0.4)
def second():
  return "kind person"

@trigger_randomly(0.1)
def third():
  return "happy person"

@trigger_randomly()
def fourth():
  return "beautiful person"

@trigger_randomly()
def fifth():
  return "reliable person"

Running:

personality = {"good person": 0,
"kind person": 0,
"happy person": 0,
"beautiful person": 0,
"reliable person": 0}

for i in range(1000):
    personality[fourth()] += 1

print(personality)

I would like to create a function that receives a probability and returns the strings based on percentages.

function declaration: def trigger_randomly(probability=None)

Should print sentences count based on probability:

{'good person': 500, 'kind person': 301, 'happy person': 95, 
 'beautiful person': 56, 'reliable person': 48}

My code

import numpy as np
from functools import wraps
from random import choices

functions, weights = [], []

def trigger_randomly(probability=None):
    if probability == None:
      probability = 0.1/2
    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

@trigger_randomly(0.5)
def first():
  return "good person"

@trigger_randomly(0.3)
def second():
  return "kind person"

@trigger_randomly(0.1)
def third():
  return "happy person"

@trigger_randomly()
def fourth():
  return "beautiful person"
 
@trigger_randomly()
def fifth():
  return "reliable person"

personality = {"good person": 0, 
           "kind person": 0, 
           "happy person": 0, 
           "beautiful person": 0, 
           "reliable person": 0}
 
for i in range(1000):
    personality[fourth()] += 1
 
print(personality)

I need to use only numpy library

yochi
  • 9
  • 3
  • Please add your attempt to write one to your question. – martineau Feb 03 '21 at 19:19
  • First, that output makes no sense - you've got over 100 results coming from options that should have probability 0. Second, this decorator API has serious usability issues. For example, it's impossible to use it with two sets of functions in the same program. – user2357112 Feb 03 '21 at 19:20
  • Third, you specifically say you want to use NumPy, but working one scalar at a time is an extremely inefficient way to use NumPy. It's like driving to the store by stopping and restarting your car every centimeter. – user2357112 Feb 03 '21 at 19:21
  • 1
    The task you want to achieve is reasonable enough, but decorators are absolutely the wrong way to do it. You can't use Python decorators to choose between different functions, but it would be easy to have a single function that returns the strings you want based on percentages. – Tim Roberts Feb 03 '21 at 19:33
  • I would like to create a function that receives a probability and returns the strings based on percentages. – yochi Feb 03 '21 at 19:43
  • function declaration: def trigger_randomly(probability=None): – yochi Feb 03 '21 at 19:44
  • I write my code in the question @martineau – yochi Feb 03 '21 at 21:49
  • The accepted answer doesn't use `numpy`, but see [A weighted version of random.choice](https://stackoverflow.com/questions/3679694/a-weighted-version-of-random-choice). – martineau Feb 03 '21 at 22:11

0 Answers0