格式化数值,也可以是无

时间:2018-07-01 18:56:51

标签: python format

我正在寻找一种更好的方法来处理这样的语句中的可选None值(缺少值):

logger.info("temp1 = %.1f, temp2 = %.1f, position = %.2f", t1, t2, pos)

为了防止:

TypeError: must be real number, not NoneType

这就是我现在正在做的事情:

logger.info(
    "temp1 = %s, temp2 = %s, position = %s",
    "null" if t1 is None else format(t1, '.1f'),
    "null" if t2 is None else format(t2, '.1f'),
    "null" if pos is None else format(pos, '.2f'))
    # any placeholder like "null", "None", "---", or "N/A" is fine

,我不喜欢它。有没有更好的办法?使用str.formatf-strings解决这个小问题也有帮助。

3 个答案:

答案 0 :(得分:2)

创建一个包装,该包装在调用__format__时进行自我检查。

class AnyOrNone(object):  # The wrapper is not type-specific
    def __init__(self, value):
        self.value = value

    def __format__(self, *args, **kwargs):
        if self.value is None:
            return "None"
        else:
            return self.value.__format__(*args, **kwargs)

答案 1 :(得分:0)

一种方法是为此编写一个简单的函数,例如:

ret[i][k]

或者您可以编写一个可以接受并格式化多个参数的函数:

def fin(obj): return "null" if obj is None else format(obj, '.1f')

logging.info("temp1 = %s, temp2 = %s, position = %s", fin(t1), fin(t2), fin(pos))
# INFO:root:temp1 = null, temp2 = 0.2, position = 6.8

编辑:或者,使用Python 3.6+ f字符串:

def fins(*objs):
    return ("null" if obj is None else format(obj, '.1f') for obj in objs)

logging.info("temp1 = %s, temp2 = %s, position = %s", *fins(t1, t2, pos))
# INFO:root:temp1 = null, temp2 = 0.2, position = 6.8

或者,当obj是浮点型时使用precision,否则使用str(obj)

def ff(obj, fmt):
    return "null" if obj is None else format(obj, fmt)

logger.info(f"temp1 = {ff(t1, '.1f')}, temp2 = {ff(t2, '.1f')}, position = {ff(pos, '.2f')}")
# temp1 = None, temp2 = 0.2, position = 6.79

在所有情况下,

def ff(obj, p):
    return format(obj, '.%df' % p) if isinstance(obj, float) else str(obj)

logger.info(f"temp1 = {ff(t1, 1)}, temp2 = {ff(t2, 1)}, position = {ff(pos, 2)}")
# temp1 = None, temp2 = 0.2, position = 6.79

如果您希望以这种方式转换作为t1, t2, pos = None, 0.234, 6.789 参数传递的 all 浮点数,则可以创建一个custom handler,但这似乎是过分的,并且容易转换。不想。

答案 2 :(得分:0)

我知道两种方法:

for x in [1.23456, None]:
print(
    '1: {}'.format(x is not None and '{:0.4f}'.format(x) or 'None')
)
print(
    '2: {:{x_fmt}}'.format(x, x_fmt=x is not None and '0.4f' or '')
)

出局:

1: 1.2346
2: 1.2346
1: None
2: None