前言:

Python有几种方法可以显示程序的输出;数据可以以人类可读的形式打印出来,或者写入文件以供将来使用。

在开发应用程式时我们往往会需要把变数进行字串格式化,也就是说把字串中的变数替换成变量值。事实上,在 Python 中有许多方式可以进行,其中最常见的有四种方式:

  1. 旧式字串格式化
  2. 新式字串格式化
  3. 字串插值
  4. 样板字串

字串插值是在 Python 3.6 之后有支援的方法,若是你的版本是在 Python 3.6 之后的话建议可以使用。若是需要让使用者可以输入变数来转换成字串格式化的话,建议可以使用样板字串来避免一些资讯安全上的问题。

以下就上述提到的四种方法来各自说明其特色和使用方式:

旧式字串格式化(%)

相对于Python 版本之后推荐使用的新式字串格式化,旧式版本使用 % 运算子来进行字串格式化,若是有C 语言撰写经验的读者或许会觉得的似曾相似(是不是有点像 printf ?) 。使用 % 格式是告诉 Python 直译器要在那边替换文字 text 并使用字串呈现。这就是所谓的旧式字串格式化(%s 是以字串输出,%f 是以浮点数输出、%d 是以十进位整数输出):

text = 'world'
print('hello $s' % text)
# hello world

若是希望把內容轉成十六進位的話可以使用:

print('%x' % 23)
# 17

若是有多個變數要替換則使用 tuple 傳遞需要替代的內容值:

print('hello %s %s' % ('world', 'go'))
# hello world go

新式字串格式化(format())

在Python3以后,开始引入新串格式化,也就是使用 format()函式来让字串格式化,其功能和旧式格式化相差无几,但主要是舍去 让字串格式化使用上可以更加 正常,正常,预期性也相对提升。

一般基本用法:

text = 'world'
print('hello {}'.format(text))
# hello world

也可以使用名称来指定变数变换顺序:

name = 'Jack'
text = 'world' print('hello {name}, hello {text}'.format(name=name, text=text))
# hello Jack, hello world

若是希望把内容转成十六进位的话可以使用 format spec 在 {} 新增 :x

更漂亮的输出格式:字串插值(Formatted String Literal)

虽然已经有了新式字串格式化,而在Python 3.6又添加了格式字串字面值(Formatted String Literal)此一作法可以把Python运算式嵌入在字串常数中。

眼尖的读者可能会发现,咦,怎么跟隔壁棚的 JavaScript ES6字串模版有点像呀?

现在我们来看一下一般的使用方式:

text = 'world'
print(f'Hello, {text}')

新的字串插值语法相当强大的点是,可以在里面嵌入任何 Python的运算式,表示来说,我们想要呈现整数相加:

x = 10
y = 27 print(f'x + y = {x + y}')
# 37

同样,若是希望把内容转成十六进位的话可以使用 format spec 在 {} 新增 :x

print('{:x}'.format(23))
# 17

读者可能会觉得很字串插值神奇,但实际上其背后原理是由Python语法解析器把f-string字串插值格式字串转成一连串的字串常数和运算式,最后结合成最终的字串 。

def hello(text, name):
return f'hello {text}, hello {name}' # 实际上Python会把它变成字串常数和变数(过程中有优化) def hello(text, name):
return 'hello ' + text + ', hello' + name

模板字串(Template String)

模板字串(Template String)机制相对简单,也比较安全。

以下是一般的使用情境,需要从Python内建模组string 引入:

from string import Template

text = 'world'
t = Template('hello, $text')
t.substitute(text=text)
# hello, world

然而若是希望把内容变成成十六进位的话需要自己使用hex函式自己转换:

from string import Template

number = 23
t = Template('hello, $number')
t.substitute(number=hex(number))
# hello, 0x17

由于其他的字串格式化功能强大,所以反而会造成恶意用户输入变数替换成字串时造成不可预期的错误(一般来说使用者的输入都是不可信的,要进行过滤)。

体现为恶意使用者可能可以透过字串格式的恶意输入来获取敏感资讯(例如:密码,令牌,金钥等)?

SECRET_TOKEN = 'my-secret-token'

# Error func
class Error:
def __init__(self):
pass err = Error()
malicious_input = '{error.__init__.__globals__[SECRET_TOKEN]}'
malicious_input.format(error=err)
# my-secret-token

没想到,透过字串格式的方式竟然可以透过 __globals__ 字典检索我们的SECRET_TOKEN,若是一不留神,很可能机密资料就泄漏出去。此时若是使用范本String发生错误,是比较安全的选项 :

from string import Template

SECRET_TOKEN = 'my-secret-token'

# Error func
class Error:
def __init__(self):
pass err = Error()
malicious_input = '${error.__init__.__globals__[SECRET_TOKEN]}'
t = Template(malicious_input)
t.substitute(error=err)
# ValueError: Invalid placeholder in string: line 1, col 1

总结

虽然Python相信是能用简单唯一的方式来完成任务,而字串格式化却有多种方式,也各有其优缺点,其本身或许在于版本不同变迁所致。所以你有可能在公司内部 专案不同专案看到使用不同的字串格式化方式,若是看到同一个专案使用不同字串格式化方式也不要混淆。

