#πŸ”’ I really need help with a small piece of code

229 messages Β· Page 1 of 1 (latest)

hollow glacier
#
time_split = time_input.split(":")


def is_time_valid(time_str: str) -> bool:
    hours = len(time_str[0])
    minutes = len(time_str[1])
    if time_str[0].isdigit() and time_str[1].isdigit():
        if hours == 2 and int(time_str[0]) <= 23 and minutes == 2 and int(time_str[1]) <= 59:
            joined = ":".join(time_str)
            print(f"Start time: {joined}")
            return True
        else:
            print("Invalid time")
            return False
    else:
        print("Invalid time")
        return False
        
while True:
    if is_time_valid(time_split):
        break ```

I am a beginner in python by the way,
so basically this asks the user to input a time in the format HH:MM, but for some reason when it is invalid (so 9:04 for example) it keeps on looping "invalid time" instead of just once. Does anybody know why?
gritty bearBOT
#

@hollow glacier

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

hearty idol
#
def is_time_valid(time_str: str) -> bool:
    hours = time_str[0]
    minutes = time_str[1]
    
    # Check if hours and minutes are valid digits and lengths
    if hours.isdigit() and minutes.isdigit():
        if len(hours) == 2 and int(hours) <= 23 and len(minutes) == 2 and int(minutes) <= 59:
            joined = ":".join(time_str)
            print(f"Start time: {joined}")
            return True
        else:
            print("Invalid time")
            return False
    else:
        print("Invalid time")
        return False

while True:
    time_input = input("Please enter a time (HH:MM): ")
    time_split = time_input.split(":")
    
    if len(time_split) == 2 and is_time_valid(time_split):
        break

#

This issue was with your time checking logic

hollow glacier
#

Could you maybe explain it a little more in depth? I am still really confused by the looping stuff

hearty idol
#
hours = len(time_str[0])
minutes = len(time_str[1])
#

This part of code is your culprit

#

See, what you need to do is split the time in two parts from colon.

str.split() function of you is handling that properly and storing it as list of string

#

You're checking how many characters are in the hour part (time_str[0]) and the minute part (time_str[1]). For example:

If the user enters 9:04, time_str[0] (hours) is "9", and time_str[1] (minutes) is "04".

So len(time_str[0]) is 1 because the hour is just "9" (not "09"), and len(time_str[1]) is 2 because "04" is two characters.

Now, your condition says that the hour must have exactly 2 characters and the minute must also have exactly 2 characters. So when it sees 9:04, it doesn't work because 9 has only 1 character. This is why it's always saying "Invalid time" when you input something like 9:04.

hollow glacier
#

Ahhh, I see

#

Thanks a lot for your help

lament bay
#

why not do the split and the all the checking inside the function instead and only keep this outside of the function?

while True:
    time_input = input("Please enter a time (HH:MM): ")    
    if is_time_valid(time_input):
        break
#

it would also be advisable to keep printing out of the function to make it more reusable

hollow glacier
lament bay
# hollow glacier Is that better?

to demonstrate how it could look if doing it that way
the function could be this simple and small

def is_time_valid(timestamp: str) -> bool:
    if ":" not in timestamp:
        return False

    hours, minutes = timestamp.split(":", 1)
    if hours.isdigit() and minutes.isdigit() and len(hours) == 2 and len(minutes) == 2 and int(hours) <= 23 and int(minutes) <= 59:
        return True
    return False
```but it can be hard to read such long lines, so it might be better to format it on a few more line like:
```py
def is_time_valid(timestamp: str) -> bool:
    if not ":" in timestamp:
        return False

    hours, minutes = timestamp.split(":", 1)
    if (
        hours.isdigit()
        and minutes.isdigit()
        and len(hours) == 2
        and len(minutes) == 2
        and int(hours) <= 23
        and int(minutes) <= 59
    ):
        return True
    return False
```to make the logic a easier to read and understand
then when calling the function you could do
```py
while True:
    start_time = input("Please enter a time (HH:MM): ").strip()
    if is_time_valid(start_time):
        print(f"Start time: {start_time}")
        break
    print("Invalid time")
#

this way you can even ask for the end time before printing the start_time, as you can do that after both getting a valid start_time and end_time by just moving the print() statement that prints the start time to after the two loop for getting the times

hollow glacier
#

Oh wow that is much easier to read

#
while True:
    start_time = input("Please enter a time (HH:MM): ").strip()
    end_time = input("Please enter a time (HH:MM): ").strip()
    if is_time_valid(start_time) and is_time_valid(end_time):
        print(f"Start time: {start_time}")
        print(f"Start time: {end_time}")
        break
    print("Invalid time")

I would do this for the end time right?

lament bay
#

it's also fully reusable and customizable if you want different error messages for the two time stamps, for example

while True:
    start_time = input("Please enter a start time (HH:MM): ").strip()
    if is_time_valid(start_time):
        break
    print("Invalid start time")

while True:
    end_time = input("Please enter an end time (HH:MM): ").strip()
    if is_time_valid(end_time):
        break
    print("Invalid end time")

print(f"Start time: {start_time}")
print(f"End time: {end_time}")
hollow glacier
#

Ahhh alright

#

thanks a lot for your help

#

Never knew that you could make the long if statement so easily readable

lament bay
#

oops, had a mistake in there that i have now corrected

hollow glacier
#

Also,

#

Do you have a suggestion on how to subtract the end time and start time from each other correctly?

#

for example 11:05 and 09:05 becomes 02:00

lament bay
#

if you are not allowed to use functions from the datetime module/library you would have to do it with some math

hollow glacier
#

I have no clue what the datetime module is, so i definitely am not allowed no

#

tried to use regular expressions in the first place for this but that isnt allowed either unfortunately

lament bay
#

make function that can convert the time stamps to a total number of minutes that the timestamp represents and then just take the end minus the start and then get the duration in the number of minues and have another function that converts the number of minuts back to a proper time stamp in hours and minutes

hollow glacier
#

ahh

#

so just split the two times?

#

and convert them to integers

lament bay
#

usually one does the above with seconds, but since you don't concern yourself with seconds you can work in minutes instead

hollow glacier
#

Right

lament bay
hollow glacier
#

does python recognize 11 - 09 to be 02?

lament bay
#

as each hour is 60 minutes you only have to take the hours * 60 + minutes

hollow glacier
#

or would i have to do that myself

lament bay
#

you would need to convert them both to integers before doing the calculation

hollow glacier
lament bay
#

because then you can just do end - start and get the duration in minutes, then convert the minutes to hours and minutes again

hollow glacier
#

right

#

so if the start time were to be 09:05 id have to do

start_time_split = start_time.split(":")
start_time_int = int(start_time_split)

start_time_int[0] * 60 + start_time_int[1]

or is this incorrect

lament bay
hollow glacier
#

I have seen map fly by when I was trying to fix it myself but I have no clue what it does no

#

does int(start_time_int[0]) work?

lament bay
#

so, you are allowed to use it?
it's one of the python build-ins, so nothing to import to be able to use it

hollow glacier
lament bay
hollow glacier
#

ahh okay

lament bay
#

int() doesn't change the value of the variable, it returns the result that you then can do something with

#

like assign it back to the same or another variable

hollow glacier
#
start_time_split = start_time.split(":")
start_hours = int(start_time_split[0])
start_minutes = int(start_time_split[1])

#

like this?

#

or would i have to manually use int(start_time_split[0] for it to work

lament bay
#

as this is a function you probably want to keep variable names neutral to reuse the function between both start_time and end_time for example

#

but yeah, more or less

hollow glacier
#

by the way, I really appreciate all the help. I wouldve given up by now if i were on my own

lament bay
#

as it is a function the variable can be named something other then the variable that you called it with

hollow glacier
#

ohhhhh

#

right I forgot that it was a function

lament bay
#

look at the example above where i used the same validation function for both start_time and end_time

hollow glacier
#

def time_math(time_change):
  time_split = time_change.split(":")
  time_int = int(time_split)

def time_math(time_change):
 time_split = time_change.split(":")
 time_int_hours = int(time_split[0)
 time_int_minutes = int(time_split[1])

#

would either of these be correct?

lament bay
#

the best way to know is if you write the code and try it
if it's a long script you can make a new .py file and just have the minimal code that you want to try and use a string that you set to a variable instead of using input() in such code that you just want to try out different things in

#

we can try it here in the chat

hollow glacier
#

it is a very long messy script now yeah

#

not that long now i look at it

#
#Functions

def is_first_name_valid(name: str) -> bool:
    if name.isalpha() and len(name) > 2 and name[0].isupper():
        return name
    else:
        print("Invalid input")


def is_last_name_valid(name: str) -> bool:
    if name.isalpha() and len(name) > 2 and name[0].isupper():
        return name
    else:
        print("Invalid input")


while True:
    first_name = input("Enter your first name")
    if is_first_name_valid(first_name):
        break

while True:
    last_name = input("Enter your last name")
    if is_last_name_valid(last_name):
        break

#Testing this version out.
def is_time_valid(time_str: str) -> bool:
    if not ":" in time_str:
        return False

    hours, minutes = time_str.split(":", 1)
    if hours.isdigit() and minutes.isdigit() and len(hours) == 2 and len(minutes) == 2 and int(hours) <= 23 and int(minutes) <= 59:
        return True
    return False


def is_time_valid(time_str: str) -> bool:
    if not ":" in time_str:
        return False

    hours, minutes = time_str.split(":", 1)
    if (
        hours.isdigit()
        and minutes.isdigit()
        and len(hours) == 2
        and len(minutes) == 2
        and int(hours) <= 23
        and int(minutes) <= 59
    ):
        return True
    return False

while True:
    start_time = input("Please enter a time (HH:MM): ").strip()
    if is_time_valid(start_time):
        print(f"Start time: {start_time}")
        break
    print("Invalid time")

def time_math(time_change):
  time_split = time_change.split(":")
  time_int_hours = int(time_split[0])
  time_int_minutes = int(time_split[1])

#

this is it with the comments put away, there was a lot of comments of me trying things

#

the first part before the comment is something that already works btw,

lament bay
#

!e - see how this will fail with errors

time_split = "13:47".split(":")
time_int = int(time_split)
gritty bearBOT
lament bay
#

πŸ’₯

hollow glacier
#

dang

lament bay
#

!e

time_split = "13:47".split(":")
time_int_hours = int(time_split[0])
time_int_minutes = int(time_split[1])
print(time_int_hours)
print(time_int_minutes)
gritty bearBOT
lament bay
#

while this works

hollow glacier
#

So cant use int on lists or such

#

got it

lament bay
#

and even if we didn't print it it would execute without any errors, but we wouldn't get any output either, so it would be hard to know if it gave us the result that we were expecting

hollow glacier
#

Right

lament bay
#

this is why it can be good to make a little separate .py file and try small code snippets in in isolation

hollow glacier
#

yeah thats good to know

lament bay
#

and then you can integrate it into your code after

hollow glacier
#

I normally use online python for those small things

#
def time_math(time_change):
  time_split = time_change.split(":")
  time_int_hours = int(time_split[0])
  time_int_minutes = int(time_split[1])
  time_total = time_int_hours * 60 + time_int_minutes
  print(time_total)

time_math(start_time)
#

boom

lament bay
#

but you don't really want to print it, you want to return it so that you can do things with it, like doing mathematical operations on it

hollow glacier
#

Yeah I printed it to test it out to see if it worked

#

now I need to get an end time and do the same, subtract it and magically make it into a HH:MM format again

lament bay
#

my suggestion would be to return it either way, after your debug print and then remove the debug print line from the code when you have verified it

#

or in this case as the print happens as the very last thing before you return the same value, you could just call the function within a print() statement instead

#

so if it returned instead of printing inside the function so that it is in it's final state
you can do

print(time_math(start_time))
#

that way you don't need to go back and change anything within the function if everything works as expected, then you just change the calling code outside of the function to not print it

hollow glacier
#

ohh alright, didnt know you could print a function

lament bay
#

you don't print the function, you print the result of the function

#

so you can think of it as a variable or the value that the function returns that is getting printed

hollow glacier
#

Ahhhhhh

#

Yeah my bad I still struggle a bit on the return stuff

lament bay
#

!gif

gritty bearBOT
#
Print and return

Here's a handy animation demonstrating how print and return differ in behavior.

See also: /tag return

hollow glacier
#

Oh wow this gif is very handy

lament bay
#

here is a little animation that explains how arguments in a function call and parameters in the function signature and return works

hollow glacier
#

I thought it worked that way but this is a very easy way of explaining

#

Cant believe its this much trouble for a small assignment 😹

#

But I now know what to do thanks to you, thanks a lot

lament bay
#

then you need to convert the minutes back to a time stamp if you want to present the duration in that way

hollow glacier
#

should I create a function for that also?

lament bay
#

yeah, i would suggest you do that

hollow glacier
#

alright

lament bay
#

good to have reusable code

#

even if you just use it once

#

it also abstracts the main code so that there isn't to much implementation details in the main body of code

hollow glacier
#

so if i were to have 09:05 it would be 545, i would need to do:

545 / 60
545 % 60

right?

hollow glacier
lament bay
#

that way it's easier to follow the main code and the function names can serve as a high level explanation of what is happening and if you want to know the details you can go and look at the implementation in the function

hollow glacier
lament bay
#

it's called "extraction" (when you take part of the code and put it in a function that you call from where you took the code) and is a "refactoring" technique (refactoring is the practise of rewriting code to improve it, often restructuring and rewriting parts of it)
then you can try to improve the code in the function to generalize it so it becomes more reusable

hollow glacier
#

yeah makes sense

lament bay
#

it also makes the code more manageable by braking it up
but you want to break it up at logical boundaries, if you break it up in the wrong way the code just gets scattered in several places and it instead gets hard to follow the logic of the code and you will have to jump around in the code a lot to where the different functions are defined when reading the code to understand what is happening

#

so it's important to do it in the right way if applying extraction

hollow glacier
#

isnt a good way of doing that just commenting a section: "Functions" and have all your functions there?

lament bay
lament bay
#

@hollow glacier by the way, you might want explanations for things in the validation function
like how some of it works and why we do certain things in there in a specific way

hollow glacier
hollow glacier
lament bay
hollow glacier
#

that got me pretty curious

lament bay
#

!d map

gritty bearBOT
#
map

map(function, iterable, *iterables)```
Return an iterator that applies *function* to every item of *iterable*, yielding the results. If additional *iterables* arguments are passed, *function* must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged into argument tuples, see [`itertools.starmap()`](https://docs.python.org/3/library/itertools.html#itertools.starmap).
hollow glacier
#

Im here!

lament bay
#

that means that it will run a function for every item in an iterable
but when giving it the function it should run you only give it the name, without any parentheses
and the map() function doesn't return a list or tuple but a "map object" that is an iterable that works just like a "generator" that instead of returning all the data all at once instead yields one item at a time on demand, if you want it as a real list with all the data at once you need to enclose it in a list() as well (or do it as a separate operation afterwards)

lets pretend that timestamp is the name of the function parameter for a function in the below examples

earlier you asked about this, that isn't valid since split() returns a list and you can't apply int()on the whole list all at once like this

timestamp = "13:47"
time_split = timestamp.split(":")
time_int = int(time_split)
```that you already seen the error from earlier in this conversation, so i see no need to run the code again

instead, you need to apply the function to each item or element in the list, this a perfect job for `map()`
so for the `int()` function that you have been using we can specify it like this:
#

!e

timestamp = "13:47"
time_split = timestamp.split(":")
print(time_split)
time_int_generator = map(int, time_split)
print(time_int_generator)
time_int_list = list(time_int_generator)
print(time_int_list)
gritty bearBOT
lament bay
#

as you can see from the first output line, after the split we have a list of strings
then we print the map object which isn't very helpful as you can see, you need to use it in an iterator context such as a for loop or similar to make it useful
and when we enclose it in list() we force it to give us all the values one after another until the generator is exhausted and have no more results to give us, and we get that as list that we finally print

#

!e

timestamp = "13:47"
time_int_list = list(map(int, timestamp.split(":")))
print(time_int_list)
gritty bearBOT
lament bay
#

we can even combine them all in one line like the above code

#

you can see that the elements in the list aren't enclosed in any kind of quotes, which means they are proper numbers in both the last line of the last output as well as this output

#

a more natural fit for this would maybe be together with a for loop like the following

#

!e

timestamp = "13:47"
for number in map(int, timestamp.split(":")):
    print(number)
gritty bearBOT
hollow glacier
#

Oh woe

#

wow*

lament bay
#

there we never need to enclose it in a list() since a for loop can work directly with a iterable like a generator

#

you see how we specify the function without the parentheses, that gives us a reference (the address of) a callable (code, for example a function) that map() can then call with each item or element one at a time as the argument to that function

#

it works almost like this code:

#

!e

timestamp = "13:47"
for item in timestamp.split(":"):
    print(int(item))
gritty bearBOT
hollow glacier
#

Ahh I kind of get it now yeah

lament bay
#

but yield each result from the map() function one by one instead of printing them

hollow glacier
#

Damn thats complicated

lament bay
#

it can be a complex concept to wrap your head around in the beginning but very useful at times

hollow glacier
#

Yeah it looks useful, is there an example that you can tell me that this can be used for instead of changing numbers into integers?

#

Mb for the response time im just rereading all this to get a good understanding of it

lament bay
#

that's okay, it was kind of a wall of text there πŸ˜‰

#

have you learned about "unpack"ing in python?

hollow glacier
#

Uhh pretty sure I haven’t

lament bay
hollow glacier
lament bay
#

it's one of the most common ways where you use unpacking naturally without even thinking much of it

#

dictionaries (sometimes called a "hash map" in general computer science) and are often used for lookup tables and is a very very useful data structure for solving a lot of different problems in programming

hollow glacier
#

I remember using a dictionary when i had to calculate wheter a position on a chess board was white or black

#

That was pretty interesting

lament bay
#

they have the key and value pairs, where the key must be of a hashable data type, which many immutable (those that can't be changed but instead needs to be replaced in their entirety) data types such as str (text strings), tuple and frozenset
the key can't be something that is internally mutable, as they can't be hashed to a stable value, for example list, dict or a set as all of them has content that can be changed or updated without replacing the whole object
but the value can almost be what ever you want

#

let's use the following dictionary where the name of each fruit is the key and the color is the value, both being strings, so each key maps to one value here

fruits = {
    "banana": "yellow",
    "apple": "green",
    "cherry": "red",
}
```just for compactness in the following examples we can write them on one line even if it isn't as readable
```py
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
```you can ask for a list of only all the keys or only all the values or all of the key value pares as a tuple for each item or pair
#

!e

fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
print(fruits.keys())
print(fruits.values())
print(fruits.items())
gritty bearBOT
hollow glacier
#

Ohh, never knew they consisted out of keys and values

#

You can also set a string as a key and a int as the value right

lament bay
#

and when you just use the dictionary by itself in a iterable context it's the same as doing .keys() on it, like this

#

!e

fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for fruit in fruits:
    print(fruit)
gritty bearBOT
lament bay
#

sorry, print wasn't a good example in this context

#

you can also access the value for each iteration like this (a bit of a clubsy way, you'll see a better way soon where unpacking comes into play):

#

!e

fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for fruit in fruits:
    print(fruit, fruits[fruit])
gritty bearBOT
lament bay
#

as the variable fruit contains the first key "banana" during the first iteration of the loop you can access the value of that key with fruits["banana"] or in this case fruits[fruit]

hollow glacier
#

what does it do exactly when you say fruits[fruit]

lament bay
#

so first it's like doing fruits["banana"], the second iteration fruit contains "apple" as that is the second key in the dictionary and is then like doing fruits["apple"] and so on, thus we can access the value and print it as well

#

but as you can see this is a bit extra work and pretty verbose, so here we can instead use .items() on the dictionary

#

!e

fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for item in fruits.items():
    print(item)
gritty bearBOT
lament bay
#

now we get a tuple which is mostly like a list but it's internally immutable (so can't be change the content of the tuple but have to replace) for each item and get the key as the first element in the tuple and the value as the second element

#

this tuple can be unpacked and then the code looks like this instead

#

!e

fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for key, value in fruits.items():
    print(key, value)
gritty bearBOT
lament bay
#

now key contains the first element of the tuple that is returned for each iteration of .items() on the dictionary in the for loop and value contains the second element

#

now it's much easier to use the value and key together in the loop for different things

#

in the same way we can "unpack" return values such as tuples or lists that are returned by a function

#

this is something you already seen me use in the function i wrote to show you a shorter and more readable function for validation in the form of

def is_time_valid(timestamp: str) -> bool:
    ...
    hours, minutes = timestamp.split(":", 1)
    ...
silk sluice
#

(unpack in codeblock makes it look like a keyword or function exists which does that)

lament bay
silk sluice
#

(Yeah quotes are better, or maybe use markdown such as italics)

#

(Isn't it cool how parentheses make your messages invisible to everyone else?)

lament bay
#

@hollow glacier the line with unpacking the list that .split() returns into two variables

hours, minutes = timestamp.split(":", 1)
```it now requires that we get exactly two elements back, not an empty list, or a list with a single element or two or more elements, it will raise an exception in such cases which we don't want
#

!d str.split

gritty bearBOT
#

str.split(sep=None, maxsplit=-1)```
Return a list of the words in the string, using *sep* as the delimiter string. If *maxsplit* is given, at most *maxsplit* splits are done (thus, the list will have at most `maxsplit+1` elements). If *maxsplit* is not specified or `-1`, then there is no limit on the number of splits (all possible splits are made).

If *sep* is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, `'1,,2'.split(',')` returns `['1', '', '2']`). The *sep* argument may consist of multiple characters as a single delimiter (to split with multiple delimiters, use [`re.split()`](https://docs.python.org/3/library/re.html#re.split)). Splitting an empty string with a specified separator returns `['']`.

For example:
lament bay
#

to make sure that .split() never returns more then two elements i included a 1 as the second argument to .split() which then becomes the maxsplit parameter and makes it so that it will only split on the first separator (a colon in this cace) that it sees and then stop splitting after that, everything before the colon will end up as a string in the first element and everything after the first colon will end up in the second element which is also a string (which then can contain even colons in the string as .split() will not process them after it has hit the maxsplit limit)

#

so now that possible error is taken care of, now we need to make sure that we will be able to split it on colon, which we can only do if the string contains at least one colon

hollow glacier
#

My bad im back, im having dinner rn

lament bay
#

that is what we check before we try to split it with these two lines

    if ":" not in timestamp:
        return False
```as that make sure that the string has at least one colon, otherwise we do a "early return" out of the function
#

so with that check before the split as well as the maxsplit argument of 1 makes sure that the .split() will succeed and give us exactly two elements, which now ends up being unpacked into the variables hours and minutes respectively and will not raise any exceptions/errors as we have done a few things to make sure that will never happen when we get to that point in the code

hollow glacier
#

I will need to reread this as soon as I am in a quieter spot im sorry. Cant really focus and dont want to lie and say that i understand it all

#

Will this auto close? If i dont respond within an hour

lament bay
#

it's okay, just ask questions if have any

hollow glacier
#

Cause i do not want to lose all that valuable info

#

Thanks again by the way, ill return to you asap

lament bay
#

so if someone else writes it will be kept open for longer

hollow glacier
#

Ohh okay

lament bay
#

when a thread is closed in any way it is archived as read-only, so all information will remain for posterity on this server πŸ˜‰
to find it you can either copy the link to the whole thread under the three dots at the top right of this thread or to a specific message on the three dots to the right of any message
that way you can save it in one way or another and come back to it at a later time, you just won't be able to write or change anything after and will need to open a new thread if you want to continue the conversation at a later time

silk sluice
lament bay
lament bay
lament bay
#

@hollow glacier "guard clauses" also called "guard statements" or "early return" and sometimes also called "inversion" (but that shouldn't be confused with another common technique called "dependency inversion" which is used for something totally different and isn't of interest right now) is probably a concept you want to read up on, it removes indentation levels and to some extent can also prevent some code duplication
it's what i used in the function i wrote to remove indentation from the previous version of the code that had deep nested if's and quite a few else's (which i don't have a single one of in the new version of the function)
close to the end of this very long article is a short example of "early return" that i link directly to: https://realpython.com/python-control-flow/#hard-to-read-nested-constructs

lament bay
#

bump, keeping this thread alive a little bit longer for OP

gritty bearBOT
#
Python help channel closed for inactivity

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.