2011-08-16 26 views
13

在最近写入一个类,我最初包括沿着如下的__repr__方法的一部分:包括格式化可迭代作为更大格式的字符串

return "{}({!r}, {!r}, {!r})".format(
       self.__class__.__name__, 
       self.arg1, 
       self.arg2, 
       self.arg3) 

重复该“{R!}”片断等,感觉如果我曾经为这堂课添加任何更多的论据,那么将会是非常乏味的。然而,对我而言,更强大的替代品并不会赢得任何优雅的奖品。与str.join

fmt = "{}(%s)" % ", ".join(["{!r}"]*3) 
return fmt.format(self.__class__.__name__, 
        self.arg1, 
        self.arg2, 
        self.arg3) 

格式化参数分别:

构建格式字符串编程

args = ", ".join(map(repr, [self.arg1, self.arg2, self.arg3])) 
return "{}({})".format(self.__class__.__name__, args) 

我用最后的例子目前实施的类,但我感兴趣的建议为替代方法(因为我不是特别满意上述任何选项)。

更新: 由斯内德的回答启发,我现在已经添加了以下效用函数的帮助模块:

def format_iter(iterable, fmt='{!r}', sep=', '): 
    return sep.join(fmt.format(x) for x in iterable) 

>>> format_iter(range(10)) 
'0, 1, 2, 3, 4, 5, 6, 7, 8, 9' 
>>> format_iter(range(10), sep='|') 
'0|1|2|3|4|5|6|7|8|9' 
>>> format_iter(range(10), fmt='{:04b}', sep='|') 
'0000|0001|0010|0011|0100|0101|0110|0111|1000|1001' 
>>> format_iter(range(10), fmt='{0.real}+{0.imag}j') 
'0+0j, 1+0j, 2+0j, 3+0j, 4+0j, 5+0j, 6+0j, 7+0j, 8+0j, 9+0j' 

UPDATE2: 我结束了添加第二个实用功能,几乎与Agf的答案中的一样相同:

def call_repr(name, *args): 
    return "{}({})".format(name, format_iter(args)) 

所以最初的冒犯__repr__函数现在看起来像:

def __repr__(self): 
    return call_repr(self.__class__.__name__, 
        self.arg1, 
        self.arg2) 

(是的,原来的构造函数的参数一个今天早些时候就走开了。)

回答

8

如果这是你要重复一个模式,我可能会使用:

# This is a static method or module-level function 
def argrepr(name, *args): 
    return '{}({})'.format(name, ', '.join(repr(arg) for arg in args)) 

def __repr__(self): 
    return argrepr(self.__name__, self.arg1, self.arg2, self.arg3) 

# This is a static method or module-level function 
def argrepr(*args): 
    return '(' + ', '.join(repr(arg) for arg in args) + ')' 

def __repr__(self): 
    return repr(self.__name__) + argrepr(self.arg1, self.arg2, self.arg3) 
+0

事实证明,我结束了这样做,只有''format_iter(args)''调用,而不是内联inv ''str.join'' – ncoghlan

8

我倾向于是,如果你不喜欢的代码,把它藏在一个函数:

def repr_all(*args): 
    return ", ".join(repr(a) for a in args) 


def __repr__(self): 
    args = repr_all(self.arg1, self.arg2, self.arg3) 
    return "{}({})".format(self.__class__.__name__, args) 
+0

接受,因为这是为我落得这样做(见更新) – ncoghlan

+0

直接灵感哦,被接受的答案有一段时间,直到我的解决方案演变为看起来更像是从AGF的建议:) – ncoghlan

0

我可能会不喜欢它:

def __repr__(self): 
    return "{0}({1})".format(
     type(self).__name__, 
     ", ".join(repr(arg) for arg in (self.arg1, self.arg2, self.arg3))) 

或:

_init_getter = operator.attrgetter('arg1', 'arg2', 'arg3') 
def __repr__(self): 
    return "{0}({1})".format(
     type(self).__name__, 
     ", ".join(repr(arg) for arg in self._init_getter(self)))