2017-09-24 72 views
2

我試圖寫一個漂亮的打印程序,我在其中使用幾個包含浮點對的命名元組的程序,我遇到了這個問題。不能使用部分作爲__str__

from collections import namedtuple 
Position = namedtuple('Position', 'x y') 
Vector = namedtuple('Vector', 'x y') 
Size = namedtuple('Size', 'width height') 

我想格式化浮點數打印,因爲結果的時候:

import math 
print(Position(math.pi, math.pi), Vector(math.pi, math.pi), Size(math.pi, math.pi)) 

過長:

Position(x=3.141592653589793, y=3.141592653589793) Vector(x=3.141592653589793, y=3.141592653589793) Size(width=3.141592653589793, height=3.141592653589793) 

所以我創建了一個函數來打印指定的元組:

def pretty_float_pair(name, labels, obj): 
    """ 
    If labels = ('a', 'b') and object = (1.2345, 1.2345) returns: 
     'name(a=1.23, b=1.23)' 
    """ 
    return '{}({}={:.2f}, {}={:.2f})'.format(name, labels[0], obj[0], labels[1], obj[1]) 

應該爲每個類型固定名稱和標籤,只有obj參數不同,所以我想我可以使用functools部分。

from functools import partial 
Position.__str__ = partial(pretty_float_pair, 'Position', ('x', 'y')) 
Vector.__str__ = partial(pretty_float_pair, 'Vector', ('x', 'y')) 
Size.__str__ = partial(pretty_float_pair, 'Size', ('width', 'height')) 
print(Position(math.pi, math.pi), Vector(math.pi, math.pi), Size(math.pi, math.pi)) 

但是,這將引發TypeError: pretty_float_pair() missing 1 required positional argument: 'obj'.

令人驚訝的,如果我使用lambda來創建它的工作職能。

Position.__str__ = lambda x: pretty_float_pair('Position', ('x', 'y'), x) 
Vector.__str__ = lambda x: pretty_float_pair('Vector', ('x', 'y'), x) 
Size.__str__ = lambda x: pretty_float_pair('Size', ('width', 'height'), x) 
print(Position(math.pi, math.pi), Vector(math.pi, math.pi), Size(math.pi, math.pi)) 

打印我想要的東西:

Position(x=3.14, y=3.14) Vector(x=3.14, y=3.14) Size(width=3.14, height=3.14) 

我試圖理解爲什麼部分版本無法正常工作。

+0

你的功能不正常縮進。請修復。你可以用我的答案作爲參考。 –

+0

即使你的問題已經結束,你應該從已發佈的答案中選擇一個答案(假設它對你有幫助)。 –

回答

3

functools.partial返回可調用的非描述符,大致等效於未綁定的方法。這意味着它沒有被傳遞self參數,這與您所看到的錯誤一致。

由於lambda的行爲就像使用def定義的常規函數​​一樣,它實際上是一個描述符。 lambda的__get__方法返回一個綁定版本,該版本在實例中傳遞爲x

要獲得更像行爲方式的部分功能,請改爲使用functools.partialmethod。您必須將obj移動到參數列表的開頭,以便在綁定方法時可以接收self

這裏就是你們的榜樣:

 
from functools import partialmethod 

def pretty_float_pair(obj,name, labels): 
    """ 
    If labels = ('a', 'b') and object = (1.2345, 1.2345), returns: 
     name(a=1.23, b=1.23) 
    """ 
    return '{}({}={:.2f}, {}={:.2f})'.format(name, labels[0], obj[0], labels[1], obj[1]) 

Position.__str__ = partialmethod(pretty_float_pair, 'Position', ('x', 'y')) 
Vector.__str__ = partialmethod(pretty_float_pair, 'Vector', ('x', 'y')) 
Size.__str__ = partialmethod(pretty_float_pair, 'Size', ('width', 'height')) 

print(Position(math.pi, math.pi), Vector(math.pi, math.pi), Size(math.pi, math.pi)) 
1

功能通過被descriptors得到他們的隱含self說法:查找x.f結構,並返回記得x,以便其提供給f的方法對象。 functools.partial(...)不返回描述符,所以它沒有得到特殊的處理。 (它實際上是一個類,所以它「返回」它自己的一個實例。)

+1

因爲這是真的不會倒下,但你需要有一個解決方案來得到答案。現在,你最好只是有一個非常有見地的評論。 –

+0

@MadPhysicist:呃,問題中沒有問號,但是我寫這個來解決「我試圖理解爲什麼部分版本不起作用」。 –

+0

你是對的。 +1。 OP在他們的問題中有如此強烈的含義,我非常疲倦,我讀了一些與我腦中的實際問題截然不同的東西。謝謝你的收穫。 –

相關問題