一般情况我们会根据不同Python版本和使用情境去使用不同字串格式化方式,例如:若是使用Python 3.6之后的话建议可以使用字串插值,若版本比3.6旧,则使用新式字串格式化(format ())。若是需要让使用者可以输入变数来转换成字串格式化的话,建议可以使用样板字串来避免一些资讯安全上的问题。

參考文件

  1. python string — Common string operations
  2. (那些過時的) Python 字串格式化以及 f-string 字串格式化
  3. 字串格式化
  4. Python String Formatting Best Practices
  5. Python 字串格式化教學與範例
  6. A Quick Guide to Format String in Python
  7. 菜鸟教程python格式化问题

如何使用 Python 進行字串格式化的更多相关文章

  1. Python 字串处理

    #!/usr/bin/python #-*- coding:utf-8 –*- import os import sys import re import shutil import xlrd imp ...

  2. python之字串

    python字串声明: 单引('), 双引("), 三引(''' 或 """"). python字串前缀: r表示原生字串, 字串内容: (1)不能包 ...

  3. 动态规划--求最大连续子数组的和(Python实现)&求解最大连续乘积字串(Python实现)

    def MaxSum(self,array,n): sum=array[0] result=array[0] for i in range(0,n): if sum<0: sum=a[i] el ...

  4. python笔记--2--字符串、正则表达式

    字符串 ASCII码采用1个字节来对字符进行编码,最多只能表示256个符号. UTF-8以3个字节表示中文 GB2312是我国制定的中文编码,使用1个字节表示英语,2个字节表示中文:GBK是GB231 ...

  5. 孤荷凌寒自学python第九天Python的输出print的格式化

    孤荷凌寒自学python第九天Python的输出print的格式化 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) (今天感觉手写笔记整得清楚些,汇总电子 笔记时,自己思路凌乱了,练习过程也还 ...

  6. char s[]字串和char *s字串有什麼区别?

    C語言有兩種字串宣告方式char s[]和char *s,兩者有什麼差異呢? Introduction char s[] = "Hello World"; (只是用字符串常量初始化 ...

  7. #Windows Phone:在HTML5专案中,如何从Javascript传送字串到C#的APP端

    原文:#Windows Phone:在HTML5专案中,如何从Javascript传送字串到C#的APP端 #Windows Phone:在HTML5专案中,如何从Javascript传送字串到C#的 ...

  8. Python用类实现串以及对串的方法进行单元测试

    串是一种常见的数据结构,这里使用Python定义类来实现相应的方法.先看代码,再对相关知识进行讲解. # coding=utf-8 __all__=['ADTString'] class ADTStr ...

  9. Python第一行代码

    Python版本:Python 3.6.1 0x01 命令行交互 在交互式环境的提示符>>>下,直接输入代码,按回车,就可以立刻得到代码执行结果.现在,试试输入100+200,看看计 ...

随机推荐

  1. Json解析方式汇总 excel vba

    一. 这种方式比较复杂,因为office版本的原因,所以要加其它函数 Private Function parseScript(strJson As String) Dim objJson As Ob ...

  2. [CSP-S2019]树的重心 题解

    CSP-S2 2019 D2T3 考场上扔了T2来打这题的部分分,然后没看到数据范围是等号,不知道怎么判完全二叉树然后40分滚粗…… ---- 思路分析 很容易想到$O(n^2)$每次暴力找重心,这个 ...

  3. SEO外包好还是自己组建团队

    http://www.wocaoseo.com/thread-151-1-1.html       营络营销已成为企业不可忽视的一块大肥肉,很多企业都想进来分一杯羹,但是不少企业苦于缺少过硬的技术,无 ...

  4. Min Cost Climbing Stairs [746]

    Min Cost Climbing Stairs [746] 题目描述 简单来说就是:要跳过当前楼梯需要花费当前楼梯所代表的价值cost[i], 花费cost[i]之后,可以选择跳一阶或者两阶楼梯,以 ...

  5. wampserver64 apache2.4版本局域网互相访问总结

    wampserver64  apache2.4版本局域网互相访问总结 背景:在我的电脑上给算法组开发了一个工具,需要在局域网环境下其他同事都能访问到,搞了一下午终于搞定,于是整理了这篇文档,给其他同行 ...

  6. linux系统工程师修改打开文件数限制代码教程。服务器运维技术

    提示linux文件打开错误,修改linux打开文件数参数. /etc/pam.d/login 添加 session required /lib/security/pam_limits.so 注意看这个 ...

  7. 初学WebGL引擎-BabylonJS:第8篇-阴影网格与活动

    [playground]-shadows(阴影) 源码 var createScene = function () { var scene = new BABYLON.Scene(engine); / ...

  8. 面试【JAVA基础】多线程

    本次整理的内容如下: 1.进程与线程的区别 进程是一个可执行的程序,是系统资源分配的基本单位:线程是进程内相对独立的可执行单元,是操作系统进行任务调度的基本单位. 2.进程间的通信方式 2.1.操作系 ...

  9. vue 页面首次加载缓慢原因及解决方案

    第一次打包vue的项目部署到服务器,发现首次加载特别的缓慢要几十秒才加载出来,完全没有在本地开发环境上那么流畅. 主要原因是页面在打包后没有进行相关的配置导致资源文件特别大,一次想要全部加载完成回特别 ...

  10. java向上转型神解析

    向上转型 经典案例 向上转型 向上转型应注意的问题 向上转型的好处 静态方法的调用 经典案例 public class Animal { public void eat(){ System.out.p ...