Python字符串格式:%vs连接

时间:2016-01-05 19:05:13

标签: python string string-formatting

我正在开发一个应用程序,我在其中执行一些请求以获取对象ID。在每一个之后,我调用一个方法(get_actor_info())将此id作为参数传递(参见下面的代码)。

ACTOR_CACHE_KEY_PREFIX = 'actor_'

def get_actor_info(actor_id):
    cache_key = ACTOR_CACHE_KEY_PREFIX + str(actor_id)

可以注意到,我正在将actor_id转换为string并将其与前缀连接起来。但是,我知道我可以通过多种其他方式(例如.format()'%s%d')来实现这一点,这导致了我的问题:在可读性方面,'%s%d'会比字符串连接更好吗? ,代码约定和效率?

由于

4 个答案:

答案 0 :(得分:11)

这很容易成为一个基于意见的线程,但我发现格式化在大多数情况下更具可读性,并且更易于维护。在不进行“精神连接”的情况下,更容易想象最终字符串的外观。例如,哪些更具可读性?

errorString = "Exception occurred ({}) while executing '{}': {}".format(
    e.__class__.__name__, task.name, str(e)
)

或者:

errorString = "Exception occurred (" + e.__class__.__name__
    + ") while executing '" + task.name + "': " + str(e)

至于是否使用%.format(),我可以更客观地回答:使用.format()%是“旧式”,根据Python Documentation,它们很快就会被移除:

  

由于str.format()很新,很多Python代码仍使用%运算符。但是,由于最终将从语言中删除这种旧格式,因此通常应使用str.format()

文档的后续版本已经停止提及这一点,但尽管如此,.format()是未来的方式;用它!

连接速度更快,但这不应该是一个问题。使您的代码可读和可维护作为第一线目标,然后优化您稍后需要优化的部分。过早优化是万恶之源;)

答案 1 :(得分:5)

在性能方面,连接更好。在您的示例中,连接和替换都是可读的,但是当涉及到更复杂的模板时,替换会赢得简单性和可读性竞争。

例如,如果您有数据并且想要在html中显示它,则连接会让您头疼,而替换将简单易读。

答案 2 :(得分:3)

Python 3.6将引入另一个选项:

ACTOR_CACHE_KEY_PREFIX = 'actor_'

def get_actor_info(actor_id):
    cache_key = f'{ACTOR_CACHE_KEY_PREFIX}{actor_id}'

效果应该与'{}{}'.format(ACTOR_CACHE_KEY_PREFIX, actor_id)相当,但可以说更具可读性。

答案 3 :(得分:0)

我猜想,如果要连接的所有术语都是常量,则可以通过python优化与+运算符的连接以提高性能。例如:

DB_PREFIX = 'prod_'
INDEX_PREFIX = 'index_'

CRM_IDX_PREFIX = DB_PREFIX + INDEX_PREFIX + 'crm_'

但是大多数情况下,格式函数和运算符用于连接变量内容。例如:

crm_index_name = "{}_{}".format(CRM_IDX_PREFIX, index_id)

实际上,如果您使用+运算符进行连接,如下所示:

crm_index_name = CRM_IDX_PREFIX + '_' + str(index_id)

您正在通过自定义代码以固定方式定义格式。如果您使用带有命名引用的格式字符串,则代码更具可读性。例如:

crm_index_name = "{db_prefix}_{idx_prefix}_{mod_prefix}_{id}".format(
   db_prefix=CRM_IDX_PREFIX,
   idx_prefix=INDEX_PREFIX,
   mod_prefix='crm',
   id=index_id,
)

这样,您就可以将格式定义为常量。例如:

IDX_FORMAT = "{db_prefix}_{idx_prefix}_{mod_prefix}_{id}"

crm_index_name = IDX_FORMAT.format(
   db_prefix=CRM_IDX_PREFIX,
   idx_prefix=INDEX_PREFIX,
   mod_prefix='crm',
   id=index_id,
)

如果将来需要更改格式,此结果将更加清楚。 例如,要更改分隔符的顺序,您只需更改 将字符串格式化为:

IDX_FORMAT = "{db_prefix}_{mod_prefix}_{idx_prefix}-{id}"

此外,为了进行调试,您可以将所有这些变量分配给字典,并将其作为关键字参数传递给format函数:

idx_name_parts = {
   'db_prefix': CRM_IDX_PREFIX,
   'idx_prefix': INDEX_PREFIX,
   'mod_prefix': 'crm',
   'id': index_id,
}
crm_index_name = IDX_FORMAT.format(**idx_name_parts)

利用globals()函数,我们还可以:

IDX_FORMAT = "{CRM_IDX_PREFIX}_{mod_prefix}_{INDEX_PREFIX}-{index_id}"

crm_index_name = IDX_FORMAT.format(mod_prefix = 'crm', **globals())

这类似于python3的formatted string literal

crm_index_name = f"{CRM_IDX_PREFIX}_crm_{INDEX_PREFIX}-{index_id}"

我还将 Internationalization 视为另一个使用上下文,其中格式化表达式比+运算符更有用。输入以下代码:

message = "The account " + str(account_number) + " doesn't exist"

如果您将gettext module之类的翻译功能与+运算符一起使用,它将是:

message = _("The account ") + str(account_number) + _(" doesn't exist")

因此最好翻译整个格式的字符串:

message = _("The account {account_number} doesn't exist").format(account_number)

以便完整的消息在西班牙语翻译文件中更具意义:

#: main.py:523
msgid "The account {account_number} doesn't exist"
msgstr "La cuenta {account_number} no existe."

这对于将自然语言的语法强加改变的自然语言翻译特别有用,例如 german 语言。