Python: try statement in a single line

前端 未结 13 1606
囚心锁ツ
囚心锁ツ 2020-12-01 03:47

Is there a way in python to turn a try/except into a single line?

something like...

b = \'some variable\'
a = c | b #try statement goes here
<         


        
相关标签:
13条回答
  • 2020-12-01 04:27

    if you need to actually manage exceptions:
    (modified from poke53280's answer)

    >>> def try_or(fn, exceptions: dict = {}):
        try:
            return fn()
        except Exception as ei:
            for e in ei.__class__.__mro__[:-1]:
                if e in exceptions: return exceptions[e]()
            else:
                raise
    
    
    >>> def context():
        return 1 + None
    
    >>> try_or( context, {TypeError: lambda: print('TypeError exception')} )
    TypeError exception
    >>> 
    

    note that if the exception is not supported, it will raise as expected:

    >>> try_or( context, {ValueError: lambda: print('ValueError exception')} )
    Traceback (most recent call last):
      File "<pyshell#57>", line 1, in <module>
        try_or( context, {ValueError: lambda: print('ValueError exception')} )
      File "<pyshell#38>", line 3, in try_or
        return fn()
      File "<pyshell#56>", line 2, in context
        return 1 + None
    TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
    >>> 
    

    also if Exception is given, it will match anything below.
    (BaseException is higher, so it will not match)

    >>> try_or( context, {Exception: lambda: print('exception')} )
    exception
    
    0 讨论(0)
  • 2020-12-01 04:31

    You mentioned that you're using django. If it makes sense for what you're doing you might want to use:

    my_instance, created = MyModel.objects.get_or_create()
    

    created will be True or False. Maybe this will help you.

    0 讨论(0)
  • 2020-12-01 04:32
    parse_float = lambda x, y=exec("def f(s):\n try:\n  return float(s)\n except:  return None"): f(x)
    

    There is always a solution.

    0 讨论(0)
  • 2020-12-01 04:33

    In python3 you can use contextlib.suppress:

    from contextlib import suppress
    
    d = {}
    with suppress(KeyError): d['foo']
    
    0 讨论(0)
  • 2020-12-01 04:39

    This is terribly hackish, but I've used it at the prompt when I wanted to write up a sequence of actions for debugging:

    exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
    print "The problem is %s" % problem[1]
    

    For the most part, I'm not at all bothered by the no-single-line-try-except restriction, but when I'm just experimenting and I want readline to recall a whole chunk of code at once in the interactive interpreter so that I can adjust it somehow, this little trick comes in handy.

    For the actual purpose you are trying to accomplish, you might try locals().get('c', b); ideally it would be better to use a real dictionary instead of the local context, or just assign c to None before running whatever may-or-may-not set it.

    0 讨论(0)
  • 2020-12-01 04:41

    There is no way to compress a try/except block onto a single line in Python.

    Also, it is a bad thing not to know whether a variable exists in Python, like you would in some other dynamic languages. The safer way (and the prevailing style) is to set all variables to something. If they might not get set, set them to None first (or 0 or '' or something if it is more applicable.)


    If you do assign all the names you are interested in first, you do have options.

    • The best option is an if statement.

      c = None
      b = [1, 2]
      
      if c is None:
          a = b
      else:
          a = c
      
    • The one-liner option is a conditional expression.

      c = None
      b = [1, 2]
      a = c if c is not None else b
      
    • Some people abuse the short-circuiting behavior of or to do this. This is error prone, so I never use it.

      c = None
      b = [1, 2]
      a = c or b
      

      Consider the following case:

      c = []
      b = [1, 2]
      a = c or b
      

      In this case, a probably should be [], but it is [1, 2] because [] is false in a boolean context. Because there are lots of values that can be false, I don't use the or trick. (This is the same problem people run into when they say if foo: when they mean if foo is not None:.)

    0 讨论(0)
提交回复
热议问题