how format specifier taking value while tuple list is passed

前端 未结 1 1422
星月不相逢
星月不相逢 2021-01-27 16:20

I have a piece of code as below:

tupvalue = [(\'html\', 96), (\'css\', 115), (\'map\', 82)]

So while printing the above tuple in the desired fo

相关标签:
1条回答
  • 2021-01-27 16:47

    First, the easy question:

    How can I use a comprehension to format all the values in tupvalue in the required format as in the example shown?

    That's a list comprehension: ['%s:%d' % t for t in tupvalue]

    Now, the harder question!

    how the single value tupvalue[0] is recognised as a tuple of two values by the format specifier '%s:%d'?

    Your intuition that something a bit strange is going on here is correct. Tuples are special-cased in the language for use with string formatting.

    >>> '%s:%d' % ('css', 115)  # tuple is seen as two elements
    'css:115'
    >>> '%s:%d' % ['css', 115]  # list is just seen as one object!
    TypeError: not enough arguments for format string
    

    The percent-style string formatting does not duck-type properly. So, if you actually wanted to format a tuple, you'll have to wrap it in another tuple, unlike any other kind of object:

    >>> '%s' % []
    '[]'
    >>> '%s' % ((),)
    '()'
    >>> '%s' % ()
    TypeError: not enough arguments for format string
    

    The relevant section of the documentation is at section 4.7.2. printf-style String Formatting, where it is mentioned:

    If format requires a single argument, values may be a single non-tuple object. Otherwise, values must be a tuple with exactly the number of items specified by the format string

    The odd handling of tuples is one of the quirks called out in the note at the beginning of that section of the documentation, and one of the reasons that the newer string formatting method str.format is recommended instead.

    Note that the handling of the string formatting happens at runtime. You can verify this with the abstract syntax tree:

    >>> import ast
    >>> ast.dump(ast.parse('"%s" % val'))
    "Module(body=[Expr(value=BinOp(left=Str(s='%s'), op=Mod(), right=Name(id='val', ctx=Load())))])"
    

    '%s' % val parses to a binary operation on '%s' and val, which is handled like str.__mod__(val), in CPython that's a BINARY_MODULO opcode. This means it's usually up to the str type to decide what to do when the val received is incorrect*, which occurs only once the expression is evaluated, i.e. once the interpreter has reached that line. So, it doesn't really matter whether the val is the wrong type or has too few/too many elements - that's a runtime error, not a syntax error.

    Except in some special cases where CPython's peephole optimizer is able to "constant fold" it at compile time.

    * Unless val's type subclasses str, in which case type(val).__rmod__ should be able to control the result.

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