2014-05-14 106 views
17

我試圖爲布爾表達式打印一個真值表。雖然這樣做,我偶然發現了以下情況:一旦使用Python中的format()方法打印布爾值True/False

>>> 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()轉換True1。我知道boolint一個子類,這樣True計算爲1

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

但爲什麼使用格式說明變化'True'1在第一個例子?我轉向docs for clarification。它說的唯一的事情是:

的一般慣例是,一個空的格式字符串("")產生,如果你曾呼籲str()上的值相同的結果。非空格式字符串通常會修改結果。

因此,當您使用格式說明符時,字符串會被修改。但是,爲什麼從True1的變化如果只有指定了一個比對運算符(例如^)?

+1

「一般慣例是空格式字符串(」「)產生的結果與您對該值調用str()時的結果相同,非空格式字符串通常會修改結果。 - [docs](https://docs.python.org/2/library/string.html#format-specification-mini-language) – netcoder

+0

我不知道爲什麼這樣做,但如果你想修復它可以做'format(str(True),「^」)' – jspurim

+0

謝謝,我已經修復了它,但我只是好奇「爲什麼」:) –

回答

9

優秀的問題!我相信我有答案。這需要通過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',神祕感已經結束!

+2

我想OP是問爲什麼''^'。format(True)=='1''',而不是爲什麼''''。格式(True)=='True'''。或者說爲什麼當後者正確評估時,爲什麼會在前者中隱式轉換爲「int」呢? – aruisdante

+0

'True' *是一個'int',它只在'format_spec'爲空時從'int'和'str'中轉換。 – huu

+1

不是在Python中,它不是。 '>>> type(True)= '',和''type(True)== type(1)== False''。在C解釋器中的底層C代碼中,顯然它被轉換成了一個''int'',因爲C缺少一個bool基元,但是這並不能解釋python方面的隱式轉換。 – aruisdante