3

I want to know how to make a function return the return value of a nested function, if the return value of the nested function is not None.

To make my code work, I could just copy the code of the nested function in my main function, but this is too repetitive (DRY). I looked into some questions with copying functions with from functool import partial but this just allows you to have another function with different variables or docstring. Furthermore I've glanced at all related questions and none seem to have an elegant piece of code (to do this simply).

Here the main function ExtractOne is fed a list of numbers. Generally (relevant to my code) the 4th element is one, so that element is checked with CheckIfOne function. If this is the case, the function returns 1 and is thus exited. If that is not the case, then the code continues by checking all the elements in the fed list if they're a one, again, using CheckIfOne for each element. If the element is one, ExtractOne should return 1, thus breaking the for loop and function.

Here's a snippet of what works. It's copying the return value of CheckIfOne (the nested function) onto a variable a, checking if a is not None, and returning a if this is the case.

Example 1:

def CheckIfOne(part):
    if part == 1:
        return 1

def ExtractOne(parts):
    #4th element is generally 1
    a = CheckIfOne(parts[3])
    if a:
        return a
    
    #else scan through the list for 1
    for part in parts:
        a = CheckIfOne(part)
        if a:
            return a

>>> ps = [1,2,3,4,5]
>>> ExtractOne(ps)
1
>>>

Here's how I would like it to look like, but of course this is not how nested functions work, the nested function returns a value and this must be copied onto a variable and that variable checked if it's not None and then returned, like in the above snippet.

Example 2:

def CheckIfOne(part):
    if part == 1:
        return 1

def ExtractOne(parts):
    #4th element is generally 1
    CheckIfOne(parts[3])
    
    #else scan through the list for 1
    for part in parts:
        CheckIfOne(part)

>>> ps = [1,2,3,4,5]
>>> ExtractOne(ps)
>>> 

However, it does work when I just copy the code of CheckIfOne, but this violates the DRY rule.

Example 3:

def ExtractOne(parts):
    #4th element is generally 1
    if parts[3] == 1:
        return 1
    
    #else scan through the list for 1
    for part in parts:
        if part == 1:
            return 1

>>> ps = [1,2,3,4,5]
>>> ExtractOne(ps)
1
>>>

I expect there to be a simple, pythonic python syntax to just copy the code of the nested function onto the main piece of code like in example 3.

2 Answers 2

3

Ignoring for a second that your code won't always have a return value, that the naming convention isn't in itself 'pythonic', and that there are simpler ways to reduce complexity, and assuming that you are just asking the question generically.

There is nothing wrong with calling a separate method, but if you simply want to spare yourself having another top level function and you will only use the code within your function, you can define the function inside the function, like below.

def ExtractOne(parts):

    def CheckIfOne(part):
        if part == 1:
            return 1

    #4th element is generally 1
    a = CheckIfOne(parts[3])
    if a:
        return a

    #else scan through the list for 1
    for part in parts:
        a = CheckIfOne(part)
        if a:
            return a

ps= [1,2,3,4,5]
print(ExtractOne(ps))
Sign up to request clarification or add additional context in comments.

2 Comments

Naming convention isn't something I pay much attention to: length of code I do, including too long of var or func names. I was wondering if there was a way to condense "a=CheckIfOne(part); if a: return a;" into something like CheckIfOne.__copy_code__(part) so the code in ExtractOne is equivalently that of example 3.
Your comment seems that you are asking for a macro - which Python doesn't have. Python places human readability as paramount and arguably what you are showing (at least in the comment above) would suffer readability issues. As an aside (not the place for a debate), but readability is the same reason that naming conventions should be something you pay attention to.
0

You can return multiple numbers, but putting all of your returns into an array (or list) then return them after you have finished.

def foo(numbs):
    output = []
    ...
    output.append(data)
    ...
    return output

5 Comments

I was wondering how I could condense: a = CheckIfOne(parts[3]); if a: return 1; into a one-liner.
you could use a ternary operator. a = (0,1)[parts[3] == 1]
or you can do if(CheckIfOne(parts[3]) == 1): return 1
Thank you very much for the input, but I want to emphasise that this was a piece of ducktesting code, very simple example. For my main code (not this!) I would need to basically copy the code of a nested function (here CheckIfOne) into the main function (here, ExtractOne), like with Example 3. I thought if there was something like CheckIfOne.__copy_code__(part) to do just this. With this I would have a nicer one liner than "a = CheckIfOne(part); if a: return a;" and I'd comply with the DRY principle.
maybe try a lambda? checkIfOne = lambda numb : (None,1)[numb == 1] this will allow you to call the lambda later on as a function but with much smaller syntax. There is no real reason to have short code, size != efficiency

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.