I'm pretty new to Python and have written a function that has 5 arguments:
def function(a,b,c,d=False,e=" "):
Argument d can either be true or false. If false, then the default value for e will be white space, and we wouldn't need to pass this into the function when calling it, if true, then we can either pass an argument to e, or leave it blank.
function(a,b,c,False) #Example 1: d==False
function(a,b,c,True,'*') #Example 2: d==True, then pass value to e to override default
My issue, however, lies with the following example:
function(a,b,c,True) #Example 3: d==True but no value passed to e
If d is true and no value is passed to argument e, I want to change the default value of e to something else. I only want to do this in instances where d==True and e isn't passed. Basically, I want the default behaviour of argument e to be dependent on the boolean value of d:
def function(a,b,c,d=False,e=" " if d==False, '*' if d=True)
Basically, I want two default states for argument e, dependent on whether argument d is True or False.
Is this possible?
Use a None value for e and adjust if not passed
def function(a,b,c,d=False,e=None):
if e is None:
e="*" if d else ' '
pass
Related
I have a python string like: "(a and b and c) or (d and e)", where a, b, c, d and e are conditions of some kind. As you can probably see, this is actually a logical expression.
I'd like to somehow convert it into a logic-gate-like function, say, f. So I would pass a number of true conditions to f, and get the logical results. Examples:
If I pass it (d and e) (i.e., d and c are true), f returns True.
If I pass it (a and b and c), f returns True.
If I pass it just a, f returns False.
If I pass it just b and c, f returns False.
I have no idea how to tackle such a question. strtobool doesn't quite handle my requirements, and I'm not sure how to even convert the given string into a function. As for passing it true conditions as input, I'm thinking of passing it a list of True booleans, i.e. all conditions are False by default. e.g. from the first example above:
d = True; e = True
f([d, e])
> True
d = True; e = False
f([d])
> False
You're looking for eval.
Essentially, you can do-
eval('d and e', {'d': True, 'e': False})
Which passes the d and e string to evaluate, and also passes in some globals, to set the value of those variables.
It's often better to use the third argument, locals, instead of globals however.
eval('d and e', {}, {'d': True, 'e': False})
This will achieve the same thing, except d and e are set in local scope, the second argument is just empty.
The problem is, if I define a function in python with 3 parameters and then I input only 2 parameters, I will get an error.
Can I define the function so if there is one parameter missing (user has given 2 inputs instead of 3), it will use a default value for that missing parameter such as 0?
def sum(a, b, c):
return a+b+c
If I use:
add = sum(1, 2)
print(add)
It will give me an error. Now I want to define the function so it will add the missing value as 0, but if I give all the 3 values, it will not use 0 as a default value.
you can use default parameters:
def my_sum(a, b, c=0):
return a + b + c
When defining the defining a function if you set a value to a parameter, then you are tellign the function to use that value as default, except a value is specified.
This means that by setting a=0,b=0,c=0 AS #Olvin Roght said, you will by default pass a 0 to those parameters (hence not affecting your sum) unless something else is specified.
Example:
def sum(a=0, b=0, c=0):
return a+b+c
Output:
print(sum(a=1,b=2))
3 #1+2+0
print(sum(a=1,b=2,c=3))
6 #1+2+3
print(sum())
0 #0+0+0
Let's say we have the function f and I need the argument b to default to an empty list, but can't set b=[] because of the issue around mutable default args.
Which of these is the most Pythonic, or is there a better way?
def f(a, b=None):
if not b:
b = []
pass
def f(a, b=None):
b = b or []
pass
The first form as it reads easier. Without any specific context, you should explicitly test for the default value, to avoid potential truthiness issues with the passed in value.
def f(a, b=None):
if b is None:
b = []
pass
From PEP 8, Programming Recommendations:
Also, beware of writing if x when you really mean if x is not None --
e.g. when testing whether a variable or argument that defaults to None
was set to some other value. The other value might have a type (such
as a container) that could be false in a boolean context!
You can see examples of this approach throughout the cpython repository:
Lib/bdb.py
Lib/argparse.py
Lib/base64.py
def f(a, b=''):
if not b:
b = []
print(a)
You can cdo something simple such as "if not b". If you are going to make the default argument an empty string or set it equal to None, you can simply use an if statement to define what B should be if you are never actually going to enter an argument for b. In this example we simply set it to an empty list.
Say I have some arguments passed to a function, I use those arguments to do some calculations, and then pass the results to another function, where they are further used. How would I go about passing the results back to the first function and skipping to a point such that data is not sent back to the second function to avoid getting stuck in a loop.
The two functions are in two different python scripts.
The way I'm currently doing it is by adding any new arguments supposed to be coming from the second script as non keyword arguments, and passing all the arguments from the first function to the second even if they are not needed in the second. The second function passes all the arguments back to the first, and an if condition on the non keyword argument to check whether it has its default value is used to determine if the data has been sent back by the second function.
In f1.py:
def calc1(a, b, c, d = []):
a = a+b
c = a*c
import f2
f2.calc2(a, b, c)
If d != []: # This checks whether data has been sent by the second argument, in which case d will not have its default value
print(b, d) # This should print the results from f2, so 'b' should
# retain its value from calc1.
return
In the another script (f2.py)
def calc2(a, b, c):
d = a + c
import f1
f1.calc1(a, b, c, d) # So even though 'b' wasn't used it is there in
# f2 to be sent back to calc1
return
Having two methods recursively call each other is usually a bad idea. It's especially bad between two files. It looks like you want to call calc1(), have it call calc2() internally, and then make a decision about what to do based on the result of calc2().
Is this what you are trying to do?
#### f1.py
import f2
def calc1(a, b, c):
a = a+b
c = a*c
d = f2.calc2(a, b, c)
# This checks whether data has been sent by the second argument,
# in which case d will not have its default value
if d:
# This should print the results from f2, so 'b' should retain
# its value from calc1.
print(b, d)
#### f2.py
def calc2(a, b, c):
return a + c
I have some variables and I want to select the first one that evaluates to True, or else return a default value.
For instance I have a, b, and c. My existing code:
result = a if a else (b if b else (c if c else default))
Another approach I was considering:
result = ([v for v in (a, b, c) if v] + [default])[0]
But they both feel messy, so is there a more Pythonic way?
Did you mean returning first value for what bool(value)==True? Then you can just rely on the fact that boolean operators return last evaluated argument:
result = a or b or c or default
If one variable is not "defined", you can't access its name. So any reference to 'a' raises a NameError Exception.
In the other hand, if you have something like:
a = None
b = None
c = 3
you can do
default = 1
r = a or b or c or default
# r value is 3
So long as default evaluates to True:
result = next((x for x in (a, b, c, d , e, default) if x))
You could do something like this (in contrast to the other answers this is a solution where you don't have to define the 'missing' values as being either None or False):
b = 6
c = 8
def first_defined(items):
for x in items:
try:
return globals()[x]
break
except KeyError:
continue
print first_defined(["a", "b", "c"])
In order to avoid NameErrors when a, b or c isn't defined: give the function a list of strings instead of variable references (you can't pass non-existing references). If you are using variables outside the 'globals()' scope, you could use getattr with its default argument.
--
If a, b and c are defined, I'd go for something like this (considering the fact that an empty string, None or False evaluate to a boolean False):
a = None
b = 6
c = 8
def firstitem(items):
for x in items:
if x:
return x
break
else:
continue
print firstitem([a, b, c])
Don't know if this works in every case, but this works for this case.
a = False
b = "b"
c = False
default = "default"
print a or b or c or default # b
How about this ?
a=None
b=None
c=None
val= reduce(lambda x,y:x or y,(a,b,c,"default"))
print val
The above prints "default". If any of the inputs is defined, val would contain the first defined input.
If by defined you mean ever assigned any value whatsoever to in any scope accessible from here, then trying to access an "undefined" variable will raise a NameError exception (or some subclass thereof, but catching NameError will catch the subclass too). So, the simplest way to perform, literally, the absolutely weird task you ask about, is:
for varname in ('a', 'b', 'c'):
try: return eval(varname)
except NameError: pass
return default
Any alleged solution lacking a try/except won't work under the above meaning for "defined". Approaches based on exploring specific scopes will either miss other scopes, or be quite complex by trying to replicate the scope-ordering logic that eval does for you so simply.
If by "defined" you actually mean "assigned a value that evaluates to true (as opposed to false)", i.e., all values are actually defined (but might happen to be false, and you want the first true value instead), then the already-proposed a or b or c or default becomes the simplest approach. But that's a totally different (and even weirder!) meaning for the word "defined"!-)