python修改模板对象的属性_Python中string.Template模板对象的使用时机、方法及如何自定义...

上篇内容我们详细介绍了将Python中的字符串首字母改为大写的三种方式(罗马不是一天建成的,要日积月累,Python字符串处理你掌握了没?)。其中,我们提到了在string模块有一个创建模板的方法。今天,我们详细了解一下如何使用string模块创建一个自定义的模板类。

908fa0ec08fa513d5d92c21f2017abfeb3fbd9b3.jpeg?token=acaeded974498494c46909043603a03d&s=6D82E41F1962C5050F4075D20300C0B3简单的模板可以使程序更可读、更高效

理解模板定义的时机

我们在程序中经常会遇到这样的需求:

有一个字典,记录了某学生的信息,如下:

stuInfo = {'ID': '000120', 'name': 'Lucy', 'age': 18, 'home_addr': 'BeiJing', 'final_score': 98}

程序要求我们将这个信息输出成这样:

【学号】000120

【姓名】Lucy

【年龄】18

【地址】BeiJing

【成绩】98

738b4710b912c8fcaaab8762e2796c40d7882140.jpeg?token=3ca5824d04f939919d88d222a037f1e5&s=4452C53A4F65790BD057D44F0300F0F9以学生信息格式化输出为例

看过前面章节内容的小伙伴肯定知道,使用format()和'%'都可以实现这样的需求。但是这两种方式都是通过函数(方法)实现的。

9213b07eca806538aa92374989a75f41ac3482f4.jpeg?token=ed05444d53c92448c1fa02418bd59aad&s=120A964593C550FEDAD5E1F003004037如何更精准

假设我们上面格式化的字符串,要在程序中的多个位置使用。此时,我们不可能每次用到上面这串格式化的内容时,都在程序中添加一大串的格式化输出代码。这样,不仅增加了程序的代码量,且会无形中增加了程序的维护难度,有没有代码简化方案?再者,上面的ID、name、age、home_addr、final_score属性对应我们格式化字符串中的学号、姓名、年龄、地址、成绩,每次输出改变的是这些属性的值,如果有一个数据结构(类似)能够像工厂中流水线生产产品一样,只要我们送入原材料(值),它就像机器一样按照指定数量一个个将产品给我们输出出来,这样岂不是更好?假设我们程序的某个地方只需要变量中有下划线的属性:如'home_addr'和'final_score',但是,我们已经定义好了这种输出结构。现在该如何处理呢(我们将这种输出结构定义为一个类,那么只需要修改类属性即可解决这个问题)?此时,定义一个模板就是最佳方案(对于什么是模板,这里就不在粘贴它的定义了)。

30adcbef76094b36e4993ffbbdb682dc8d109d18.jpeg?token=5e52da3e46b70cbc015294fec3c2cae4&s=8C91A254F0F87D8C3FFCFD53020030F3想知道的自己搜索吧

如何实现上面的需求

上面也讲了,我们可以使用三种方式来实现它

279759ee3d6d55fbd4ccf0277358b14f20a4dd2d.jpeg?token=e7371762980a27fed54c3c29b654adf1&s=E382D601124406E887016595030050E0探讨实现方法

format函数实现

s = "【学号】: {ID}\n【姓名】: {name}\n【年龄】:{age}\n【地址】:{home_addr}\n【成绩】:{final_score}"

print("Format:", s.format(**stuInfo))

'%'实现

