Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good practice to mix yield and return statements in python?

Tags:

python

I'd quite like to have the following behaviour:

def foo(bar=None):
    if bar:
        return other_function(other_thing[bar])
    else:
        for i in other_thing:
            yield other_function(i)

The idea being that the function can then be used as a generator to build all instances, or it can be used to return a specific instance. Is this a good way to do this in Python? If not, is there a better way.

like image 393
David Boshton Avatar asked Mar 02 '15 09:03

David Boshton


Video Answer


1 Answers

Only in Python 3 it is syntactically possible to have return value and yield in the same function, in Python 2 it will result in:

SyntaxError: 'return' with argument inside generator

In Python 3 return value inside a generator is actually a syntactic sugar for raise StopIteration(value), which is also supported by the yield from clause:

def f():
    yield from iter('123')
    return 'ok'

def g():
    message = yield from f()
    print('Message:', message)

In [1]: list(g)
Message: ok
Out[1]: ['1', '2', '3']

So, this construct does not do what you expect it to. Besides, it does not seem a very good ("pythonic") idea to vary the return type (or, rather, interface) of a function based on the argument value. That may be a matter of taste, though, here is what Guido van Rossum says in his interview in the book Masterminds of Programming:

I have a few personal pet peeves: first of all, and this is specific to dynamic languages, don’t make the return type of a method depend on the value of one of the arguments; otherwise it may be hard to understand what’s returned if you don’t know the relationship—maybe the type-determining argument is passed in from a variable whose content you can’t easily guess while reading the code.

like image 143
bereal Avatar answered Sep 24 '22 22:09

bereal