Python 中的嵌套 f 字符串(第三个嵌套 f 字符串)
Nested f-strings in Python (Third nested f-string)
我需要将 json 转换为给定的 hcl 结构。有这个代码:
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
double_q = '"'
result = f"""
users = [
{''.join([
f'''{{
name = {double_q}{ d['name'] }{double_q},
pass = {double_q}{ d['pass'] }{double_q},
permissions = [
{''.join([f"{{ access = {double_q}{ d['permissions'][index]['access'] }{double_q}, role = {double_q}{ d['permissions'][index]['role'] }{double_q} }}," for index in range(len(d['permissions'])) ])}
]
}},
''' for d in user_dicts['users']
])}
]"""
print(result)
其中 returns 以下行:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
需要做什么才能在权限中的字典之间换行,同时保持空格数?即:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },
{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
我尝试将 f 字符串添加到 new_line 变量:
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
double_q = '"'
new_line = '\n'
result = f"""
users = [
{''.join([
f'''{{
name = {double_q}{ d['name'] }{double_q},
pass = {double_q}{ d['pass'] }{double_q},
permissions = [
{f'{new_line}'.join([f"{{ access = {double_q}{ d['permissions'][index]['access'] }{double_q}, role = {double_q}{ d['permissions'][index]['role'] }{double_q} }}," for index in range(len(d['permissions'])) ])}
]
}},
''' for d in user_dicts['users']
])}
]"""
print(result)
但是下一行从行首变成:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },
{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
快速修复
您在正确的轨道上,将 new_line
变量与 str.join()
一起使用。要保持空格数,只需将它们包含在 new_line
:
中
new_line = ' \n'
进一步思考
您可能想开始使用模板引擎,例如 Jinja。
优点
- 您无需担心(嵌套)f-strings
- 模板字符串看起来像您想要的输出(有点所见即所得)
- 空格控制很容易
缺点
- 您可能需要花一些时间学习如何使用模板引擎
你的例子,用Jinja
实现
要运行以下代码,需要安装jinja2
包
import jinja2
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
template_str = """
users = [
{% for user in users %}
{
name = "{{ user['name'] }}",
pass = "{{ user['pass'] }}",
permissions = [
{% for p in user['permissions'] %}
{ access = "{{ p['access'] }}", role = "{{ p['role'] }}" },
{% endfor %}
]
},
{% endfor %}
]
""".strip()
template = jinja2.Template(template_str, trim_blocks=True, lstrip_blocks=True)
users = template.render(user_dicts).replace("'", '"')
模板字符串 template_str
基本上是您想要的输出,加上一些特殊标记({% for ... %}
、{% endfor %}
、{{ ... }}
)。这些标记告诉引擎如何“填空”。
我需要将 json 转换为给定的 hcl 结构。有这个代码:
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
double_q = '"'
result = f"""
users = [
{''.join([
f'''{{
name = {double_q}{ d['name'] }{double_q},
pass = {double_q}{ d['pass'] }{double_q},
permissions = [
{''.join([f"{{ access = {double_q}{ d['permissions'][index]['access'] }{double_q}, role = {double_q}{ d['permissions'][index]['role'] }{double_q} }}," for index in range(len(d['permissions'])) ])}
]
}},
''' for d in user_dicts['users']
])}
]"""
print(result)
其中 returns 以下行:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
需要做什么才能在权限中的字典之间换行,同时保持空格数?即:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },
{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
我尝试将 f 字符串添加到 new_line 变量:
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
double_q = '"'
new_line = '\n'
result = f"""
users = [
{''.join([
f'''{{
name = {double_q}{ d['name'] }{double_q},
pass = {double_q}{ d['pass'] }{double_q},
permissions = [
{f'{new_line}'.join([f"{{ access = {double_q}{ d['permissions'][index]['access'] }{double_q}, role = {double_q}{ d['permissions'][index]['role'] }{double_q} }}," for index in range(len(d['permissions'])) ])}
]
}},
''' for d in user_dicts['users']
])}
]"""
print(result)
但是下一行从行首变成:
users = [
{
name = "test1",
pass = "password1",
permissions = [
{ access = "yes", role = "admin" },
{ access = "yes", role = "user" },
]
},
{
name = "test2",
pass = "password2",
permissions = [
{ access = "yes", role = "admin" },
]
},
]
快速修复
您在正确的轨道上,将 new_line
变量与 str.join()
一起使用。要保持空格数,只需将它们包含在 new_line
:
new_line = ' \n'
进一步思考
您可能想开始使用模板引擎,例如 Jinja。
优点
- 您无需担心(嵌套)f-strings
- 模板字符串看起来像您想要的输出(有点所见即所得)
- 空格控制很容易
缺点
- 您可能需要花一些时间学习如何使用模板引擎
你的例子,用Jinja
要运行以下代码,需要安装jinja2
包
import jinja2
user_dicts = { 'users': [ {'name': 'test1', 'pass': 'password1', 'permissions': [ {'access': 'yes', 'role': 'admin'}, {'access': 'yes', 'role': 'user'} ] }, {'name': 'test2', 'pass': 'password2', 'permissions': [ {'access': 'yes', 'role': 'admin'} ] } ] }
template_str = """
users = [
{% for user in users %}
{
name = "{{ user['name'] }}",
pass = "{{ user['pass'] }}",
permissions = [
{% for p in user['permissions'] %}
{ access = "{{ p['access'] }}", role = "{{ p['role'] }}" },
{% endfor %}
]
},
{% endfor %}
]
""".strip()
template = jinja2.Template(template_str, trim_blocks=True, lstrip_blocks=True)
users = template.render(user_dicts).replace("'", '"')
模板字符串 template_str
基本上是您想要的输出,加上一些特殊标记({% for ... %}
、{% endfor %}
、{{ ... }}
)。这些标记告诉引擎如何“填空”。