s = '''【学号】: %s\n【姓名】: %s\n【年龄】:%s\n【地址】:%s\n【成绩】:%f"

print(s % (stuInfo['ID'], stuInfo['name'], stuInfo['age'], stuInfo['home_addr'], stuInfo['final_score']))

string.Template实现

t = string.Template("【学号】: $ID\n【姓名】: $name\n【年龄】:$age\n【地址】:$home_addr\n【成绩】:$final_score")

print(t.substitute(stuInfo))

从上面很容易看出

对于'%'它具有格式化输出的作用,但是在对其传值时,必须提供变量的类型,这也是其容易出错的原因,很多时候,我们并不需要依次判断变量的类型;

format()函数相对灵活,它不仅提供了格式化输出功能,还能实现模板的一些功能,而且它传入的数据也没有验证数据类型;

Template模板虽然没有进行类型验证,但是它使用面向对象的方式很好的解决了这一问题。

Template模板使用

如何使用Template模板呢?

5882b2b7d0a20cf4faf541976873b533adaf9995.jpeg?token=0ede60cf756af60ed5316a55893bf597&s=8152CD336D51F219565D85C10300E0B3如何操作呢?

# 导入模块

from string import Template

# 创建模板(此时就生成了一个模板对象,类似工厂里面的机器,但是这个机器还没有给它提供原材料,它还生产不出产品来)

t = Template("【学号】: $ID\n【姓名】: $name\n【年龄】:$age\n【地址】:$Addr\n【成绩】:$Score")

# 生成内容(传入数据)

r = t.substitute(stuInfo)

# 输出结果

>>>print(r)

【学号】: 000120

【姓名】: Lucy

【年龄】:18

【地址】:BeiJing

【成绩】:98

Template类在这里没有进行格式化输出,但是它比较'%'更具有灵活性。

此时,假设程序员在字典中没有将'Score'的内容传入到模板中,程序就会抛出KeyError异常。如果我们不想它抛出异常,可以使用safe_substitute(stuInfo),它会输出这样的内容(直接将变量名称输出出来)

【学号】: 000120

【姓名】: Lucy

【年龄】:18

【地址】:BeiJing

【成绩】:$Score

模板的高级特性

我们先来看下Template提供了哪些属性可供我们使用,还是上面的例子

7af40ad162d9f2d3f31977f8b79674166327cc19.jpeg?token=4e4d1563d33a515c0c31a3c865f90407&s=53AB9F455E5144C6DA058CE60300E013深入探究

template:输出模板内容。

>>>print(t.template)

【学号】: $ID

【姓名】: $name

【年龄】:$age

【地址】:$Addr

【成绩】:$Score

会将模板原样输出,format和'%'可没有这样的功能哦

delimiter:变量标识符,默认使用"$",当然我们也可以修改它

pattern:模板替换规则,它返回一个正则表达式的字符串形式编译出来的pattern实例,其实就是等价于pattern = re.compile(reg)。它是模板的匹配模式,它必须包含4个命名组(捕获转义定界符、变量名称、加括号的变量名、不合法的定界符模式),具体是哪些东西,下文会涉及。对于re模块不熟悉的小伙伴抓紧时间学习哦!先看一下pattern默认的样子

re.compile('

\$(?:

(?P\$) | # 两个分隔符的转义序列

(?P(?a:[_a-z][_a-z0-9]*)) | # 分隔符和Python标识符,查找变量名的模式

{(?P(?a:[_a-z][_a-z0-9, re.IGNORECASE|re.VERBOSE)

整个模板都是通过这个re模块完成内容匹配的,比如我们上面定义的模板变量名前面加了"$"符,就是通过这个正则表达式来匹配的,甚至于我们匹配的变量名称默认使用这个正则表达式:(?P(?a:[_a-z][_a-z0-9]*))

idpattern:查找变量名的匹配模式

>>>print(t.idpattern)

(?a:[_a-z][_a-z0-9]*)

常用的属性都在这里了。Template模板的强大之处就是通过这些属性来体现的。

如何自定义一个模板

使用下面的方法自定义一个模板类,改变模板匹配规则。

d000baa1cd11728b6cf5c63dd6863dcbc2fd2c50.jpeg?token=609475faec4a180f3da0247261a32af7&s=E7E8BB54C898BFE946881D470300C062如何自定义一个模板类?

import string

class MyTemplate(string.Template): # 继承模板类

delimiter = "%"

idpattern = '[a-z0-9]*'

这样我们就自定义好了一个模板对象,模板中变量名以"%"开始,并且,变量名称如果是英文字符和0-9数字的都是可以匹配到的。

解决上面的问题

我们在讨论其应用时机时,提出了一个需求,就是加下划线的home_addr和final_score两个属性不需要匹配输出,那么,我们该如何解决呢?

9345d688d43f879438c06517cc61f0f11bd53a4f.jpeg?token=60b8779e342c9f0aca8d89cf40fd8fe0&s=0905CF1019B0C5EF181831D7030050A0解决问题

import string

class MyTemplate(string.Template): # 继承模板类

idpattern = '[a-z]+_[a-z]+'

可以通过自定义一个模板类的方式对模板中变量进行进一步筛选。

t = MyTemplate('''

【学号】: %ID

【姓名】: %name

【年龄】:%age

【地址】:%home_addr

【成绩】:%final_score

''')

>>>print(t.safe_substitute(stuInfo))

【学号】: %ID

【姓名】: %name

【年龄】:%age

【地址】:BeiJing

【成绩】:98

成功匹配到了变量名中带有下划线的变量(为了区别将前面三个属性也加上去了,具体应用时可直接去除)。

好了,今天的内容就到这里了,我们通过一个案例,详解了Python中Template模板对象的使用时机及方式。对于模板中re模块的匹配不是很理解的小伙伴们抓紧时间学习re模块哦。当然,我们后续内容也会涉及re模块的使用问题,对Python感兴趣的小伙伴们关注我,后续会推出更加精彩的内容。大家也可以在下方留下宝贵的意见建议。我们一起学习、进步……

转载请注明出处,百家号:Python高手养成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值