Python inline conditional in string concatenation
Asked Answered
S

1

5

I had this:

msg = time + b' - ' + Logger.LEVELS_WORD[msg_loglevel] + b': ' + msg.encode('utf-8') + b'\n'

Since sometimes msg was already bytes, I wanted to concat msg.encode('utf-8') if it was string or else just msg, so I did this:

msg = time + b' - ' + Logger.LEVELS_WORD[msg_loglevel] + b': ' + msg if isinstance(msg, bytes) else msg.encode('utf-8') + b'\n'

But it is not working as I expected, since now msg equals msg. (time + log level isn't getting added).

Should I do if/else instead?

Selfdeprecating answered 22/4, 2016 at 13:54 Comment(4)
What did you expect and what did it do?Purplish
@AmitGold concat msg.encode('utf-8') or msg depending on if it was already bytes.Selfdeprecating
instead of one of the msgs, change it to something similar like _msg and then do msg = _msgPurplish
The problem you have as stated in the answer provided is precedence, the if is taking the whole before expression. So you need to use parentheses in your conditional (msg if isinstance(msg, bytes) else msg.encode('utf-8'))Ohmage
P
8

A conditional expression has a very low precedence; it is executed last only before a lambda. As such the expression, as written, choses between either time + b' - ' + Logger.LEVELS_WORD[msg_loglevel] + b': ' + msg or msg.encode('utf-8')) + b'\n'.

Put the conditional expression with the if and else branches in parentheses:

msg = time + b' - ' + Logger.LEVELS_WORD[msg_loglevel] + b': ' + (
    msg if isinstance(msg, bytes) else msg.encode('utf-8')) + b'\n'

Consider using duck-typing (test for hasattr(msg, 'encode')), and breaking up the expression into multiple lines for readability. If you are using Python 3.5 or newer, perhaps you want to use printf-style formatting:

if hasattr(msg, 'encode'):
    msg = msg.encode('utf-8')
msg = b'%s - %s: %s\n' % (time, Logger.LEVELS_WORD[msg_loglevel], msg)
Phosphate answered 22/4, 2016 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.