我得到了一个包含4个变量的元组列表,每个变量将打印在一行中,我希望用户指定这些打印的格式。
到目前为止,这是我的代码:
mylist = [
("Monday", "13", "November", "2017"),
("Tuesday", "14", "November", "2017"),
("Wednesday", "15", "November", "2017")]
# Note: The real list have a thousand of items, not just 3.
custom_format = self.GUI_field_where_user_types.get_text()
for item in mylist:
weekday = item[0]
daynumber = item[1]
month = item[2]
year = item[3]
print(eval(custom_format))
# Example custom_format: '"{0}, {1} of {2} from year {3}".format(weekday, daynumber, month, year)'
对于测试,我只是尝试了上面的输入,它显然有效,但我不想使用eval,因为它显然太危险了。所以我的问题是:如何让用户以安全的方式定义格式?
注意:用户应该只能在.format()方法"{0}, {1} of {2} from year {3}"
之前编辑字符串,阻止访问任何python命令,但允许他只使用变量他想要的,并不总是他们中的4个。一些例子可能是:
答案 0 :(得分:2)
这很简单。只需在输入字符串上调用.format
,并使用参数解包语法将项目作为参数传递:
mylist = [
("Monday", "13", "November", "2017"),
("Tuesday", "14", "November", "2017"),
("Wednesday", "15", "November", "2017")]
fmt = input('Format? ')
for item in mylist:
print(fmt.format(*item))
执行:
Format? {0}, {1} of {2}
Monday, 13 of November
Tuesday, 14 of November
Wednesday, 15 of November
要处理用户输入无效格式,您可以捕获异常并重试:
while True:
try:
fmt = input('Format? ')
for item in mylist:
print(fmt.format(*item))
break
except (IndexError,ValueError,KeyError):
print('Invalid format.')
执行:
Format? {A}
Invalid format.
Format? {4}
Invalid format.
Format? {
Invalid format.
Format? The year is {3}
The year is 2017
The year is 2017
The year is 2017
答案 1 :(得分:0)
使用方法安排格式:
def fill_format(custom_format, date):
used_vars = []
used_indexes = []
#Look for what is used
for i in range(len(date)):
if "{"+str(i)+"}" in custom_format:
used_vars.append(date[i])
used_indexes.append(i)
#Replace indexes starting from 0
for new_index, used_index in enumerate(used_indexes):
custom_format = custom_format.replace("{"+str(used_index)+"}", "{"+str(new_index)+"}")
return custom_format.format(*used_vars)
mylist = [
("Monday", "13", "November", "2017"),
("Tuesday", "14", "November", "2017"),
("Wednesday", "15", "November", "2017")]
custom_format = "{3}, {1} at month {2}"
for item in mylist:
print(fill_format(custom_format, item))
输出:
2017, 13 at month November
2017, 14 at month November
2017, 15 at month November
修改强>
如果日期总是有4个时间单位,您可以使用:
def fill_format(custom_format, date):
return custom_format.replace("{0}", date[0]).replace("{1}", date[1]).replace("{2}", date[2]).replace("{3}", date[3])
答案 2 :(得分:0)
我的建议:坚持使用标准化的datetime
格式。使用datetime,我们可以使用强大的strftime根据一组预定义模式打印日期时间。考虑这个例子:
<meta name="description" content="{% page_attribute "meta_description" %}">
打印:
import datetime
mylist = [
("Monday", "13", "November", "2017"),
("Tuesday", "14", "November", "2017"),
("Wednesday", "15", "November", "2017")]
custom_format = "%A, %d of %B from year %Y"
for item in mylist:
# Create datetime object
dt = datetime.datetime.strptime('-'.join([*item]),"%A-%d-%B-%Y")
# Print with format
print(dt.strftime(custom_format))
如果您想创建自己的语言&#34;使用字典映射到标准字典。考虑这个例子:
Monday, 13 of November from year 2017
Tuesday, 14 of November from year 2017
Wednesday, 15 of November from year 2017
输出:
import datetime
import re
mylist = [
("Monday", "13", "November", "2017"),
("Tuesday", "14", "November", "2017"),
("Wednesday", "15", "November", "2017")]
d = {"WEEKDAY": "%A",
"DAYNUMBER": "%d",
"MONTH": "%B",
"YEAR": "%Y"}
input_ = "YEAR-%m-DAYNUMBER is equal to WEEKDAY, DAYNUMBER of MONTH from year YEAR"
# Use re library to change WEEKDAY --> %A and so on...
pattern = re.compile(r'\b(' + '|'.join(d.keys()) + r')\b')
custom_format = pattern.sub(lambda x: d[x.group()], input_)
for item in mylist:
# Create datetime object
dt = datetime.datetime.strptime('-'.join([*item]),"%A-%d-%B-%Y")
# Print with format
print(dt.strftime(custom_format))
使用最少的代码,您可以获得所需的所有灵活性。