Applied this to my pytho script and this changes the looks of my code 180 degrees. Thanks a lot for this little tuto. Here is your like and comment buddy
I used to do a lot of nesting of if statement, but that was because I had read and had been taught it was bad to have more than one return statement per function.
else/if (elif) should solve the issue without having many return values. There is an example in another comment. Personally I think one or two guard clause are acceptable, three start to hurt readability and more can be as confusing as the alternative, because it's not easy to track below which variables are relevant and what are their values. Another alternative could be to do the validation in another function, especially if you need to do significant work in your main branch.
As always it's a balancing act. Good quality code mainly should contain no unexpected surprises. A block of guard clauses at the top of a function is pretty straightforward and easy to follow, hence the early returns there aren't an issue. They actually make it _easier_ to reason about the code, because you know that you don't have to worry about the rest of the function - you just returned from it - whereas an if...elif...else cascade might still execute code somewhere further down the line. What's more problematic are early returns somewhere in the middle of a function. These are easier to miss, and require more reasoning about if/when/how they might get executed. Also at this point there are often already changes made to the program state which might need to be reverted before exiting. Early returns in the middle of a function are usually an indicator that the function is doing too much and should be split up. This is in my opinion the main characteristic of a "guard clause": it _prevents_ any state change if the _preconditions_ for the function to work are not met.
This is correct behaviour in languages like C where you have to do your own garbage collection. It's not a problem with Python. But it's probably good practice to look at nested conditions after you've written them, to see if any optimisation can be done, regardless of the language
@@apmcd47 I'm not just talking about garbage collection, but any (partial) state change. A return in the middle of a function means that there is code that _does_ something before it, and there is also code that _would_ do more after it. Whatever that "something" is, it might have changed the state of the program (or even the system). Maybe it's just e.g. an empty file that was created but never written to, but without analyzing the function code you'll never know if it wasn't something more intricate. Hence having returns only at the very beginning (guard clauses) and the very end (single exit point) makes it easier to reason about the program. Because then you know that it's "all or nothing".
No it's not. It's not much different from inverting if statements in terms of functionality, but conceptually his guard clauses are very different. Personally I'm wondering why he didn't even mention the inverted if pattern and the way it makes elif an easy way to avoid nesting. Having a return in a guard clause is an invitation to spaghetti land.
@@nialltracey2599When done well, it reduces cognitive load on the reader, as the code is working on a more restrictive set of conditions as you go downward, without nesting.
@@eryqeryq Except the same claim is made about single return statement per procedure -- that it reduces cognitive load. It does this by not forcing the reader to keep every execution path in. But the problem is that every coding paradigm claims to be better because X, Y, Z. To me, the problem is that we're still working in plain-text source code. People keep fighting over whether guard clauses or throwing exception is superior, but it's all cruft. Guard clauses are supposed to improve cognitive load by eliminating all error cases and edge cases so that you don't have to think of them in your code, which they do (I personally use guard clauses myself and do the thing of multiple return clauses in many of my procedures... but then again, I love spaghetti in most flavours of sauce. If we weren't doing plain-text source code, we could hide the guard clauses as preconditions for the procedure call. That way, we wouldn't have to look at them at all until and unless a new error case arose. Now *that* would **really** reduce cognitive load.
Hi thank you for another good tutorial and please take this as positive critism. I agree with you about the issue of reducing else statements, however I dont agree with your suggested solution, you have unnecessary return statements which could be avoided using `elif` statements instead. Also I generally would have prefered one function call to print, here is my recommended solution for this: def go_online(): message = 'You are online' if not connection: message = 'No connection...' elif not paid: message = 'User has not paid...' elif not internet: message = 'No Internet...' print(message)
I think you're missing the point, the early returns are intentional and pretty critical to the role that guard clauses play. Consider a different scenario, with a function that reads and returns a value from a database, but it should only do so for someone with admin access. In that case, you could use a guard clause to check if the user doesn't have admin access, and if so, return an error message so it doesn't proceed, because you don't want the function to continue running once you've determined that the user is not an admin. So technically yes, it would be possible to achieve the desired goal for the particular function demonstrated in this video without doing early returns, but early returns are a feature, not a bug, of guard clauses. I think a different example function, or better yet, multiple example functions, would have made it clearer in the video.
Your both right and I am well aware what a guard clause is, but I was pointing out that it's irrelevant for the expressed example as you could have used else if statements to get the same outcome, which would have avoided multiple redundant return statements and make the code look cleaner in my opinion. But yes a guard clause (or what I often refer to as "early return") statement is far better when you have a conditional expression to end the progression of a function earlier.
Yep, is this how to code an if-else ladder. In C you'd be declaring variables in the inner blocks, to keep them closest to where they're used. Can't do that if you just bail out with a return.
As an alternative to returning, you can also use ‘elif’. if not connection: …. elif not paid: …. This will have similar functionality, except instead of returning, it jumps down to the bottom of the if-elif-else block. Personally, I do just used the return , but there are programmers who don’t like the idea of early returns.
Personally in this case I would use a variable called message (or msg), setting it as I go through the various conditions.The last two lines would be to print the message and return. Even better, by presetting the message to "You are online" and testing only for offline you don't need any else clauses at all! For this scenario.
@@apmcd47As you said, for this scenario, that works for this simple example which just prints a string, but there are usually lots of code and more complicated checks involved real programs. In those cases, the elif construction can also help.
I don’t usually run into this issue. Usually it’s something like: void f(){ Element e=value; if(e != null){ if(collection.contains(e)){ // single block } } } Your demo says to invert it into this: void f(){ Element e=value; if(e!=null) return; if(collection.contains(e)){ // single block } } Weird. The compiler should skip the second if statement im both cases (assuming it fails the first one). Your approach does highlight a common topic- if the bools are dependent/ independent on the previous bool, then that should affect the nesting. Some benefits to this inversion: possibly saving memory (less localized variables), which helps performance a little. Modularization- it’s more organized (in your case). Personally, I think this technique might be compiler specific. I think we shouldn’t be worrying about our branching statements ~this much - again, they run in O(1), and aren’t the bottleneck of performance - so a lot of projects really wouldn’t benefit from making this change. I think what your teaching is really niche, and doesn’t really apply to many situations, where it benefits them - a lot of nested-if statements are inter-functional, and we can’t always adopt methods for control flow in them. I think youre tackling an “issue”, that isn’t an issue: why are we trying to make coding more complicated? (In your case, it is more readable- In my case, it is less readable). While I appreciate the very small amount of saved memory, I also think it’s important to recognize that the compiler might perform worse - transversals of if statements could affect its ability to optimize the cycle times of them.
This would be textbook case for "easier to ask forgiveness than permission" style in python? try: connect() except connection_error, payment_error, no_internet_error, user_not_online_exception: solve_the_problem
Four functions, each raising an exception or calling the next function? And why have multiple exceptions when you can do "raise connection_error("Please pay your bill")?
Now, as a bonus challenge, rewrite this code to comply with one of the strict industrial standard coding guidelines (the old MISRA standard comes to mind), where each function is allowed a single return path (no more, no less). Guard clauses are a great coding technique for avoiding indentation and keeping code readable. But early returns are an all-too-common source of bugs. In your example at 3:52 would work better with “elif” and “else” anyway.
This is fine if your conditions are prerequisites, and you can "fail fast". And I agree that reducing nesting is an admirable goal. But a lot of situations are more nuanced than this where conditions are not fail/success, and where you sometimes have to "unwind" yourself to clean up things when a failure does occur. Also, it's not good to fail "too quickly" as it's annoying when something tells me I have something wrong, I correct it, and then it tells me the next thing that's wrong when it could have told me about it in the first place.
Can't you just do: if not internet: print("No internet") elif not paid: print("user has not paid") else: print("You are online") it seems a lot more readable and it less lines of code
@@erik.... Because I like having one entry and one exit point, I think it's clearer. I understood the concept, I know it works, but years and years doing it another way is something hard to break.
@@moroboshidan7960 is it really clearer when several execution paths go over the whole function, and all but one of them (hopefully) without actually executing anything? With nested if...else blocks, or even an (already better) if...elif...else cascade you still have to scroll down to make sure that nothing else gets executed before the return. Deeply nested if...else constructs also have the disadvantage that you even have to scroll down just to see what happens in the 'else' case does (hopefully without losing the indentation level). Guard clauses with early return make it _much_ easier to reason about the code: If a precondition is not met you are _guaranteed_ that nothing happens (because the return is right there). That said: _after_ the guard clauses it's usually better to have only one more exit point. Early returns somewhere in the _middle_ of a function are a completely different thing; easy to miss, often very hard to reason about, and often also requiring cleanup to partial state changes before the return (which is a very common place for introducing bugs). Such early returns in the middle of a function are usually a sign that the function is doing too much and should be split up.
Can use a similar pattern when printing error messages except you just add text to a string. If the string has zero length after all the if-statements you run the function and return. Only requires one return. Alternatively a boolean flag that represents an error. Booleans are powerful when it comes to control the flow of the program.
if your going 3 or more deep i agree if statements make it more confusing. although nesting 2 or 3 IMO makes the code way more readable. it depends on the project though i guess
More than 1 nested layer (so total 2 conditional layers) is unreadable. Even if you don’t like the returns from guards and don’t want the else ifs from the other solution, you can still extract all that inner nested logic out to a function that just returns you something. You can even return an Enum that’s a range of values indicating if something had an error or if it was a success or if something else happened etc etc
Hi Man I have one question and I can´t find answer. I read temperature which is float number. I have some zone from -10 to 10. And when I break this zone from outside I want to make action. if temperature > -10: do someting. elif temperature < 10: Do someting. But what is my problem? When I run microcontroler and actual temperature is -5.5. So I need to know how to specify the barier that when I´m already inside zone from -10 to 10 to do nothing. And when I break zone from outside to iside do what I want. I hope it´s clear. Can you help me how to solve it? Thank you so much :)
What about creating helper functions for each "if"? E.g. check_connection(), check_payment(), etc that return a boolean. And then the go_online() function would look like: def go_online(): if all(check_connection(), check_payment(), check_internet()): print("You are online!") Would that work?
instead of doing multiple functions, you can make a single generator that handles all your checks. def go_online(): def checks(): yield is_connection_ok yield is_payment_ok yield is_internet_ok if all(checks()): print("You are online!") I'm not sure i would actually use it, but i'd still prefer to do this than slapping all method in the "all".
if not(connection and paid and internet and online): print 'Sorry there was a problem:', print 'there is no conection.'*(not connection), print "you did not pay." *(not paid), print "internet is not detected."*(not internet), print "not online."*(not online) else: print('connecting...')
Can you explain how to do that? I was wanting to do something like what you seem to be saying, but Python got angry with me. I've never coded in Python before so this was my first program: if not(connection and paid and internet and online): print 'Sorry there was a problem:', print 'there is no conection.'*(not connection), print "you did not pay." *(not paid), print "internet is not detected."*(not internet), print "not online."*(not online) else: print('connecting...')
Maybe it's me and my superior intelligence (not really) but I find very readable the if Elses in Python due to the tabulation. In other languages you must count parenthesis or look for where a closing braket startede, but in python you just see the ELIF code, and look up for the correspondent IF in the same column.
if not(connection and paid and internet and online): print 'Sorry there was a problem:', print 'there is no conection.'*(not connection), print "you did not pay." *(not paid), print "internet is not detected."*(not internet), print "not online."*(not online) else: print('connecting...')
A switch/case statement block would help here, but I doubt we'll ever see that in Python. There seems to be almost ideological opposition to it. One thing that I really welcomed when I started writing more Go code (despite a lot of issues where I wish Go had gone the Python route).
Since switch/case is just labels and gotos in disguise (and cannot be easily rewritten as if/elif internally, because of the fall-through capability) it will probably never be added to python. (And if you implemented the variant where each case only executes the associated code block, i.e. without requiring a 'break', then there's not really much difference to if/elif, so why bother in the first place.)
@@Bien100 see the end of my comment (the part in brackets). match/case in python is just if/elif written differently. It is _not_ a C-like implementation with fall through.
@@Bien100 Ugh. Impossible to keep up, especially when you work in corporate/prod environment where you have to stay backwards compatible. I'm sometimes still stuck with enforcing version 3.8.
“It's better to ask for forgiveness than to ask for permission” In other words, code only the happy path, and let caller deal with (implicitly raised) exceptions if something goes wrong.
Logically, these do not achieve quite the same thing, depending. If there is not an internet connection BECAUSE they haven’t paid, you would get no internet before fail to pay, for example. Even reversing the if statements without the function could allow you to improve the nesting situation.
Technically this is still good code as in it works and does the job. What it isn’t is manageable beyond a point. IMO good and bad can be subjective and some people prefer one style over another. And getting work done is always better than some fancy elegance no one can manage because it is too indented or too complex with jumps here and there to understand what is going on. Always should balance simplicity with management. Gift your future self
Excellent video! After watching your video Python makes more sense. Question? Originally i am familiar with JavaScript for a little over 1 year. Just switched to Python because I will be focused on backend for the Meta course. From your personal experience do you feel learning Python gave you a better understanding of programming if you came from another programming language? Trying to understand how Python could improve my JavaScript Skills, thank you.
From my personal experience, I can tell that it's good to switch from a language to another, cause when you do, you're able to better understand some specific concepts that in another language, maybe didn't make a lot of sense, so yes you can learn a lot from every language you learn :) (Excuse my English)
I'm not sure why Pythonistas avoid elif in cases like this. It's exactly why the switch/case statements are added to other languages. Someone else mentioned that old-school methods strongly favor a single return point (back to the days of hardware debuggers, I think - also mathematical proofs of function correctness), and tend to go there as well, but also readability for simple boolean checks like this. (Obviously doesn't really apply to more complex checks where the elif is working on different types of comparisons - not readable at all).
Elif would simply not answer the problematic of multiple conditions to check and do something specific to handle the result. Switch is now available in python 3.11 but even if it would be way cleaner to use a switch/case statement (given a bit of refactoring of the conditions in a single variable with an enum or something similar) it would not be really useful if you have multiple boolean statements that you need to check in a row in a single place in the code (simply not worth it to refactor in this case to have pattern matchable variable)
@@jonathanbereyziat4063in this case, you could use elif, together with the guards if not connection: ... elif not ...: ... else: print("...") und hier sind wieder alle
with an if...elif cascade you'd still have to make sure that the function doesn't do something after the last check before returning. With a guard clause you can be _certain_ that nothing unintentional can happen if the precondition is not met.
I mean, I'd use an if statement with &&/and to check every one of those. Unless I am in a situation where I can use return if certain conditions aren't met.
You could've done the same without defining a function.. just use if/elif/else statements with the same idea that you did inside that function (i.e. if not connected.. elif not paid.. etc.)
Instead of having a return command inside every if statement, couldn’t you turn them into elif statements? That way if one executes, the rest are skipped, no return command needed. Then at the end have an “else” statement that confirms you are online if none of the other elif statements trigger .
what if my condition has 3 possible responses, such as if this is in this category, say this, if it is in this category say this, if it is in that category say that.
@Indently Ohh im so sorry now i watched the video and understood the concept. And i was not trying to write this comment in a criticism-like way, i was making this Comment jokingly... again im so sorry
Your Python "not" implementation is just another variation of the if ... else newbie programming. I want you to think about this from the user's perspective: the user will get more and more frustrated with this program, because as soon as he or she fixes one issue, another will crop up. The insight here is to gather all the things which are wrong and inform the user at once about all of them.
def check_status(connection, paid, internet, online): if not connection: return 'No connection...' if not paid: return 'User has not paid...' if not internet: return 'No internet...' if not online: return 'You are offline' return 'You are online!' # Example usage: connection = True paid = True internet = True online = True status_message = check_status(connection, paid, internet, online) print(status_message)
At 3:11, you just demonstrate a careless mistake using guard clause pattern, and make everyone "online". A better version (and faster by skipping the second if statement if there is no connection ) should be using elif, like below. >>> if not connection: ... print('no connection') ... elif not paid: ... print('not paid') ... elif not internet: ... print('no internet') ... elif not online: ... print('offline') ... else: ... print('You are online') ...
I m not a programmer, but using lists or dictionaries couldn't be even better, like this: connection=False paid=True internet=False online=True l=[ ( connection, 'Your connection is on', 'Your connection is off'), (paid, 'You have paid', 'You haven\'t paid'), (internet, 'No connection', 'Internet has offline'), (online, 'You are online', 'You aren\'t online')] for k,z,x in l: if k == True: print(f'{z}') else: print(f'{x}') Could you comment this code? TIA
the complexity of this code is way to high. and this code don't have the same logic as the example. With the example, the logic are "if all condition met, do something. if not print the correct error message"
@@ArimasArtadiThank you very much, now, indeed, it is returning better results. Some answers are quite precise, few mistakes and other are very funny, like this: "Try to find the word Saturn in Aristotle's Physic , if you can't find it, print the correct error message." Brad: The word "Saturn" is not used in Aristotle's Physics. Here is the error message: **Error:** The word "Saturn" is not used in Aristotle's Physics. I apologize for the inconvenience. I am still under development and learning to perform many kinds of tasks, including finding words in text. I will try my best to avoid making similar mistakes in the future. I would also like to add that Aristotle's Physics was written in the 4th century BC, and Saturn was not discovered until the 17th century AD. Therefore, it is not surprising that Aristotle does not mention Saturn in his Physics." If you have more tips or some indication to share, @Arimas, please do it. Thank you very much.
Why? I would somewhat agree for a function that returns a value: having too many exit points could indicate that a dictionary lookup would be a better pattern. But guard clauses seem especially useful in procedures (functions that return void). What's the problem with having early return when it isn't returning a value anyway and is only control flow?
electricity = 1 internet = 1 laptop_charged = 1 website_working = 1 while 1: if not electricity: print('No electricity') break else: print('Electricity is available') if not internet: print('but no internet') break else: print('internet is available') if not laptop_charged: print('but laptop not charged') break else: print('laptop charged') if not website_working: print('but website not working') break else: print('website working') print("Transaction can be done") break
def mult_checks(check_dict: dict[bool]) -> bool: """ go through all items in dictionary making sure they are True """ checks = all(list(check_dict.values())) # Passed if checks: print('You are online...') return True # Failed for k, v in check_dict.items(): if not v: print(f'{k} Failed!') return False mult_checks({'online':True, 'paid': True, 'Internet': False})
@@wartemNit picking here, but the precise reason why it doesn’t need the list constructor is not because the values method returns a list, but that the all function takes any iterable. Edit: The return type of the values method isn’t exactly a list. It’s dict_values on Python 3.8.
You know your code's bad when it looks like HTML but isn't HTML
got the whole squad laughing
😐
JSX💀
lol
😂
Applied this to my pytho script and this changes the looks of my code 180 degrees. Thanks a lot for this little tuto. Here is your like and comment buddy
I used to do a lot of nesting of if statement, but that was because I had read and had been taught it was bad to have more than one return statement per function.
else/if (elif) should solve the issue without having many return values. There is an example in another comment.
Personally I think one or two guard clause are acceptable, three start to hurt readability and more can be as confusing as the alternative, because it's not easy to track below which variables are relevant and what are their values.
Another alternative could be to do the validation in another function, especially if you need to do significant work in your main branch.
As always it's a balancing act. Good quality code mainly should contain no unexpected surprises.
A block of guard clauses at the top of a function is pretty straightforward and easy to follow, hence the early returns there aren't an issue. They actually make it _easier_ to reason about the code, because you know that you don't have to worry about the rest of the function - you just returned from it - whereas an if...elif...else cascade might still execute code somewhere further down the line.
What's more problematic are early returns somewhere in the middle of a function. These are easier to miss, and require more reasoning about if/when/how they might get executed. Also at this point there are often already changes made to the program state which might need to be reverted before exiting.
Early returns in the middle of a function are usually an indicator that the function is doing too much and should be split up.
This is in my opinion the main characteristic of a "guard clause": it _prevents_ any state change if the _preconditions_ for the function to work are not met.
This is correct behaviour in languages like C where you have to do your own garbage collection. It's not a problem with Python. But it's probably good practice to look at nested conditions after you've written them, to see if any optimisation can be done, regardless of the language
@@apmcd47 I'm not just talking about garbage collection, but any (partial) state change.
A return in the middle of a function means that there is code that _does_ something before it, and there is also code that _would_ do more after it. Whatever that "something" is, it might have changed the state of the program (or even the system). Maybe it's just e.g. an empty file that was created but never written to, but without analyzing the function code you'll never know if it wasn't something more intricate.
Hence having returns only at the very beginning (guard clauses) and the very end (single exit point) makes it easier to reason about the program. Because then you know that it's "all or nothing".
@@stephanweinberger I was replying to the original post in this thread, not your reply
This is also called inversion of your if statements. handle the sad paths first by inverting the statements, this forces the sad paths to the top
No it's not.
It's not much different from inverting if statements in terms of functionality, but conceptually his guard clauses are very different.
Personally I'm wondering why he didn't even mention the inverted if pattern and the way it makes elif an easy way to avoid nesting.
Having a return in a guard clause is an invitation to spaghetti land.
@@nialltracey2599When done well, it reduces cognitive load on the reader, as the code is working on a more restrictive set of conditions as you go downward, without nesting.
@@eryqeryq Except the same claim is made about single return statement per procedure -- that it reduces cognitive load. It does this by not forcing the reader to keep every execution path in. But the problem is that every coding paradigm claims to be better because X, Y, Z.
To me, the problem is that we're still working in plain-text source code. People keep fighting over whether guard clauses or throwing exception is superior, but it's all cruft.
Guard clauses are supposed to improve cognitive load by eliminating all error cases and edge cases so that you don't have to think of them in your code, which they do (I personally use guard clauses myself and do the thing of multiple return clauses in many of my procedures... but then again, I love spaghetti in most flavours of sauce.
If we weren't doing plain-text source code, we could hide the guard clauses as preconditions for the procedure call. That way, we wouldn't have to look at them at all until and unless a new error case arose.
Now *that* would **really** reduce cognitive load.
Hi thank you for another good tutorial and please take this as positive critism. I agree with you about the issue of reducing else statements, however I dont agree with your suggested solution, you have unnecessary return statements which could be avoided using `elif` statements instead.
Also I generally would have prefered one function call to print, here is my recommended solution for this:
def go_online():
message = 'You are online'
if not connection:
message = 'No connection...'
elif not paid:
message = 'User has not paid...'
elif not internet:
message = 'No Internet...'
print(message)
Sure, but what about if you need to be doing something other than printing a string?
I think you're missing the point, the early returns are intentional and pretty critical to the role that guard clauses play.
Consider a different scenario, with a function that reads and returns a value from a database, but it should only do so for someone with admin access. In that case, you could use a guard clause to check if the user doesn't have admin access, and if so, return an error message so it doesn't proceed, because you don't want the function to continue running once you've determined that the user is not an admin.
So technically yes, it would be possible to achieve the desired goal for the particular function demonstrated in this video without doing early returns, but early returns are a feature, not a bug, of guard clauses. I think a different example function, or better yet, multiple example functions, would have made it clearer in the video.
Your both right and I am well aware what a guard clause is, but I was pointing out that it's irrelevant for the expressed example as you could have used else if statements to get the same outcome, which would have avoided multiple redundant return statements and make the code look cleaner in my opinion.
But yes a guard clause (or what I often refer to as "early return") statement is far better when you have a conditional expression to end the progression of a function earlier.
Yep, is this how to code an if-else ladder. In C you'd be declaring variables in the inner blocks, to keep them closest to where they're used. Can't do that if you just bail out with a return.
2:22 Instead of "return", why not use elifs?
As an alternative to returning, you can also use ‘elif’.
if not connection:
….
elif not paid:
….
This will have similar functionality, except instead of returning, it jumps down to the bottom of the if-elif-else block.
Personally, I do just used the return , but there are programmers who don’t like the idea of early returns.
Personally in this case I would use a variable called message (or msg), setting it as I go through the various conditions.The last two lines would be to print the message and return. Even better, by presetting the message to "You are online" and testing only for offline you don't need any else clauses at all! For this scenario.
@@apmcd47As you said, for this scenario, that works for this simple example which just prints a string, but there are usually lots of code and more complicated checks involved real programs. In those cases, the elif construction can also help.
@@apmcd47 Now you've introduced _additional_ complexity (and memory consumption, and execution time) just to return a constant.
@@stephanweinberger Your opinion. I did say for this specific case.
@@apmcd47 it's not really an opinion when you are adding more memory consumption and execution time.
Good knowledge. Enough content to fill one minute video only, though.
I don’t usually run into this issue. Usually it’s something like:
void f(){
Element e=value;
if(e != null){
if(collection.contains(e)){
// single block
}
}
}
Your demo says to invert it into this:
void f(){
Element e=value;
if(e!=null)
return;
if(collection.contains(e)){
// single block
}
}
Weird.
The compiler should skip the second if statement im both cases (assuming it fails the first one). Your approach does highlight a common topic- if the bools are dependent/ independent on the previous bool, then that should affect the nesting.
Some benefits to this inversion: possibly saving memory (less localized variables), which helps performance a little. Modularization- it’s more organized (in your case).
Personally, I think this technique might be compiler specific. I think we shouldn’t be worrying about our branching statements ~this much - again, they run in O(1), and aren’t the bottleneck of performance - so a lot of projects really wouldn’t benefit from making this change. I think what your teaching is really niche, and doesn’t really apply to many situations, where it benefits them - a lot of nested-if statements are inter-functional, and we can’t always adopt methods for control flow in them. I think youre tackling an “issue”, that isn’t an issue: why are we trying to make coding more complicated? (In your case, it is more readable- In my case, it is less readable). While I appreciate the very small amount of saved memory, I also think it’s important to recognize that the compiler might perform worse - transversals of if statements could affect its ability to optimize the cycle times of them.
I can't thank you enough, keep these amazing videos coming please!
Can you do a quick follow-up video to check time efficiency?
This would be textbook case for "easier to ask forgiveness than permission" style in python?
try: connect()
except connection_error, payment_error, no_internet_error, user_not_online_exception: solve_the_problem
Four functions, each raising an exception or calling the next function? And why have multiple exceptions when you can do "raise connection_error("Please pay your bill")?
Now, as a bonus challenge, rewrite this code to comply with one of the strict industrial standard coding guidelines (the old MISRA standard comes to mind), where each function is allowed a single return path (no more, no less).
Guard clauses are a great coding technique for avoiding indentation and keeping code readable. But early returns are an all-too-common source of bugs.
In your example at 3:52 would work better with “elif” and “else” anyway.
Easy, set a variable msg in each of the "if not" conditions, than print msg at the end then return
I find that basic solutions are often the best solutions🙌
This is fine if your conditions are prerequisites, and you can "fail fast". And I agree that reducing nesting is an admirable goal. But a lot of situations are more nuanced than this where conditions are not fail/success, and where you sometimes have to "unwind" yourself to clean up things when a failure does occur. Also, it's not good to fail "too quickly" as it's annoying when something tells me I have something wrong, I correct it, and then it tells me the next thing that's wrong when it could have told me about it in the first place.
Can't you just do:
if not internet:
print("No internet")
elif not paid:
print("user has not paid")
else:
print("You are online")
it seems a lot more readable and it less lines of code
Ig thats what he did, here he made a function instead
What is really cool, you made ~2 minutes topic somehow into 8minutes. That's real skillz.
Something even more cool, is that you can half that time by setting the playback speed to 2x on TH-cam :)
I have a bit of a resistance for using more than one return into a function.
Why? That doesn't make any sense.
@@erik.... Because I like having one entry and one exit point, I think it's clearer.
I understood the concept, I know it works, but years and years doing it another way is something hard to break.
@@moroboshidan7960 is it really clearer when several execution paths go over the whole function, and all but one of them (hopefully) without actually executing anything?
With nested if...else blocks, or even an (already better) if...elif...else cascade you still have to scroll down to make sure that nothing else gets executed before the return. Deeply nested if...else constructs also have the disadvantage that you even have to scroll down just to see what happens in the 'else' case does (hopefully without losing the indentation level).
Guard clauses with early return make it _much_ easier to reason about the code: If a precondition is not met you are _guaranteed_ that nothing happens (because the return is right there).
That said: _after_ the guard clauses it's usually better to have only one more exit point. Early returns somewhere in the _middle_ of a function are a completely different thing; easy to miss, often very hard to reason about, and often also requiring cleanup to partial state changes before the return (which is a very common place for introducing bugs).
Such early returns in the middle of a function are usually a sign that the function is doing too much and should be split up.
@@moroboshidan7960well, don't be taught bad things from bad schools
Can use a similar pattern when printing error messages except you just add text to a string. If the string has zero length after all the if-statements you run the function and return. Only requires one return. Alternatively a boolean flag that represents an error. Booleans are powerful when it comes to control the flow of the program.
So multiple returns is better than nested if?
What about making matrices instead?
if your going 3 or more deep i agree if statements make it more confusing. although nesting 2 or 3 IMO makes the code way more readable. it depends on the project though i guess
True, always depends on the scenario :)
More than 1 nested layer (so total 2 conditional layers) is unreadable.
Even if you don’t like the returns from guards and don’t want the else ifs from the other solution, you can still extract all that inner nested logic out to a function that just returns you something.
You can even return an Enum that’s a range of values indicating if something had an error or if it was a success or if something else happened etc etc
3 nested if is readable for you?? You have robot eyes? We use this guard pattern so that it is easier to read and maintain for the other developers.
Hi Man I have one question and I can´t find answer. I read temperature which is float number. I have some zone from -10 to 10. And when I break this zone from outside I want to make action. if temperature > -10: do someting. elif temperature < 10: Do someting. But what is my problem? When I run microcontroler and actual temperature is -5.5. So I need to know how to specify the barier that when I´m already inside zone from -10 to 10 to do nothing. And when I break zone from outside to iside do what I want. I hope it´s clear. Can you help me how to solve it? Thank you so much :)
Have you tried to use = to solve your problem?
You can use >= -10 for the lower boundary and , using elifs.!
I always use this way nowadays to get rid of unnecessary intendation. I call it the "return early" pattern.
Great tip. Much cleaner and readable.
What about creating helper functions for each "if"? E.g. check_connection(), check_payment(), etc that return a boolean. And then the go_online() function would look like:
def go_online():
if all(check_connection(), check_payment(), check_internet()):
print("You are online!")
Would that work?
at that point you might aswell just check the variables rather than using functions that return a boolean
You could do that, but then you wouldn't know where a potential problem with the connection lies.
instead of doing multiple functions, you can make a single generator that handles all your checks.
def go_online():
def checks():
yield is_connection_ok
yield is_payment_ok
yield is_internet_ok
if all(checks()):
print("You are online!")
I'm not sure i would actually use it, but i'd still prefer to do this than slapping all method in the "all".
Sure, but this fragments your code with higher order functions for something you could easily leave inline
if not(connection and paid and internet and online):
print 'Sorry there was a problem:',
print 'there is no conection.'*(not connection),
print "you did not pay." *(not paid),
print "internet is not detected."*(not internet),
print "not online."*(not online)
else:
print('connecting...')
Indently urging us not to indent... irony.
It is way more efficient to use Enums and byte flags + byte shifting to handle this, more readable and 0 if/else statements.
Can you explain how to do that? I was wanting to do something like what you seem to be saying, but Python got angry with me. I've never coded in Python before so this was my first program:
if not(connection and paid and internet and online):
print 'Sorry there was a problem:',
print 'there is no conection.'*(not connection),
print "you did not pay." *(not paid),
print "internet is not detected."*(not internet),
print "not online."*(not online)
else:
print('connecting...')
Also useful if you need to add another condition later on in an update. 😊
Maybe it's me and my superior intelligence (not really) but I find very readable the if Elses in Python due to the tabulation. In other languages you must count parenthesis or look for where a closing braket startede, but in python you just see the ELIF code, and look up for the correspondent IF in the same column.
The same effect of "return" in the guard method can be replicated in the main code using "if" and "break" to avoid nested "else".
Does break work outside loops?
I like to make those statements one liners
if not connection: return print("No connection")
if not(connection and paid and internet and online):
print 'Sorry there was a problem:',
print 'there is no conection.'*(not connection),
print "you did not pay." *(not paid),
print "internet is not detected."*(not internet),
print "not online."*(not online)
else:
print('connecting...')
A switch/case statement block would help here, but I doubt we'll ever see that in Python. There seems to be almost ideological opposition to it. One thing that I really welcomed when I started writing more Go code (despite a lot of issues where I wish Go had gone the Python route).
Since switch/case is just labels and gotos in disguise (and cannot be easily rewritten as if/elif internally, because of the fall-through capability) it will probably never be added to python.
(And if you implemented the variant where each case only executes the associated code block, i.e. without requiring a 'break', then there's not really much difference to if/elif, so why bother in the first place.)
Since Python 3.10 Switch/Case is available but called Match/Case 😊
@@Bien100 see the end of my comment (the part in brackets).
match/case in python is just if/elif written differently. It is _not_ a C-like implementation with fall through.
@@Bien100 Ugh. Impossible to keep up, especially when you work in corporate/prod environment where you have to stay backwards compatible. I'm sometimes still stuck with enforcing version 3.8.
If you're doing a small script, you could also use `exit()` to stop the program
That's a great way to make the code short and concise! Now, if we could just invent a way to make videos short and concise...
never knew this is called a guard clause. i do this all the time because white space is an anti pattern. makes code too hard to read
What is the theme setup used in this video?
Can anyone tell me why did he used a function but not wrote only ifs
“It's better to ask for forgiveness than to ask for permission”
In other words, code only the happy path, and let caller deal with (implicitly raised) exceptions if something goes wrong.
What's the ide name?
Just to clarify, “God clauses” or “guard clauses”?
Is there any way of getting switch case from c# 😂
Missed the chance to also show people the match-case in python, as that is the next logical thing that a dev needs to know.
Match case is a completely other topic and is not a replacement for if else though.
Logically, these do not achieve quite the same thing, depending. If there is not an internet connection BECAUSE they haven’t paid, you would get no internet before fail to pay, for example.
Even reversing the if statements without the function could allow you to improve the nesting situation.
Technically this is still good code as in it works and does the job. What it isn’t is manageable beyond a point.
IMO good and bad can be subjective and some people prefer one style over another. And getting work done is always better than some fancy elegance no one can manage because it is too indented or too complex with jumps here and there to understand what is going on. Always should balance simplicity with management. Gift your future self
What about elif?
Excellent video! After watching your video Python makes more sense.
Question?
Originally i am familiar with JavaScript for a little over 1 year. Just switched to Python because I will be focused on backend for the Meta course.
From your personal experience do you feel learning Python gave you a better understanding of programming if you came from another programming language? Trying to understand how Python could improve my JavaScript Skills, thank you.
From my personal experience, I can tell that it's good to switch from a language to another, cause when you do, you're able to better understand some specific concepts that in another language, maybe didn't make a lot of sense, so yes you can learn a lot from every language you learn :)
(Excuse my English)
I do this also inside of loops, instead of breathing l nesting i just break or continue
I'm not sure why Pythonistas avoid elif in cases like this. It's exactly why the switch/case statements are added to other languages. Someone else mentioned that old-school methods strongly favor a single return point (back to the days of hardware debuggers, I think - also mathematical proofs of function correctness), and tend to go there as well, but also readability for simple boolean checks like this. (Obviously doesn't really apply to more complex checks where the elif is working on different types of comparisons - not readable at all).
Elif would simply not answer the problematic of multiple conditions to check and do something specific to handle the result. Switch is now available in python 3.11 but even if it would be way cleaner to use a switch/case statement (given a bit of refactoring of the conditions in a single variable with an enum or something similar) it would not be really useful if you have multiple boolean statements that you need to check in a row in a single place in the code (simply not worth it to refactor in this case to have pattern matchable variable)
@@jonathanbereyziat4063in this case, you could use elif, together with the guards
if not connection:
...
elif not ...:
...
else:
print("...")
und hier sind wieder alle
with an if...elif cascade you'd still have to make sure that the function doesn't do something after the last check before returning. With a guard clause you can be _certain_ that nothing unintentional can happen if the precondition is not met.
I mean, I'd use an if statement with &&/and to check every one of those. Unless I am in a situation where I can use return if certain conditions aren't met.
yes that would do in other example, but you won't get the exact messages
How are you going to return the exact error messages if one of the variables is false?
@@m.moonsie You know what, that's a fair argument.
Ahhh yes replace if statments with replace it with if statements without else that's fire 🔥 🔥🔥
this really getting compact with those conditions 🤟🏾 me too not a fan of nested condition ,What if dependency b/w condition any idea ,
You could've done the same without defining a function.. just use if/elif/else statements with the same idea that you did inside that function (i.e. if not connected.. elif not paid.. etc.)
And statement has left the chat:
What about using np.select() ?
Please share an example
THANK YOU FOR THIS VIDEO!❤
LOL! Here 3:11 is why to not do that: "And I forget to return..."
God clause?
I, guard clause Swift has this.
Instead of having a return command inside every if statement, couldn’t you turn them into elif statements?
That way if one executes, the rest are skipped, no return command needed.
Then at the end have an “else” statement that confirms you are online if none of the other elif statements trigger .
Huh. Somehow, I only now noticed that I kinda thaught this to myself without realizing.
This is amazing
thank you
Pattern matching is much cleaner.
But is it easy for people to understand?
Nice! Is this a design pattern?
The guard clause pattern was something I would see more in Swift to keep code clean. In Python it really depends on where you use it :)
good vids. concise..
What we see here is not the problem of nesting ifs but the the biggest design flaw of Python: the lack of block closing symbol.
Thank you.
I just did not know the name of pattern but I use it a lot...
Be a never-nester
There are dozens of us. I think.
never have to nest when you write it all in assembly
Multiples returns inside function/class or anything else is a bad practice!
Ahh yes, the yandev indentation.
Or use state machines
I keep hearing god clause...
what if my condition has 3 possible responses, such as if this is in this category, say this, if it is in this category say this, if it is in that category say that.
Why isnt my buddies `and` and `all` here!??
Please pay attention to the concept of the video, not the example, because the example I created is for demonstration purposes only.
@Indently Ohh im so sorry now i watched the video and understood the concept. And i was not trying to write this comment in a criticism-like way, i was making this Comment jokingly... again im so sorry
No worries ahah. I appreciate the humour in the comments, so don’t stop :)
Your more readable solution is longer.
Not as long as mine though. Mine is the longest
dam not bad, nice vid
Yandev be like: we don’t do that here
Your Python "not" implementation is just another variation of the if ... else newbie programming. I want you to think about this from the user's perspective: the user will get more and more frustrated with this program, because as soon as he or she fixes one issue, another will crop up. The insight here is to gather all the things which are wrong and inform the user at once about all of them.
def check_status(connection, paid, internet, online):
if not connection:
return 'No connection...'
if not paid:
return 'User has not paid...'
if not internet:
return 'No internet...'
if not online:
return 'You are offline'
return 'You are online!'
# Example usage:
connection = True
paid = True
internet = True
online = True
status_message = check_status(connection, paid, internet, online)
print(status_message)
good
Subscribed
So programming should be more like the sciencetific method; not proving, but excluding... go figure. :-)
At 3:11, you just demonstrate a careless mistake using guard clause pattern, and make everyone "online". A better version (and faster by skipping the second if statement if there is no connection ) should be using elif, like below.
>>> if not connection:
... print('no connection')
... elif not paid:
... print('not paid')
... elif not internet:
... print('no internet')
... elif not online:
... print('offline')
... else:
... print('You are online')
...
No, I think creating a dictionary is a better option.
Speaking of being concise, this video could've been 1/4 as long.
I m not a programmer, but using lists or dictionaries couldn't be even better, like this:
connection=False
paid=True
internet=False
online=True
l=[ ( connection, 'Your connection is on', 'Your connection is off'),
(paid, 'You have paid', 'You haven\'t paid'),
(internet, 'No connection', 'Internet has offline'),
(online, 'You are online', 'You aren\'t online')]
for k,z,x in l:
if k == True:
print(f'{z}')
else:
print(f'{x}')
Could you comment this code?
TIA
the complexity of this code is way to high.
and this code don't have the same logic as the example.
With the example, the logic are "if all condition met, do something. if not print the correct error message"
@@ArimasArtadiThank you very much, now, indeed, it is returning better results.
Some answers are quite precise, few mistakes and other are very funny, like this:
"Try to find the word Saturn in Aristotle's Physic , if you can't find it, print the correct error message."
Brad:
The word "Saturn" is not used in Aristotle's Physics.
Here is the error message:
**Error:** The word "Saturn" is not used in Aristotle's Physics.
I apologize for the inconvenience. I am still under development and learning to perform many kinds of tasks, including finding words in text. I will try my best to avoid making similar mistakes in the future.
I would also like to add that Aristotle's Physics was written in the 4th century BC, and Saturn was not discovered until the 17th century AD. Therefore, it is not surprising that Aristotle does not mention Saturn in his Physics."
If you have more tips or some indication to share, @Arimas, please do it. Thank you very much.
This is not specific to python
Yeah but this syntax is
Ew... I was taught that early returns are baaad.
Why? I would somewhat agree for a function that returns a value: having too many exit points could indicate that a dictionary lookup would be a better pattern.
But guard clauses seem especially useful in procedures (functions that return void). What's the problem with having early return when it isn't returning a value anyway and is only control flow?
It's the opposite of bad. I'm curious who taught you that?
Birds build nests. I like birds. However, birds always code in binary. Thanks for the video.
electricity = 1
internet = 1
laptop_charged = 1
website_working = 1
while 1:
if not electricity:
print('No electricity')
break
else:
print('Electricity is available')
if not internet:
print('but no internet')
break
else:
print('internet is available')
if not laptop_charged:
print('but laptop not charged')
break
else:
print('laptop charged')
if not website_working:
print('but website not working')
break
else:
print('website working')
print("Transaction can be done")
break
Code damage is minor problem... I think that jumping from statement to variable to statement to function in memory can damage ram
Do you mind sharing more on this topic? I would like to hear some examples :)
@@Indently no... because i made that up. Though it is possible to reduce the ram lifetime by overheating it.
@@josipdrazin6708 if poor code causes your ram to overheat, you have bigger problems
我也不赞同他的这种写法,这种写法看似简洁,当情况更复杂时,return分支变多时,结构也就更混乱,逻辑也越不清晰。我见过那种代码,很难读。
def mult_checks(check_dict: dict[bool]) -> bool:
""" go through all items in dictionary
making sure they are True """
checks = all(list(check_dict.values()))
# Passed
if checks:
print('You are online...')
return True
# Failed
for k, v in check_dict.items():
if not v:
print(f'{k} Failed!')
return False
mult_checks({'online':True, 'paid': True, 'Internet': False})
Nice.
check_dict.values() already returns a list. No need to use the list constructor on it.
@@wartem thanks! That's even cleaner
@@wartemNit picking here, but the precise reason why it doesn’t need the list constructor is not because the values method returns a list, but that the all function takes any iterable.
Edit: The return type of the values method isn’t exactly a list. It’s dict_values on Python 3.8.
@@csbnikhil That's true. The return type is 'dict_values'. The view object contains the values of the dictionary, as a list.