Avoiding indentation in a situation where you should try: instead of if-elsif

I have a number of conditions that, after trying the "pythonic style", can only be checked by exception:

def getGrok(x):
    try:  # is x referring to a snood?
        s = makeSnood(x)
        grokster = s.snoodidle()
    except ValueError:
        try:  # is x referring to a trund?
            t = makeTrund(x)
            grokster = t.trundle()
        except ValueError:
            try:  # maybe too deep?
                d = makeTooDeep(x)
                grokster = d.groan()
            except ValueError:
                grokster = None

     if grokster:
         return grokster.grok()
     else:
         return None

There were only three possibilities, and already too deep.

It makes me think that there should be a better way. How can you do this logic without this nested tree?

+4
source share
7 answers

In your example, it seems that later attempts should really be nested in previous ones. You just make three separate attempts. They have order, but they do not have to be nested. That way you can just do something like

grokster = None
try:  # is x referring to a snood?
    s = makeSnood(x)
    grokster = s.snoodidle()
except ValueError:
    pass

if grokster is None:
    try:  # is x referring to a trund?
        t = makeTrund(x)
        grokster = t.trundle()
    except ValueError:
        pass

if grokster is None:
    try:  # is x referring to a trund?
        d = makeTooDeep(x)
        grokster = d.groan()
    except ValueError:
        pass

if grokster:
     return grokster.grok()
else:
     return None

"" , , return None - raise GroksterError("Don't know how to make grokster of x").

, , , , , , "" (makeSnood, makeTrund ..) (snoodidle, trundle ..), . , ( ). , , , , (, , ); , "" , .

+2

...

def f1(x):
    s = makeSnood(x)
    return s.snoodidle()

def f2(x):
    t = makeTrund(x)
    return t.trundle()

def f3(x):
    d = makeTooDeep(x)
    return d.groan()

... , .

def getGrok(x):
    grokster = None
    for f in (f1, f2, f3):
        try:
            grokster = f(x)
            break
        except ValueError:
            pass
    return grokster.grok() if grokster else None
+2

, , :

def make_thing(x, func, method_name):
    obj = func(x)
    return getattr(obj, method_name)()


funcs = [(makeSnood, 'snoodle'), (makeTrund, 'trundle'), (makeTooDeep, 'groan')]
for func, method_name in funcs:
    try:
        make_thing(x, func, method_name)
    except ValueError:
        pass
    else:
        break
+1

"" , , "" "" "" :

def getGrok(x):
    try: 
        return  makeSnood(x).snoodidle().grok()
    except ValueError:
        pass
    try:  
        return makeTrund(x).trundle().grok()
    except ValueError:
        pass    
    try: 
        return makeTooDeep(x).groan().grok()
    except ValueError:
        pass
    return None

grok, - , .

, Daniel, getattr , :

def getGrok(x):
    for f, m in [(makeSnood, 'snoodle'), (makeTrund, 'trundle'), (makeTooDeep, 'groan')]:
        try:
            return getattr(f(x), m)()
        except ValueError:
            pass
    return None
+1

, , :

def isThing(x, function, get_val):
    t = function(x)
    return get_val(t)

def getGrok(x):
    funcs = [(makeSnood, lambda s: s.snoodidle()), (makeTrund, lambda t: t.trundle()), (makeTooDeep, lambda d = d.groan())]
    grokster = None
    for func, get_val in funcs:
        try:  # is x referring to a snood?
            grokster = isThing(x, func, get_val)
            break
        except ValueError:
            continue

     if grokster:
         return grokster.grok()
     else:
         return None

- .

0

Here is my simplified version.

def getGrok(x):
    grokster=get_grokster(x):
    if not grokster:
        return
    return grokster.grok()

def get_grokster(x):
    try:  # is x referring to a snood?
        return makeSnood(x).snoodidle()
    except ValueError:
        pass

    try:  # is x referring to a trund?
        return makeTrund(x).trundle()
    except ValueError:
        pass

    try:  # maybe too deep?
        return makeTooDeep(x).groan()
    except ValueError:
        pass

This significantly reduces area gaps .

I like Reservations to reduce indentation. Unfortunately, this is an unknown picture. Maybe it's too easy - geeks prefer complicated things :-)

0
source
funcs = [(makeSnood, 'snoodidle'), (makeTrund, 'snoodidle'), (makeTooDeep, 'groan')]
grokster = None

while grokster is None and len(funcs) >0:
    f = funcs.pop()
    try:
        y = f[0](x)
        grokster = getattr(y, f[1])()
    except ValueError:
        pass
if grokster:
    return grokster.grok()
return None
-1
source

Source: https://habr.com/ru/post/1622472/


All Articles