2017-09-24 79 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在他们的问题中有如此强烈的含义,我非常疲倦,我读了一些与我脑中的实际问题截然不同的东西。谢谢你的收获。 –