My function is:
def names(N=None, p=None, gender=None, start=None, End=None, Interval=None):
And what this function does take the arguments and provide an output obviously. But if N is None, but p is given and all other arguments are Non or if N and P are given and all other arguments are not given, and such a map goes on, that is if one argument is given and other one is not given the output is supposed to vary. Currently I'm using an if statement and boolean to check for it. But since there are so many arguments it's being a really long number probabilities. Hence is there an easier way of doing it?
Currently I am trying:
#assuming N argument is not given but p argument is given
if ((bool(N)==False) and (bool(p)==True))==True:
#then the operation is carried out.
I would suggest having the names method accept either an object with N, p, gender, etc. properties, or a dictionary with those keys. You could then test if the object's properties, or the dictionary's keys, are set.
The object getattr() method or the dictionary .get() method will even let you set default values, or you could set default values in the object's __init__() method.
You might consider splitting the function into several functions that accept less number of parameters (aim for "high cohesion and loose coupling" as a guide in splitting the parameters).
If you convert all parameters to bool then you could exploit that True == 1 and False == 0 e.g.:
result = [['false N, false p', 'false N, true p'],
['true N, false p', 'true N, true p']][N][p]
You could use the matrix to choose a function to call instead of choosing a string.
Related
I have a function that takes in two list values and returns the AND operator output of them. Now I need to make the function take multiple values and get the output. I have done this for now for two lists of flag values:
def and_op(lst1, lst2):
return np.array([(lst1 & lst2) for lst1,lst2 in zip(lst1, lst2)])
and_op([0,0,1,1,0], [1,0,1,1,1])
OUTPUT:
array([0,0,1,1,0])
I now need to change this function such that the arguments are dynamically given and the number of arguments can be more than two.
and_op([0,1,1,0], [1,1,0,1], [1,1,1,0], [0,1,0,1])
How can I change the function so I can get output for the case above? I thought of *args, but got super confused on how to use & operator on it.
Use all function and iterate your args.
def and_op(*args):
return np.array([int(all([arg[i] for arg in args])) for i in range(len(args[0]))])
I want to define a resize(h, w) method, and I want to be able to call it in one of two ways:
resize(x,y)
resize(x)
Where, in the second call, I want y to be equal to x. Can I do this in the method definition or should I do something like resize(x,y=None) and check inside:
if y is None:
y = x
Can I do this in the method definition
No. During the method definition there's no way to know what value x might have at run-time. Default arguments are evaluated once at definition time, there's no way to save a dynamic value for y.
or should I do something like resize(x,y=None) and check inside
exactly. This is a common idiom in Python.
To complete Jim's answer, in the case that None is valid as a parameter value, you could use variable length arguments feature (positional, and/or keyword). Example of use for positional:
def resize(x,*args):
if args:
if len(args)>1:
raise Exception("Too many arguments")
y = args[0]
else:
y = x
in that example, you have to pass x, but you can pass 0 or more extra positional arguments. Of course you have to do the checking manually, and you lose the y keyword.
try this:
d = {"One":1,"Two":2,"Three":3}
d.get("Two", Print("Fail"))
Expected Output:
2
Actual Output:
Fail
2
Anyone know why the right hand argument of this expression is eagerly evaluated? What's the point of processing the right hand argument if there's a chance it's not returned?
Is there a logic to this I'm missing?
It's always evaluated because any functions has to be resolved before the return value can be sent to get.
Instead, you supply a default value to use if the key is not present, or if you need to check multiple keys to get a value, the get call will return None:
val = d.get("Two")
if val is None:
print("Fail..")
This is similar to:
if 'Two' not in d:
print("Fail..")
If you don't want to provide a default value, the first example can still be useful if you have multiple possible values to check - chaining .get calls or having multiple if .. is None: .. checks all the way down.
If you want lazy evaluation, you should use the or operator
d = {"One":1,"Two":2,"Three":3}
d.get("Two") or (print("Fail"))
Here's the logic.
x = d.get("b", expensiveComputation())
This is computed like so:
Compute "b", its value is the first argument to .get.
Call expensiveComputation(), its value is the second argument to .get.
Call .get with these two arguments
Assign the returned value to x.
If you want short-circuiting, Python is very ergonomic.
x = d.get("a") or expensiveComputation()
This is computed like so:
Compute "a", its value is the first and only argument to .get.
Call .get with the one argument.
Since it's an or operator which requires Booleans, call bool() on the returned value.
If the result is True, use the value returned by .get, else call expensiveComputation(), and use the value returned by it.
Assign that to x.
Of course, not only None is falsy, so are empty lists, empty strings, etc; if such falsy objects may occur among your values, this is not what you want.
Python 3.8 introduces assignment expressions so that you could still write one-liners like so:
x if ((x := d.get("a")) is not None) else expensiveComputation()
Here expensiveComputation() will only run if d does not have a value for "a". But this arguably balances on the verge of unreadable.
Is there any other purpose (besides being there because it needs to be) the empty tuple may have? Or: what would you use the empty tuple for? If anything. I just can't find an answer (well, a positive answer as in: "yes, there is"), please help me out with getting this question out of my head. "for testing if another tuple is empty" is not an acceptable answer since we should use 'not' operator for this.
Here's when.
def tuple_of_primes_less_than( n ):
if n <= 2: return ()
else:
x, p = set( range(2,n) ), 2
while p <= max(x):
for k in range(2,int(2+math.sqrt(p))):
x.discard(k*p)
p += 1
return tuple( sorted( x ) )
You might want to store the arguments to a function as a tuple, without knowing the structure of the function in advance. If it happens that the function you need to store the parameters for takes no parameters, you will need to store an empty tuple.
This is just one among many examples of why it's generally better not to question the existence of edge cases, just because we can't think of a use for them. The need to support the edge case invariably crops up before long.
Tuples represent arbitrary sequences of values. When you need to describe an empty sequence of values, you can use an empty tuple.
This function that I have written thus:
def simulate_turn(num_rolls, score, opponent_score):
"""This function takes in two scores and a number of die rolls and returns
what the two scores would be if num_rolls many dice were rolled. This takes
into account the swine swap, free bacon, and hog-wild."""
x = score
y = opponent_score
x += take_turn(num_rolls,opponent_score,select_dice(score,opponent_score))
if ifwillswap(x,y):
swap(x,y)
return x,y
When run in the interactive python shell (the function comes from a .py file), it is returning an int object instead of a tuple! What am I doing wrong? I am trying to have it turn a pair of values, not a single int object.
You already do return a pair of values. Even if you somehow broke x and y somewhere along the way and had something ridiculous like this:
def example():
return None, None
a = example()
a would still hold a reference to the tuple (None, None) after the execution of that function. So you are returning a tuple of two "somethings", the only question is what are those "somethings" and how you are storing them. There is no reason for you to think that your function returns an int however, because it doesn't. No matter what, with the syntax you've used, your function returns a tuple of two types. You could even just do return x, and that would return a one-item tuple. The comma prevents you from returning just an int.
My guess is that your function swap() is maybe setting your variable y equal to None and that you are perhaps misinterpreting the returned values. As others have said, I don't see how you can see anything but a tuple as the return.