【问题标题】:Printing boolean values True/False with the format() method in Python在 Python 中使用 format() 方法打印布尔值 True/False
【发布时间】:2015-09-14 12:09:48
【问题描述】:

我试图打印布尔表达式的真值表。在执行此操作时,我偶然发现了以下内容:

>>> format(True, "") # shows True in a string representation, same as str(True)
'True'
>>> format(True, "^") # centers True in the middle of the output string
'1'

只要我指定了格式说明符,format() 就会将 True 转换为 1。我知道boolint 的子类,所以True 的计算结果为1

>>> format(True, "d") # shows True in a decimal format
'1'

但是为什么在第一个示例中使用格式说明符会将'True' 更改为1

我转向docs for clarification。它唯一说的是:

一般约定是空格式字符串 ("") 产生的结果与您在值上调用 str() 时产生的结果相同。非空格式字符串通常会修改结果。

因此,当您使用格式说明符时,字符串会被修改。但是,如果指定了对齐运算符(例如^),为什么要从True 更改为1

【问题讨论】:

  • “一般约定是,空格式字符串 ("") 产生的结果与您在值上调用 str() 时产生的结果相同。非空格式字符串通常会修改结果。” -- docs
  • 我不知道为什么会这样,但如果你想修复它,你可以这样做format(str(True),"^")
  • 谢谢,我已经修好了,但我只是好奇“为什么”:)
  • 我的猜测是它与 '^' 运算符的隐式转换有关,尽管这很奇怪。另请注意,'^'align-center 运算符,而不是宽度运算符。
  • 是的,它很奇怪。更正了问题。

标签: python python-2.7 boolean string-formatting string.format


【解决方案1】:

很好的问题!我相信我有答案。这需要在 C 中挖掘 Python 源代码,所以请耐心等待。

首先,format(obj, format_spec) 只是 obj.__format__(format_spec) 的语法糖。对于发生这种情况的具体情况,您必须在函数中查看abstract.c

PyObject *
PyObject_Format(PyObject* obj, PyObject *format_spec)
{
    PyObject *empty = NULL;
    PyObject *result = NULL;

    ...

    if (PyInstance_Check(obj)) {
        /* We're an instance of a classic class */
HERE -> PyObject *bound_method = PyObject_GetAttrString(obj, "__format__");
        if (bound_method != NULL) {
            result = PyObject_CallFunctionObjArgs(bound_method,
                                                  format_spec,
                                                  NULL);

    ...
}

要找到确切的电话,我们必须查看intobject.c

static PyObject *
int__format__(PyObject *self, PyObject *args)
{
    PyObject *format_spec;

    ...

    return _PyInt_FormatAdvanced(self,
                     ^           PyBytes_AS_STRING(format_spec),
                     |           PyBytes_GET_SIZE(format_spec));
               LET'S FIND THIS
    ...
}

_PyInt_FormatAdvanced 实际上在formatter_string.c 中定义为宏作为formatter.h 中的函数:

static PyObject*
format_int_or_long(PyObject* obj,
               STRINGLIB_CHAR *format_spec,
           Py_ssize_t format_spec_len,
           IntOrLongToString tostring)
{
    PyObject *result = NULL;
    PyObject *tmp = NULL;
    InternalFormatSpec format;

    /* check for the special case of zero length format spec, make
       it equivalent to str(obj) */
    if (format_spec_len == 0) {
        result = STRINGLIB_TOSTR(obj);   <- EXPLICIT CAST ALERT!
        goto done;
    }

    ... // Otherwise, format the object as if it were an integer
}

这就是你的答案。简单检查format_spec_len 是否为0,如果是,将obj 转换为字符串。众所周知,str(True) 就是'True',谜底就结束了!

【讨论】:

  • 我认为 OP 是在问为什么 '^'.format(True) == '1',而不是为什么 ''.format(True) == 'True'。或者更确切地说,当后者正确评估时,为什么前者会隐式转换为 int
  • True 一个int,只有当format_spec为空时,它才会从int转换成str
  • 不是在 python 中它不是。 &gt;&gt;&gt; type(True) = &lt;type 'bool'&gt;type(True) == type(1) == False。在 C 解释器的底层 C 代码中,它显然被转换为 int,因为 C 缺少 bool 原语,但这不能解释 python 端的隐式转换。
  • 澄清:由于boolint 的子类,但bool 没有指定它自己的__format__ 方法,来自int 的方法通过常规继承使用。在对空格式字符串进行特殊处理的情况下,在为bool 实现 的对象上调用str()
  • 因此,为了同时将非空格式字符串(例如对齐)和布尔值打印为真/假,我们应该首先将 str(boolean) 并将其(作为字符串)发送到格式化函数?
猜你喜欢
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多