Suppose I have a function named generator
that returns a 4-tuple with randomly selected values in certain pre-specified ranges. Let's say the tuple is of the form (age, sex, location, marital_status)
:
age is in range(5, 85)
sex is a member of the set {"m", "f"}
location is a member of the set of all the cities in California
marital_status is a member of {"married", "single", "separated"}
On the other hand, let's say I have defined 20 different functions with definitions like this:
def p1 (age, sex, location, marital_status)
def p2 (age, sex, location, marital_status)
.
.
where p1
is supposed to receive parameters with values of the following form:
`age` must be in the range 20 to 45
`sex` must be male
`location` could be any city in Southern California
`marital_status` could be either single or married
and imagine a different set of values for p2
all the way to p20
.
What is a pragmatic way to determine which set of generated values match which function?
In this case all the definitions where exactly the same, but I can imagine instances where there might be slight differences in the definitions, for example p18
could be def p1 (age, location)
with specific limitations on the range of possibilities for age
and location
.
P.S. The patters are not necessarily mutually exclusive, meaning a set of generated values might as well match more than one function.
regex = r"([a-zA-Z]+) (\d+)" if re.search(regex, "Jan 2"): match = re.search(regex, "Jan 2") # This will print [0, 5), since it matches at the beginning and end of the # string print("Match at index %s, %s" % (match. start(), match. end())) # The groups contain the matched values. In particular: # match.
Pattern matching involves providing a pattern and an associated action to be taken if the data fits the pattern. At its simplest, pattern matching works like the switch statement in C/ C++/ JavaScript or Java. Matching a subject value against one or more cases.
Pattern matching is the process of checking whether a specific sequence of characters/tokens/data exists among the given data. Regular programming languages make use of regular expressions (regex) for pattern matching.
As a Pythonic way in Python 3.X (but not 2.X), you can attach annotation information (arbitrary user-defined data about a function’s arguments and result) to a function object. Here you can use this feature in a decorator to wrap your function to check the range of your arguments.
For example you can use the following range test function :
def rangetest(func):
def onCall(**kargs):
argchecks = func.__annotations__
if all(val in range(*argchecks.get(arg)) for arg,val in kargs.items()):
return func(**kargs)
else :
print ("invalid arg range")
return onCall
@rangetest
def func(a:(1, 5), b:(4,7), c:(0, 10)):
print(a + b + c)
Demo :
func(a=2, b=6, c=8)
16
func(a=2, b=6, c=15)
invalid arg range
There is some point here. The first is that, since the annotation information is within a dictionary (python returns it as a dictionary) and dictionaries don't have a specific order, you need to use keyword arguments in your function to be able to get its relative range in annotation information dictionary.
Also here I just used numeric range but you can use some custom ranges like list of words like what you show in your question.But inside the all
you need to check its type then based on its type use a proper operation :
all(kwargs.get(arg) in range(*arg_range) if is instance (arg_range,tuple) else kwargs.get(arg) in arg_range for arg,arg_range in argchecks.items())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With