I have a function that needs input as True/False that will be fed in from another function. I would like to know what is the best practice to do this. Here is the example I am trying:
def feedBool(self, x):
x = a_function_assigns_values_of_x(x = x)
if x=="val1" or x == "val2" :
inp = True
else
inp = False
feedingBool(self, inp)
return
def feedingBool(self, inp) :
if inp :
do_something
else :
dont_do_something
return
You can do:
def feedBool(self, x):
x = a_function_assigns_values_of_x(x = x)
feedingBool(self, bool(x=="val1" or x == "val2"))
Or, as pointed out in the comments:
def feedBool(self, x):
x = a_function_assigns_values_of_x(x = x)
feedingBool(self, x in ("val1","val2"))
why not just:
inp = x in ("val1", "val2")
of cause it can be compacted even more directly in the call to the next function, but that will be at the cost of some readability, imho.
You usually put the test in a function and spell out the consequence:
def test(x):
# aka `return x in ("val1", "val2")` but thats another story
if x=="val1" or x == "val2" :
res = True
else
res = False
return res
def dostuff(inp):
# i guess this function is supposed to do something with inp
x = a_function_assigns_values_of_x(inp)
if test(x):
do_something
else :
dont_do_something
dostuff(inp)
Related
I am trying to get this attribute which is very deeply nested.
The problem is that some of the values on the way tends to be None.
here is how I did it (the wrong way).
def name(x):
x = x["relay_rendering_strategy"]
if x:
x = x["view_model"]
if x:
x = x["profile"]
if x:
x = x["event_place"]
if x:
x = x["contextual_name"]
if x:
return x.lower()
return ''
data = [x for x in get_events() if name(x) == 'ved siden af']
In kotlin there is a nice syntax like this:
val name = first?.second?.third?.andSoFourth ?: ''
Is there a similar awesome way you can do it in python???
You can do something similar with dict.get and default values:
def name(x):
return x.get("relay_rendering_strategy", {}).get("view_model", {}).get("profile", {}).get("event_place", {}).get("contextual_name", "").lower()
Or use a simple try-except:
def name(x):
try:
return x["relay_rendering_strategy"]["view_model"]["profile"]["event_place"]["contextual_name"].lower()
except KeyError:
return ""
Or simply keep the nesting level down with a loop to be more DRY:
def name(x):
for k in ("relay_rendering_strategy","view_model","profile","event_place","contextual_name"):
if k not in x:
return ""
x = x[k]
return x.lower()
In python, it is better to ask forgiveness than permission.
Using try/except (as suggested by #Iain Shelvington).
def name(x):
try:
return x["relay_rendering_strategy"]["view_model"]["profile"]["event_place"]["contextual_name"].lower()
except (KeyError, AttributeError):
return ""
I have the following generator function which adds two numbers:
def add():
while True:
x = yield "x="
y = yield "y="
print (x+y)
And I can call it like this:
x=add()
next(x)
'x='
x.send(2)
'y='
x.send(3)
# 5
I thought it would be trivial to add in an init so that I don't have to do the next and I can just start sending it values, and so I did:
def init(_func):
def func(*args, **kwargs):
x=_func(*args, **kwargs)
next(x)
return x
return func
Or, simplifying it to receive no input variables like the function above:
def init(func):
x=func()
next(x)
return x
I thought that doing:
x=init(add) # doesn't print the "x=" line.
x.send(2)
'y='
x.send(3)
5
Would work, but it seems it acts just like as if the init is not there at all. Why does this occur, and how can I get rid of that behavior?
It seems to work for me. Tried
def add():
while True:
x = yield 'x='
y = yield 'y='
print (x+y)
def init(func):
x=func()
next(x)
return x
a = init(add)
a.send(5)
a.send(10)
For me this returns 15, as expected.
[update]
After your update, I think you might just want to print out the a.send():
def add():
while True:
x = yield 'x='
y = yield 'y='
print (x+y)
def init(func):
x=func()
print(next(x))
return x
a = init(add)
print(a.send(5))
a.send(10)
Your code works as-is, however, if you want to print the output that occurs before the field yield statement, then you can adapt the init method to do just that. For example:
def init(func):
x=func()
a=next(x)
if a: print (a) # this line will print the output, in your case 'x='
return x
And now you have:
>>> x=init(add)
x=
>>> x.send(2)
'y='
>>> x.send(3)
5
And finally, to keep your more generalized approach, you can do something like the following with a decorator:
def init_coroutine(_func):
def func(*args, **kwargs):
x=_func(*args, **kwargs)
_ = next(x)
if _: print (_)
return x
return func
#init_coroutine
def add():
while True:
x = yield "x="
y = yield "y="
print (x+y)
>>> x=add()
x=
>>> x.send(2)
'y='
>>> x.send(3)
5
I have the following code:
def check(onen,twon,threen,fourn,fiven):
while ((onen != twon) and (onen != threen) and (onen != fourn) and (onen != fiven)):
return onen
else:
onen = random.randint(1,45)
I'd like to ask how to make it like this:
def check(onen,twon,threen,fourn,fiven):
while ((onen != twon) and (onen != threen) and (onen != fourn) and (onen != fiven)):
return onen
else:
onen = random.randint(1,45)
(check the condition on while again)
I want to make this loop: if the condition is false, check and check again until it's true.
It seems like you have it backwards. Try this:
while not condition:
change condition
return that
For your specific example:
def check(onen, twon, threen, fourn, fiven):
while not ((onen != twon) and (onen != threen) and (onen != fourn) and (onen != fiven)):
onen = random.randint(1,45)
return onen
Or shorter:
def check(onen, twon, threen, fourn, fiven):
while onen in (twon, threen, fourn, fiven):
onen = random.randint(1,45)
return onen
Or much shorter, without the loop (only feasible for small range, though):
def check(onen, twon, threen, fourn, fiven):
return random.choice([x for x in range(1, 46)
if x not in (twon, threen, fourn, fiven)])
Note, however, that neither of those will change the value of onen outside of the function (unless, of course, you do onen = check(...)).
What you are basically looking for is a do-while loop. Python has no do-while loop, but you can easily emulate one:
def something():
while True:
# ...
# perform some task
if [condition]:
return [result]
So here you have to fill in [condition] that checks if the result is satisfying, and [result] is what you want to return. As long as the condition is not met, Python will go for another loop.
Example:
Say you want to query the user for input, you can do this with:
def something():
while True:
try:
x = int(input('Enter a number'))
except ValueError:
x = None
if x is not None:
return x
So here we will keep querying for a number until it is a valid one.
Of course we sometimes can fold the task and condition check together. Here we can transform the above program into:
def something():
while True:
try:
return int(input('Enter a number'))
except ValueError:
pass
From the update to your question it seems you just need to invert the sense of the while to get what you want:
def condition(onen, twon, threen, fourn, fiven):
return ((onen != twon) and (onen != threen) and (onen != fourn) and (onen != fiven))
def check(onen, twon, threen, fourn, fiven):
while not condition(onen, twon, threen, fourn, fiven):
onen = random.randint(1,45)
return onen
You can try this also:
something(condition):
# evaluate and return condition value
while(condition is not satisfactory):
condition = something(condition)
else:
# code post satisfaction of condition
def something():
while(condition):
return that
else:
return this
something() # just callback the function
You can also remove the else statment and just callback the current function
I have two functions that contain mostly the same code. One returns "True" if the array passed in contains all positive numbers while the other returns "True" if the array contains all numbers that are divisible by 10.
I want to combine these two functions into a function like this:
def master_function(array, function):
for i in array:
if function:
result = True
else:
result = False
break
print(result)
return result
The only part that would vary is the "function" in the If statement. When I write functions with the missing line they don't get called as the program executes.
def positive_integers(array):
i >= 0
def divisible_by_10(array):
i%10 == 0
The test code isn't executed either.
master_function([10,20,30,35],divisible_by_10)
Your functions aren't returning anything, and you need to give them access to i:
def positive_integers(i):
return i >= 0
def divisible_by_10(i):
return not i%10
def master_function(array, function):
for i in array:
if function(i):
result = True
else:
result = False
break
print(result)
return result
Your function don't return anything. Also, you need read about all and any:
def positive_integers(array):
return all(i >= 0 for i in array)
def divisible_by_10(array):
return all(i % 10 == 0 for i in array)
def master_function(array, function):
return function(array)
def master_function(array, function):
for i in array:
print str(i)
if function(i):
result = True
else:
result = False
print(result)
return result
def positive_integers(i):
if i >= 0:
return True
def divisible_by_10(i):
if i%10 == 0:
return True
master_function([10,20,30,35],divisible_by_10)
I have a generator function that tracks whether I am between a certain pair of events-- a "start" event and an "end" event. For example, it could be examining tokens and reporting whether I am between the comment delimiters "/*" and "*/" (non-nesting). The following code works, but is there a nice itertools combination or logical restructuring that would simplify it (and/or make it more "pythonic")?
def tokspan(starttok, endtok, stream):
inside = False
for tok in stream:
if (not inside) and tok == starttok:
inside = True
yield (inside, tok)
if inside and tok == endtok:
inside = False
tstream = "int x; /* a non-nesting comment /* etc. */ x=1; main();".split()
for status, tok in tokspan("/*", "*/", tstream):
print(status, tok)
The above (intentionally) returns True for the boundary tokens (/* and */), but that's not particularly important. If you have an approach that happens to exclude one or both boundaries (like python ranges do), I'd still like to know about it.
The only simplification that I can think of is rewriting the logic around setting/resetting inside:
def tokspan(starttok, endtok, stream):
inside = False
for tok in stream:
inside |= (tok == starttok)
yield (inside, tok)
inside &= (tok != endtok)
Whether this makes the code more or less readable is in the eye of the beholder.
It might be possible to use a decorator over here. I am not sure if this is going to be useful to you or not but this might just give you some ideas.
Create a decorator which stores the items you want to filter out with:
import itertools as it
class insideDec(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
def __call__(self, f):
def wrapper(x):
x1 = it.dropwhile(lambda m: not m.startswith(self.start), x )
x1.next()
x2 = it.takewhile(lambda m: not m.startswith(self.stop), x1 )
return f(x2)
return wrapper
#insideDec('{', '}')
def f(val):
return val
if __name__ == '__main__':
print ''.join(f('This is some {string that needs to} be printed'))
Now you apply the decorator to a function that accepts a string. This will convert the function into one whose input is an iterator. You then process the iterator like you would any other iterator.
Of course, you can always convert the iterator to a string at any point of time (like for example over here):
# rest of the code ...
x2 = it.takewhile(lambda m: not m.startswith(self.stop), x1 )
return f(''.join(x2))
# rest of the code ...
That's really up to you ...
Edit:
Sorry about that. I misread your question. For tokenizing, maybe something like the following might help?
class tokenize():
def __init__(self, strVal, start, stop):
self.start = start
self.stop = stop
self.strTees = it.tee(strVal, len(start))
self.inside = False
for i, strTee in enumerate(self.strTees):
for j in range(i):
next(strTee, '')
self.strVals = it.izip( *self.strTees )
def __iter__(self):
return self
def next(self):
v = ''.join(self.strVals.next())
if v == '': raise StopIteration
if v == self.start: self.inside = True
if v == self.stop: self.inside = False
# print '[',v, ']'
return (v[0], self.inside)
if __name__ == '__main__':
strVal = 'int x; /* a non-nesting comment etc. */ x=1; main();'
for x, y in tokenize( strVal, '/*', '*/' ):
print x, y
Again, this is not perfect, by might serve your purposes ...
Here is the output:
i False
n False
t False
False
x False
; False
False
/ True
* True
True
a True
True
n True
o True
n True
- True
n True
e True
s True
t True
i True
n True
g True
True
c True
o True
m True
m True
e True
n True
t True
True
e True
t True
c True
. True
True
* False
/ False
False
x False
= False
1 False
; False
False
m False
a False
i False
n False
( False
) False