Skip to content Skip to sidebar Skip to footer

What Should I Use Instead Of Assignment-in-an-expression In Python?

according to this page one can't use code like if variable = something(): #do something with variable, whose value is the result of something() and is true So in case I want to ha

Solution 1:

I had this problem years ago, in 2001 -- since I was transliterating to Python from a reference-algorithm in C which used assign-and-test heavily, I was keen to keep a similar structure for the first draft (then refactor later once correctness was well tested). So I wrote a recipe in the Cookbook (see also here), which boils down to...:

classDataHolder(object):defset(self, value): self.value = value; return value

so the if/elif tree can become:

dh = DataHolder()
if dh.set(something()):
  # do something with dh.valueelif dh.set(somethingelse()):
  # ...

the DataHolder class can clearly be embellished in various ways (and is so embellished in both the online and book versions), but this is the gist of it, and quite sufficient to answer your question.

Solution 2:

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 aelse:
            # ...
        break

Or you can explicitly compare to the function:

tests = [something, somethingelse, yetsomethingelse, anotherfunction, another]
for i, f inenumerate(tests):
    a = f()
    if a: breakifnot a:
    # no resultelif 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 inenumerate(tests):
    a = f()
    if a: breakifnot a:
    # no resultelif i == 0:
    # ...elif i == 1:
    # ...

Solution 3:

You could do this:

a=something()if a:#do something with aelse: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 areturn
    a = somethingelse()
    if a:
        #...return#5 more ifs

Solution 4:

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

classConditionValue(object):
    def__call__(self, x):
        self.value = x
        returnbool(x)

Now use it like this:

# example code
makelower = lambda c : c.isalpha() and c.lower()
add10 = lambda c : c.isdigit() andint(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 -> 112 +10 -> 123 +10 -> 13
unknown char .
D is now lower case -> d
E is now lower case -> e
F is now lower case -> f
4 +10 -> 145 +10 -> 156 +10 -> 16

Solution 5:

I might be missing something, but couldn't you factor each of the branches in your top-level if statement into separate functions, create a list of test to action tuples and loop over them? You should be able to apply this pattern to mimic if (value=condition()) {} else if (value=other_condition()) {} style logic.

This is really an extension of redglyph's response and can probably be compressed down to a iterator that raises StopIteration once it has hit a truth value.

## These are the "tests" from your original if statements. No# changes should be necessary.#defsomething():
    print('doing something()')
    # expensive stuff heredefsomething_else():
    print('doing something_else()')
    # expensive stuff here too... but this returns True for some reasonreturnTruedefsomething_weird():
    print('doing something_weird()')
    # other expensive stuff## Factor each branch of your if statement into a separate function.# Each function will receive the output of the test if the test# was selected.#defsomething_action(value):
    print("doing something's action")
defsomething_else_action(value):
    print("doing something_else's action")
defsomething_weird_action(value):
    print("doing something_weird's action")

## A simple iteration function that takes tuples of (test,action). The# test is called. If it returns a truth value, then the value is passed# onto the associated action and the iteration is stopped.#defdo_actions(*action_tuples):
    for (test,action) in action_tuples:
        value = test()
        if value:
            return action(value)

## ... and here is how you would use it:#
result = do_actions(
             (something, something_action),
             (something_else, something_else_action),
             (something_weird, something_weird_action)
)

Post a Comment for "What Should I Use Instead Of Assignment-in-an-expression In Python?"