管理 python 字符串中的关键字参数:如何仅格式化一些参数并保持其他参数未格式化
Managing keyword arguments in python strings: how to format only some arguments and keep the others unformatted
我在理解字符串的 format()
方法的工作方式时遇到了一些麻烦。
假设我设置了一个带有关键字参数的字符串变量:
s = '{hello} {person_name}'
我可以将此值分配给另一个变量或打印它。在后一种情况下,结果将是 {hello} {person_name}
.
我还可以在打印 s
时使用 format()
方法并为关键字分配一些值:
print(s.format(hello='hello', person_name='Alice'))
在这种情况下,结果是 hello Alice
。当然,我也可以把它赋值给一个新的变量。
当我只想对一个关键字使用格式时,我的问题就出现了:
print(s.format(hello='hello'))
或
a = s.format(hello='hello')
两者都报错:
KeyError: 'person_name'
我希望能够 运行 像 :
s = '{hello} {person_name}'
a = s.format(hello='hello')
if something:
b = a.format(person_name='Alice')
else:
b = a.format(person_name='Bob')
print(b)
是否可以这样,或者我应该在使用 format()
时设置所有关键字吗?
在您的用例中,您可以考虑转义字符串中的 {person}
:
# double brace the person_name to escape it for the first format
s = '{hello} {{person_name}}'
a = s.format(hello='hello')
# a = 'hello {person_name}'
if something:
b = a.format(person_name='Alice')
# b = 'hello Alice'
else:
b = a.format(person_name='Bob')
# b = 'hello Bob'
print(b)
但是,使用此方法时,您需要遵循转义变量的明确顺序。也就是说,您必须先分配 hello
,然后分配 person_name
。如果您需要灵活处理事物的顺序,我建议在完全传递变量之前使用 dict
构造变量:
# dict approach
s = '{hello} {person_name}'
# determine the first variable
d = {'hello':'hello'}
... do something
d.update({'person': 'Alice'})
# unpack the dictionary as kwargs into your format method
b = s.format(**d)
# b = 'hello Alice'
这使您可以更灵活地处理事物的顺序。但是你必须只调用一次.format()
所有 你的dict
中提供的变量(至少它必须有一个默认值),否则它仍然会提高一个错误。
如果你想要更花哨,并希望能够在没有变量的情况下打印字段名称,你也可以制作自己的包装函数:
# wrapper approach
# We'll make use of regex to keep things simple and versatile
import re
def my_format(message, **kwargs):
# build a regex pattern to catch words+digits within the braces {}
pat = re.compile('{[\w\d]+}')
# build a dictionary based on the identified variables within the message provided
msg_args = {v.strip('{}'): v for v in pat.findall(message)}
# update the dictionary with provided keyword args
msg_args.update(kwargs)
# ... and of course, print it
print(message.format(**msg_args))
s = 'Why {hello} there {person}'
my_format(s, hello='hey')
# Why hey there {person}
my_format(s, person='Alice')
# Why {hello} there Alice
您可以通过修改字典理解中的 v
来确定您想要的默认显示(在没有变量的情况下)。
我认为您必须在使用 format()
时定义所有关键字。
我建议使用 *args
的不同方法:
def printHello(*args):
print(' '.join([arg for arg in args]))
printHello('hello', 'Alice')
# hello Alice
printHello('hello')
# hello
您可以向此函数发送任意数量的单词。
Is something like this possible or should I set all keywords when I use format()?
PEP-3101 说:
If the index or keyword refers to an item that does not exist, then an IndexError/KeyError should be raised.
所以是的,如果您要使用关键字,则必须全部指定。
根据PEP 3101 如果索引或关键字引用不存在的项目,则应提出IndexError/KeyError。
但是您可以像这样创建自己的自定义格式化程序class。
from string import Formatter
class MyStringFormatter(Formatter):
def get_value(self, key, args, kwds):
try:
return super().get_value(key, args, kwds)
except KeyError:
return "{%s}" % key
fmt = MyStringFormatter()
演示
s = "{hello} {person_name}"
keywords = {'hello': 'hello'}
a = fmt.format(s, **keywords)
print(a)
# This will print hello {person_name}
something = False
if something:
person_name = {'person_name': 'Alice'}
else:
person_name = {'person_name': 'Bob'}
b = fmt.format(a, **person_name)
print(b)
# This will print `hello Bob` if `something` is False, 'hello Alice' otherwise.
我在理解字符串的 format()
方法的工作方式时遇到了一些麻烦。
假设我设置了一个带有关键字参数的字符串变量:
s = '{hello} {person_name}'
我可以将此值分配给另一个变量或打印它。在后一种情况下,结果将是 {hello} {person_name}
.
我还可以在打印 s
时使用 format()
方法并为关键字分配一些值:
print(s.format(hello='hello', person_name='Alice'))
在这种情况下,结果是 hello Alice
。当然,我也可以把它赋值给一个新的变量。
当我只想对一个关键字使用格式时,我的问题就出现了:
print(s.format(hello='hello'))
或
a = s.format(hello='hello')
两者都报错:
KeyError: 'person_name'
我希望能够 运行 像 :
s = '{hello} {person_name}'
a = s.format(hello='hello')
if something:
b = a.format(person_name='Alice')
else:
b = a.format(person_name='Bob')
print(b)
是否可以这样,或者我应该在使用 format()
时设置所有关键字吗?
在您的用例中,您可以考虑转义字符串中的 {person}
:
# double brace the person_name to escape it for the first format
s = '{hello} {{person_name}}'
a = s.format(hello='hello')
# a = 'hello {person_name}'
if something:
b = a.format(person_name='Alice')
# b = 'hello Alice'
else:
b = a.format(person_name='Bob')
# b = 'hello Bob'
print(b)
但是,使用此方法时,您需要遵循转义变量的明确顺序。也就是说,您必须先分配 hello
,然后分配 person_name
。如果您需要灵活处理事物的顺序,我建议在完全传递变量之前使用 dict
构造变量:
# dict approach
s = '{hello} {person_name}'
# determine the first variable
d = {'hello':'hello'}
... do something
d.update({'person': 'Alice'})
# unpack the dictionary as kwargs into your format method
b = s.format(**d)
# b = 'hello Alice'
这使您可以更灵活地处理事物的顺序。但是你必须只调用一次.format()
所有 你的dict
中提供的变量(至少它必须有一个默认值),否则它仍然会提高一个错误。
如果你想要更花哨,并希望能够在没有变量的情况下打印字段名称,你也可以制作自己的包装函数:
# wrapper approach
# We'll make use of regex to keep things simple and versatile
import re
def my_format(message, **kwargs):
# build a regex pattern to catch words+digits within the braces {}
pat = re.compile('{[\w\d]+}')
# build a dictionary based on the identified variables within the message provided
msg_args = {v.strip('{}'): v for v in pat.findall(message)}
# update the dictionary with provided keyword args
msg_args.update(kwargs)
# ... and of course, print it
print(message.format(**msg_args))
s = 'Why {hello} there {person}'
my_format(s, hello='hey')
# Why hey there {person}
my_format(s, person='Alice')
# Why {hello} there Alice
您可以通过修改字典理解中的 v
来确定您想要的默认显示(在没有变量的情况下)。
我认为您必须在使用 format()
时定义所有关键字。
我建议使用 *args
的不同方法:
def printHello(*args):
print(' '.join([arg for arg in args]))
printHello('hello', 'Alice')
# hello Alice
printHello('hello')
# hello
您可以向此函数发送任意数量的单词。
Is something like this possible or should I set all keywords when I use format()?
PEP-3101 说:
If the index or keyword refers to an item that does not exist, then an IndexError/KeyError should be raised.
所以是的,如果您要使用关键字,则必须全部指定。
根据PEP 3101 如果索引或关键字引用不存在的项目,则应提出IndexError/KeyError。
但是您可以像这样创建自己的自定义格式化程序class。
from string import Formatter
class MyStringFormatter(Formatter):
def get_value(self, key, args, kwds):
try:
return super().get_value(key, args, kwds)
except KeyError:
return "{%s}" % key
fmt = MyStringFormatter()
演示
s = "{hello} {person_name}"
keywords = {'hello': 'hello'}
a = fmt.format(s, **keywords)
print(a)
# This will print hello {person_name}
something = False
if something:
person_name = {'person_name': 'Alice'}
else:
person_name = {'person_name': 'Bob'}
b = fmt.format(a, **person_name)
print(b)
# This will print `hello Bob` if `something` is False, 'hello Alice' otherwise.