This question already has answers here:
Python: avoiding if condition for this code?
(8 answers)
What does colon equal (:=) in Python mean?
(6 answers)
Closed 27 days ago.
Let's say we have the following code:
if re.search(r"b.", "foobar"):
return re.search(r"b.", "foobar").group(0)
This is obviously a redundant call, which can be avoided by assigning the condition to a variable before the if block:
match = re.search(r"b.", "foobar")
if match:
return match.group(0)
However, this means that the condition is always evaluated. In the example above, that makes no difference, but if the match is only used in an elif block, that's an unnecessary execution.
For example:
match = re.search(r"b.", "foobar")
if somecondition:
return "lorem ipsum"
elif match:
return match.group(0)
If somecondition is true and we had the redundant version like in the first code block, we would never call re.search. However, with the variable placed before the if-elif-Block like this, it would be called unnecessarily. And even with the duplicated call, we're instead executing it twice if somecondition is false.
Unfortunately, depending on the use case, evaluating the condition could be very computationally expensive. With the two variants above, if performance is the goal, a choice can be made depending on the likelyhood of somecondition evaluating to true. More specifically, if the elif block is called more often than not, declaring the variable before if the if block is more performant (unless Python somehow caches the result of two identical stateless function calls), whereas the alternative is better if the elif block is rarely reached.
Is there a way to avoid this duplication by reusing the variable from the (el)if block?
Related
This question already has answers here:
Python Ternary Operator Without else
(8 answers)
Conditional return with no else
(2 answers)
Closed last month.
Quite frequently, I have written lines like
if arg == foo: return bar
It is naturally a one-liner, at the beginning of a function body. Notice there is no else, it just returns on a special value of the parameter, and proceeds with the normal flow of the function otherwise.
Still, it feels like the order is wrong. In perl it is possible to write (modulo some $'s)
return bar if arg == foo
which feels more natural. Matter of taste, I know.
Is there a pythonic way of writing something after a return word that would impose a condition on the return statement?
It is, of course, possible, that there is no way.
I have a simple question regarding the use of parentheses in Python's conditional statements.
The following two snippets work just the same but I wonder if this is only true because of its simplicity:
>>> import os, socket
>>> if ((socket.gethostname() == "bristle") or (socket.gethostname() == "rete")):
... DEBUG = False
... else:
... DEBUG = True
...
>>> DEBUG
and now without parentheses
>>> import os, socket
>>> if socket.gethostname() == "bristle" or socket.gethostname() == "rete":
... DEBUG = False
... else:
... DEBUG = True
...
>>> DEBUG
Could anyone help shed some light on this? Are there any cases where I should definitely use them?
The other answers that Comparison takes place before Boolean are 100% correct. As an alternative (for situations like what you've demonstrated) you can also use this as a way to combine the conditions:
if socket.gethostname() in ('bristle', 'rete'):
# Something here that operates under the conditions.
That saves you the separate calls to socket.gethostname and makes it easier to add additional possible valid values as your project grows or you have to authorize additional hosts.
The parentheses just force an order of operations. If you had an additional part in your conditional, such as an and, it would be advisable to use parentheses to indicate which or that and paired with.
if (socket.gethostname() == "bristle" or socket.gethostname() == "rete") and var == condition:
...
To differentiate from
if socket.gethostname() == "bristle" or (socket.gethostname() == "rete" and var == condition):
...
The parentheses are redundant in this case. Comparison has a higher precedence than Boolean operators, so the comparisons will always be performed first regardless of the parentheses.
That said, a guideline I once saw (perhaps in Practical C Programming) said something like this:
Multiplication and division first
Addition and subtraction next
Parentheses around everything else
(Yes, IIRC they left out exponentiation!)
The idea being that the precedence rules are arcane enough that nobody should be expected to remember them all, neither the original programmer nor the maintenance programmer reading the code, so it is better to make it explicit. Essentially the parentheses serve both to communicate the intent to the compiler and as documentation for the next schmoe who has to work on it.
I believe in Python those two statements will generate the same bytecode so you're not even losing any efficiency.
I was always thinking that this is part of PEP8, but apparently it's not. However in all examples you meet in PEPs, code samples and documentation you never see redundant parentheses (there is even such an inspection in PyCharm, for example).
General recommendation is to use parentheses only if it improves readability or you actually want to change the order of expression calculation (such as (a or b) and c).
Do:
if (first_expr or second_expr) and third_expr:
if first_expr or second_expr:
Don't:
if ((first_expr or second_expr) and third_expr):
if (first_expr):
if (first_expr or (second_expr and third_expr)):
In your code sample, parentheses are completely redundant, just use if socket.gethostname() == "bristle" or socket.gethostname() == "rete": (in production code, of course, in will be much more readable, but that's rather off-topic now)
In Python and many other programming languages, parentheses are not required for every expression with multiple operators. This is because operators have a defined precedence. See the table here (Section 5.15) for information on operator precedence in Python.
You can draw an analogy to arithmetic. These expressions are equivalent:
5 * 5 + 3
(5 * 5) + 3
If you mean to add three first, then you need to use the parentheses like this:
5 * (5 + 3)
Have a look at the manual. The higher you are up in the list, the operator will be applied later. "or" is above "==" , and therefore, in this particular case the answers are the same. However, for readability, and just to be sure, I would recommend parenthesis.
I just met a similar question. My conditional statement is
if count1==0 & count2==0 & count3==0:
The first result is True, the second is False, and the third is True. Intuitively, the result for this conditional statement is true. However, it's false. But the result for the following sentence is correct;
if (count1==0) & (count2==0) & (count3==0):
I still have not figured out why this happening.
Why do we see Python assignments with or?
For example:
def my_function(arg_1=None, arg_2=0):
determination = arg_1 or arg_2 or 'no arguments given!'
print(determination)
return determination
When called with no arguments, the above function would print and return 'no arguments given!'
Why does Python do this, and how can one best make best use of this functionality?
What the "or" expression does on assignment:
We sometimes see examples of this in Python as a substitute for conditional expression with ternary assignments, (in fact, it helped inspire the language to add conditional statements).
x = a or b
If bool(a) returns False, then x is assigned the value of b
Identical Use-case of Conditional Expressions (i.e. Ternary Assignments)
Here's an example of such a conditional expression that accomplishes the same thing, but with perhaps a bit less mystery.
def my_function(arg_1=None, arg_2=0):
determination = arg_1 if arg_1 else arg_2 if arg_2 else 'no arguments given!'
print(determination)
return determination
Repeating this syntax too much is considered to be bad style, otherwise it's OK for one-liners. The downside is that it is a bit repetitive.
or Expressions
The base case, x or y returns x if bool(x) evaluates True, else it evaluates y, (see the docs for reference). Therefore, a series of or expressions has the effect of returning the first item that evaluates True, or the last item.
For example
'' or [] or 'apple' or () or set(['banana'])
returns 'apple', the first item that evaluates as True, and
'' or [] or ()
returns (), even though it evaluates as False.
Extended and usage
For contrast, x and y returns x if bool(x) evaluates as False, else it returns y.
It makes sense that and would work this way when you consider that all of the conditions in a conditional and series needs to evaluate as True for the control flow to proceed down that path, and that it makes no sense to continue evaluating those items when you come across one that is False.
The utility of using and for assignment is not immediately as apparent as using or, but it was historically used for ternary assignment. That is, before this more clear and straightforward construction was available:
a = x if condition else y
the equivalent formed with boolean operators was:
a = condition and x or z # don't do this!
which while the meaning is derivable based on a full understanding of Python and and or evaluation, is not nearly as readable as the ternary conditional, and is best avoided altogether.
Conclusion
Using Boolean expressions for assignment must be done carefully. Definitely never use and for assignment, which is confusing enough to be quite error-prone. Style mavens will find use of or for assignments less preferable (than the more verbose ternary, if condition else), but I have found that it is so common in the professional Python community that it could be considered idiomatic.
If you choose to use it, do so cautiously with the understanding that the final element, if reached, will always be returned regardless of its evaluation, so that final element should probably be a literal, so that you know you have a good default fallback for your variable.
This question already has answers here:
Break out of a while loop using a function
(3 answers)
Closed 7 years ago.
I need to break out of a for loop according to the result obtained after calling a function. This is an example of what I'm after (does not work obviously):
def break_out(i):
# Some condition
if i > 10:
# This does not work.
return break
for i in range(1000):
# Call function
break_out(i)
Of course this is a very simple MWE, my actual function is much bigger which is why I move it outside of the for loop.
This answer says it is not possible and I should make the function return a boolean and add an if statement inside the for loop to decide.
Since it's a rather old question and it didn't get much attention (also, it's applied to while loops), I'd like to re-check if something like this is possible.
No, it's not (reasonably) possible. You could raise an exception, I suppose, but then you'll have to catch it with a try/except statement outside the loop.
Since OP has expressed curiosity about this, I'm going to explain why Python doesn't allow you to do this. Functions are supposed to be composable elements. They're meant to work in different contexts.
Allowing a function to break out of a loop has two separate problems:
Client code might not expect this behavior.
What if there is no loop?
For (1), if I read some code like this:
import foo # some library I didn't write
while condition:
foo.bar()
assert not condition
I reasonably assume the assertion will not fire. But if foo.bar() was able to break out of the loop, it could.
For (2), perhaps I wrote this somewhere else:
if condition:
foo.bar()
It's not clear what that should do if foo.bar() tries to break out of the loop, since there is no loop.
Rather than return break, return a value that forces a break condition. To extend your example:
def break_out(i):
# Some condition
return i > 10 # Returns `True` if you should break from loop.
for i in range(1000):
# Call function
if break_out(i):
break
# Insert the rest of your code here...
This question already has answers here:
Alternatives for returning multiple values from a Python function [closed]
(14 answers)
Closed 9 months ago.
I have a function where I need to do something to a string. I need the function to return a boolean indicating whether or not the operation succeeded, and I also need to return the modified string.
In C#, I would use an out parameter for the string, but there is no equivalent in Python. I'm still very new to Python and the only thing I can think of is to return a tuple with the boolean and modified string.
Related question: Is it pythonic for a function to return multiple values?
def f(in_str):
out_str = in_str.upper()
return True, out_str # Creates tuple automatically
succeeded, b = f("a") # Automatic tuple unpacking
Why not throw an exception if the operation wasn't successful? Personally, I tend to be of the opinion that if you need to return more than one value from a function, you should reconsider if you're doing things the right way or use an object.
But more directly to the point, if you throw an exception, you're forcing them to deal with the problem. If you try to return a value that indicates failure, it's very well possible somebody could not check the value and end up with some potentially hard to debug errors.
Return a tuple.
def f(x):
# do stuff
return (True, modified_string)
success, modified_string = f(something)
Returning a tuple is the usual way to do this in Python.
Throwing an exception for failure is one good way to proceed, and if you're returning a lot of different values, you can return a tuple. For the specific case you're citing, I often take an intermediate approach: return the modified string on success, and return None on failure. I'm enough of an unreconstructed C programmer to want to return a NULL pointer to char on failure.
If I were writing a routine to be used as part of a larger library and consumed by other developers, I'd throw an exception on failure. When I'm eating my own dogfood, I'll probably return different types and test on return.
You can use return statement with multiple expressions