我可以导入Python';s 3.6';将格式化的字符串文本(f字符串)转换为旧的3.x、2.x Python?
新的Python3.6f-strings对我来说似乎是字符串可用性的一个巨大飞跃,我很乐意在新项目中全身心地采用它们,这些项目可能会在旧的解释器上运行。2.7、3.3-3.5支持将非常好,但至少我希望在Python 3.5代码库中使用这些支持。如何导入3.6的格式化字符串文字供较老的解释器使用我可以导入Python';s 3.6';将格式化的字符串文本(f字符串)转换为旧的3.x、2.x Python?,python,string,f-string,Python,String,F String,新的Python3.6f-strings对我来说似乎是字符串可用性的一个巨大飞跃,我很乐意在新项目中全身心地采用它们,这些项目可能会在旧的解释器上运行。2.7、3.3-3.5支持将非常好,但至少我希望在Python 3.5代码库中使用这些支持。如何导入3.6的格式化字符串文字供较老的解释器使用 我知道像f“Foo is{age}{units}old”这样的格式化字符串文本不会破坏更改,因此不会包含在来自{uuuuu future\uuuuu import…调用的中。但是更改不是后端口的(AFAI
我知道像
f“Foo is{age}{units}old”
这样的格式化字符串文本不会破坏更改,因此不会包含在来自{uuuuu future\uuuuu import…调用的中。但是更改不是后端口的(AFAIK),我需要确保我用f字符串编写的任何新代码都只在Python3.6+上运行,这对于很多项目来说都是一个破坏者。不幸的是,如果你想使用它,你必须要求Python3.6+
,与矩阵乘法运算符@
和Python3.5+
相同,或者从
中产生(Python3.4+
)
这些更改了代码的解释方式,因此在旧版本中导入时会抛出语法错误。这意味着您需要将它们放在一个地方,使它们不会被旧python导入,也不会被eval
或exec
保护(我不推荐后两种!)
因此,是的,你是对的,如果你想支持多个python版本,你就不能轻松地使用它们。f字符串是由解释器在标记f
前缀时创建的-仅此功能就将扼杀任何兼容性机会
最接近的镜头是使用关键字格式,如
'Foo is {age} {units} old'.format(age=age, units=units)
在兼容性需求终止时,可以更容易地重构 将f字符串引入Python 2.7脚本。(根据文档,我假设为3.3-3.5。)
一旦您通过pip install future fstrings
安装了它,您必须在代码顶部放置一个特殊的行。这条线是:
# -*- coding: future_fstrings -*-
然后,您可以在代码中使用格式化字符串文字(f字符串):
# -*- coding: future_fstrings -*-
var = 'f-string'
print(f'hello world, this is an {var}')
以下是我使用的:
text = "Foo is {age} {units} old".format(**locals())
它解压缩(**
)由locals()
返回的dict,该dict将所有局部变量作为dict{variable\u name:value}
注意这不适用于在外部作用域中声明的变量,除非您使用非本地
(Python 3.0+)将其导入本地作用域
你也可以使用
text.format(**locals(),**globals())
在字符串中包含全局变量。我刚刚为f-string编写了一个后端编译器,名为。正如您所要求的,您可以在Python3.6flavor中编写f-string文本,并编译成一个兼容版本供最终用户运行,就像JavaScript一样
f2format
提供了一个智能但不完善的后端口编译器解决方案。它应使用str.format
方法替换f字符串文字,同时保持源代码的原始布局。你可以简单地使用
f2format/path/to/the/file\u或\u目录
这将重写所有Python文件。比如说,
var=f'foo{(1+2)*3:>5}bar{“a”,“b”!r}boo'
将转换为
var=('foo{:>5}bar{!r}boo')。格式(((1+2)*3),(“a”,“b”)
字符串连接、转换、格式规范、多行和Unicode都被正确处理。此外,f2format
将归档原始文件,以防出现语法漏洞。使用simpleeval的肮脏解决方案
import re
import simpleeval
test='_someString'
lst = ['_456']
s = '123123{lst[0]}{test}'
def template__format(template, context=None):
if context is None:
frame = inspect.currentframe()
context = frame.f_back.f_locals
del frame
ptn = '([^{]?){([^}]+)}'
class counter():
i = -1
def count(m):
counter.i += 1
return m.expand('\\1{%d}'%counter.i)
template = re.sub(ptn,string=s, repl= count)
exprs = [x[1] for x in re.findall(ptn,s)]
vals = map(simpleeval.SimpleEval(names=context).eval,exprs)
res = template.format(*vals)
return res
print (template__format(s))
我使用'str'.format(**locals())
已经有一段时间了,但过了一段时间之后,我才这样做,因为对于每个语句来说,额外的代码都有点麻烦
def f(string):
"""
Poor man's f-string for older python versions
"""
import inspect
frame = inspect.currentframe().f_back
v = dict(**frame.f_globals)
v.update(**frame.f_locals)
return string.format(string, **v)
# Example
GLOBAL = 123
def main():
foo = 'foo'
bar = 'bar'
print(f('{foo} != {bar} - global is {GLOBAL}'))
if __name__ == '__main__':
main()
使用dict()保存名称-值对
- 除了本线程中其他地方提到的方法(例如
format(**locals())
),开发人员还可以创建一个或多个python字典来保存名称-值对
- 对于任何有经验的python开发人员来说,这是一种显而易见的方法,但是很少有讨论明确地列举这个选项,可能是因为这是一种显而易见的方法
- 与不加选择地使用
locals()
相比,这种方法无疑是有利的,因为它不那么不加选择。它明确地使用一个或多个字典作为名称空间,用于格式化字符串
- Python3还允许解包多个字典(例如,
.format(**dict1,**dict2,**dict3)
…这在Python2.7中不起作用)
##初始指令
ddvars=dict()
##指定固定值
ddvars['firname']='Huomer'
ddvars['lasname']='Huimpson'
ddvars['age']=33
通过
##分配计算值
ddvars['comname']='{firname}{lasname}'。格式(**ddvars)
ddvars['reprself']=repr(ddvars)
ddvars['nextage']=ddvars['age']+1
通过
##创建并显示示例消息
mymessage='''
你好{firname}{lasname}!
今天你已经{age}岁了。
在你的下一个生日,你将是{nextage}岁!
''。格式(**ddvars)
打印(mymessage)
如果使用此方法,并假设年龄和单位已经是变量,那么将其写成'Foo is{age}{units}old.格式(age=age,units=units)
用于python2.7,这样在移动到python3.6时,它就可以快速更新为f'Foo is{age}{units}{old'
旧的“.format(**locals(),**globals())
?@MadPhysicast可以工作,但被认为形式不好,因为在format调用中包含了厨房水槽。@GringoSuave。同意,但这与实际f字串的计算方法非常接近。@Mad物理学家,不是真的,明确的设计目标是不这样做。字符串在编译时被解析为字符串和表达式部分,表达式部分是普通的
## init dict
ddvars = dict()
## assign fixed values
ddvars['firname'] = 'Huomer'
ddvars['lasname'] = 'Huimpson'
ddvars['age'] = 33
pass
## assign computed values
ddvars['comname'] = '{firname} {lasname}'.format(**ddvars)
ddvars['reprself'] = repr(ddvars)
ddvars['nextage'] = ddvars['age'] + 1
pass
## create and show a sample message
mymessage = '''
Hello {firname} {lasname}!
Today you are {age} years old.
On your next birthday you will be {nextage} years old!
'''.format(**ddvars)
print(mymessage)