The Python Oracle

What should I use instead of assignment-in-an-expression in Python?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Popsicle Puzzles

--

Chapters
00:00 What Should I Use Instead Of Assignment-In-An-Expression In Python?
00:35 Accepted Answer Score 12
01:10 Answer 2 Score 4
01:46 Answer 3 Score 3
02:06 Answer 4 Score 2
02:38 Answer 5 Score 1
03:06 Thank you

--

Full question
https://stackoverflow.com/questions/1513...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ANSWER 1

Score 4


Another alternative which offers some flexibility:

# Functions to be tested (can be expanded):
tests = [something, somethingelse, yetsomethingelse, anotherfunction, another]
for i, f in enumerate(tests):
    a = f()
    if a:
        if i == 0:
            # do something with a
        elif 1 <= i <= 3:
            # do something else with a
        else:
            # ...
        break

Or you can explicitly compare to the function:

tests = [something, somethingelse, yetsomethingelse, anotherfunction, another]
for i, f in enumerate(tests):
    a = f()
    if a: break
if not a:
    # no result
elif f == something:
    # ...
elif f == somethingelse:
    # ...

If some of the functions take arguments, you can use lambda to keep the function paradigm:

tests = [lambda: something(args), somethingelse, lambda: something(otherargs)]
for i, f in enumerate(tests):
    a = f()
    if a: break
if not a:
    # no result
elif i == 0:
    # ...
elif i == 1:
    # ...



ANSWER 2

Score 3


You could do this:

a = something()
if a:
    #do something with a
else:
    a = somethingelse()
    if a:
        #...
    else:
        #5 more nested ifs

Or, inside a function you can limit the nesting level with a return in each matching case:

def f():
    a = something()
    if a:
        #do something with a
        return
    a = somethingelse()
    if a:
        #...
        return
    #5 more ifs



ANSWER 3

Score 2


Make yourself a simple callable object that saves its returned value:

class ConditionValue(object):
    def __call__(self, x):
        self.value = x
        return bool(x)

Now use it like this:

# example code
makelower = lambda c : c.isalpha() and c.lower()
add10 = lambda c : c.isdigit() and int(c) + 10

test = "ABC123.DEF456"
val = ConditionValue()
for t in test:
    if val(makelower(t)):
        print t, "is now lower case ->", val.value
    elif val(add10(t)):
        print t, "+10 ->", val.value
    else:
        print "unknown char", t

Prints:

A is now lower case -> a
B is now lower case -> b
C is now lower case -> c
1 +10 -> 11
2 +10 -> 12
3 +10 -> 13
unknown char .
D is now lower case -> d
E is now lower case -> e
F is now lower case -> f
4 +10 -> 14
5 +10 -> 15
6 +10 -> 16



ANSWER 4

Score 1


You could use a decorator like this memorise for those functions - assuming they always return the same value. Notice that you can call expensive_foo and expensive_bar as many times as you like and the function body only ever gets executed once

def memoize(f):
    mem = {}
    def inner(*args):
        if args not in mem:
            mem[args] = f(*args)
        return mem[args]
    return inner

@memoize
def expensive_foo():
    print "expensive_foo"
    return False

@memoize
def expensive_bar():
    print "expensive_bar"
    return True

if expensive_foo():
    a=expensive_foo()
    print "FOO"
elif expensive_bar():
    a=expensive_bar()
    print "BAR"