试图用一个格式说明打印漂浮物将小于1不带前导零。 我想出了一个黑客位,但我认为有一种方法来在格式说明刚落前导零。 在文档中我找不到它。
问题
>>> k = .1337
>>> print "%.4f" % k
'0.1337'
劈
>>> print ("%.4f" % k) [1:]
'.1337'
试图用一个格式说明打印漂浮物将小于1不带前导零。 我想出了一个黑客位,但我认为有一种方法来在格式说明刚落前导零。 在文档中我找不到它。
问题
>>> k = .1337
>>> print "%.4f" % k
'0.1337'
劈
>>> print ("%.4f" % k) [1:]
'.1337'
您可以使用以下MyFloat
类,而不是内建的float
类。
def _remove_leading_zero(value, string):
if 1 > value > -1:
string = string.replace('0', '', 1)
return string
class MyFloat(float):
def __str__(self):
string = super().__str__()
return _remove_leading_zero(self, string)
def __format__(self, format_string):
string = super().__format__(format_string)
return _remove_leading_zero(self, string)
使用这个类,你将不得不使用str.format
功能代替模运算符(共%
)进行格式化。 下面是一些例子:
>>> print(MyFloat(.4444))
.4444
>>> print(MyFloat(-.4444))
-.4444
>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text .444 some more text
>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +.444 some more text
如果你也想使模运算符( %
)的str
类行为相同的方式,那么你就必须重写__mod__
的方法str
通过继承类类。 但它不会像重写一样容易__format__
的方法float
类,如在这种情况下,格式化浮点数可以存在于所得到的字符串中的任何位置。
[注:以上所有代码是用Python3。 您还可以覆盖__unicode__
在Python2,也必须改变super
电话。]
PS:您还可以覆盖__repr__
类似的方法来__str__
,如果你也想改变官方字符串表示的MyFloat
。
编辑 :其实你可以使用新的语法添加到格式刺痛__format__
方法。 所以,如果你想在需要的时候保持双方的行为,即显示前导零和不显示前导零时,没有必要。 您可以创建的MyFloat
如下类别:
class MyFloat(float):
def __format__(self, format_string):
if format_string.endswith('z'): # 'fz' is format sting for floats without leading the zero
format_string = format_string[:-1]
remove_leading_zero = True
else:
remove_leading_zero = False
string = super(MyFloat, self).__format__(format_string)
return _remove_leading_zero(self, string) if remove_leading_zero else string
# `_remove_leading_zero` function is same as in the first example
并使用这个类,如下所示:
>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text 0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(.4444)))
some text .444 some more text
>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +0.444 some more text
>>> print('some text {:+.3fz} some more text',format(MyFloat(.4444)))
some text +.444 some more text
>>> print('some text {:.3f} some more text',format(MyFloat(-.4444)))
some text -0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(-.4444)))
some text -.444 some more text
注意,使用的,而不是“F” FZ'删除前导零。
另外,上面的代码工作在两个Python2和Python3。
这里是另一种方式:
>>> ("%.4f" % k).lstrip('0')
'.1337'
它是略高于更一般的[1:]
,它也以数字> = 1的工作原理。
这两种方法都正确处理负数,但是。 以下是这方面做得更好:
>>> re.sub('0(?=[.])', '', ("%0.4f" % -k))
'-.1337'
不是特别优雅,但现在我想不出更好的方法。
虽然我很喜欢可爱的正则表达式的技巧,我想一个简单的功能做到这一点的最佳方式:
def formatFloat(fmt, val):
ret = fmt % val
if ret.startswith("0."):
return ret[1:]
if ret.startswith("-0."):
return "-" + ret[2:]
return ret
>>> formatFloat("%.4f", .2)
'.2000'
>>> formatFloat("%.4f", -.2)
'-.2000'
>>> formatFloat("%.4f", -100.2)
'-100.2000'
>>> formatFloat("%.4f", 100.2)
'100.2000'
这具有容易理解,部分原因是因为利益startswith
是一个简单的字符串匹配,而不是一个正则表达式。
它没有正则表达式和负数大于10工作的一个可行的选择
k = -.1337
("%.4f" % k).replace("-0","-").lstrip("0")
我宁愿去阅读和比什么都简单:让我们处理的符号和独立的NUMERICS。 和一点点的在线if语句从来没有伤害任何人。
k = -.1337
"".join( ["-" if k < 0 else "", ("%.4f" % abs(k)).lstrip('0')] )
import re
re.sub("^(\-?)0\.", r'\1.', "%.4f" % k)
这是短暂的,简单的,我找不到它不工作的情况。
例子:
>>> import re
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0.1337)
'.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 1.337)
'1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0.1337)
'-.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -1.337)
'-1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 10.337)
'10.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -10.337)
'-10.3370'
编辑 :如果你只考虑数字> -10和<10下面的工作:
("%.4f", k).replace('0.', '.')
使用.lstrip()
使用字符串格式化来转换为字符串后:
>>> k = .1827412
>>> print ("%.4f"%(k)).lstrip('0')
.1827
>>>
.lstrip()
可以被用来去除任何的字符串的前端字符:
>>> k = 'bhello'
>>> print k.lstrip('b')
hello
>>> print k.lstrip('bhel')
o
>>> print k.lstrip('bel')
hello
>>>
从文档 :
string.lstrip(S [,字符])
返回字符串的副本,主角删除
由于我们只考虑> -1 <1,则下面编辑将工作。
import re
re.sub(r"0+\.", ".", %0.4f" % k)
这将保持标志,只有消除数字到小数点的左侧。
我很惊讶没有人建议更多地以数学的方式来做到这一点:
n = 0.123456789
'.%d' % (n*1e4)
看起来更漂亮了我。 :)
但有趣的是你是最快的。
$ python -mtimeit '".%d" % (0.123456789*1e4)'
1000000 loops, best of 3: 0.809 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789)).lstrip("0")'
1000000 loops, best of 3: 0.209 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789))[1:]'
10000000 loops, best of 3: 0.0723 usec per loop
Python的标准库的str.format()可以被用于产生浮值的字符串转换。 然后,串可被操纵,以形成用于正或负号的最终结果。
n = -.1234567890
print('{0}'.format('-' if n < 0 else '') + ('{:0.4}'.format(n).split('-')[1 if n < 0 else 0].lstrip('0')))
当你想要的东西简单,不需要负数支持:
f'{k:.4f}'.lstrip('0')
还有,当你需要负数支持其他的解决方案,其中包括通过@ nettux443优秀的正则表达式。