python中的pro什么意思_python中的formatter的详细用法

今天抽空学习了一下python中的string service中的formatter的相关用法,主要是为了让自己的代码看起来更加和谐,因为很多java或者c语言过来的开发者都不怎么爱使用python的原生的字符串格式化工具,似乎大家都爱用下面的格式化工具

info = 'my name is %s I really enjoy %s' % ('younger', 'python')

现在我要学习使用更加python化的字符串格式化风格。

python的buildin字符串服务模块 [string](file:///Users/youngershen-mac-book-pro/Downloads/python-2.7.8-docs-html/library/string.html) 本身提供了一些字符串操作的工具类方法,其中包括一些经常会使用到的常量,和比较复杂的Formatter类,Template类,这里我要重点学习的就是string.Formatter类

[string.Formatter](file:///Users/youngershen-mac-book-pro/Downloads/python-2.7.8-docs-html/library/string.html#string-formatting)类中的方法:

format(format_string, *args, **kwargs)

format方法是string.Formatter类中的主要方法,它的参数是一个你需要去格式化的目标字符串,和一组需要去填充目标字符串的序列,比如字典和元组,format方法是对vformat方法的封装。

上面是我照文档的说明写的,其实Formatter.format方法和str.format并没有什么不同,他们的语法是通用的,只要学会一种就都会了,哪个更方便就用哪个

vformat(format_string, args, kwargs)

parse(format_string)

get_field(field_name, args, kwargs)

get_value(key, args, kwargs)

上面的这几个方法是互相调用的,所以一放在一起研究,其中Formatter.format 最终调用的是Formatter.vformat方法,测试程序如下

class Person(object):

name = 'default name'

def __init__(self, name = ''):

self.name = name

me = Person('younger')

data = [me]

s = "my name is {person[0].name:^30}"

formatter = String.Formatter()

formatter.format(s, data)

输出结果:

>>> formatter.format(s, person = data)

'my name is younger '

现在用Formatter.vformat方法

formatter.vformat(s, (), {'person' : data})

输出结果:

>>> formatter.format(s, person = data)

'my name is younger '

2个方法的结果是完全一样的,只是一个包装了另一个,再Formatter.vformat方法中必须有4个参数,中间的空元组和最后的空字典必须存在,因为Formatter.vformat的参数不是 (*args, **kwargs) 而是 (args, kwargs), 这是完全不一样的,没看清楚会悲剧的。

现在继续说上面4个方法的调用顺序, get_value调用了get_field, get_field调用parse, vformat调用了 get_value, 一般情况下我们只需要调用format就足够了,上面的4个方法都是给需要继承Formatter创建自己的格式化语法的时候来覆盖掉的,不过我们可以从这4个方法分析出很多东西。

我现在执行下面的程序

for i, v in enumerate(formatter.parse(s, start = 0)):

print i, v

结果会输出:

0 ('my name is ', 'person[0].name', '^30', None)

上面是返回的第1个编号为0的元组, 这4个值分别是

(literal_text, field_name, format_spec, conversion)

我们没有canversion, 所以第4项是None, 你也可以写上一个!r或者!s

这样的话字符串就变成了

s = "my name is {person[0].name!r:^30}"

前两项都很好理解,直接看字面就懂什么意思,第三项的意思是说格式化的时候的站位符,我这里用的是空,你也可以用星号,现在把s变成这样

s ="my name is {person[0].name!r:*^30}"

输出的结果是:

"my name is **********'younger'***********"

*号充当了占位符的作用

现在执行下面的程序:

for i ,v in enumerate(formatter.parse(s)):

temp = v

formatter.get_field(temp[1], (), {'person' : data})

输出结果为:

('younger', 'person')

用文档中的话来说就是 'object'和'used_key', 这个key和get_value中的key是相同的所以要调用get_value必须先调用get_field

下面继续执行代码

ret = formatter.get_value(formatter.get_field(temp[1], (), {'person':data})[1], (), {'person':data})

这个返回的 ret就是得到的对象,一个Person类型的list ,里面只有一个对象就是最初我们填充的那个,到此为止 , 所有的方法都跑了一遍,如果我们要改写自己的format语法,那就直接继承这个类,覆盖这么几个方法就行了,其余的2个方法很容易理解,可以直接看文档。

Formatter.format的语法

这里就不采用文档里的论道的方法来说明了,直接以我的理解来说好了

只有keyword类型的format string

最简单的:

"my name is {name}".format(name = 'younger')

带有多个组合条件的

"my name is {person[0].name!r:*^30}".format(person = data_list)

上面的意思是说传入的是一个list,list中有person, keyword是person[0].name, 很好理解,就是第0个对象的name属性, 这样用起来很方便, 非常好记, 从!r开始的奇怪语法是 Format Specification Mini-Language , 其中对一些数据类型,比如百分数,正负数, 复数, 大数,时间,小数点的位数,以及格式化format string的站位符等进行了定义,用法都和我写的例子一样,没有什么复杂的,这里例子已经算是比较复杂的例子了。

只有position类型的format string

"my name is {0.name}".format(person)

同时有position和keyword的formart string

"my name is {0.name}, I am living at {area[0].city}".format(person, area_list)

这里要注意的就是position的必须写再前面,不然是不能使用的,推荐大家一个格式化字符串里只用以个方式去写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的问题。你的意思是你在进行 logging 的二次封装时,发现在 Formatter 设置的 `filename` 参数输出的文件名不正确,对吗? 如果是这样,可能是因为在 Formatter 设置的 `filename` 参数也是默认使用 `__file__` 获得的当前模块的文件名,而不是你想要的被日志记录的文件名。 解决这个问题的方法是,你可以在自定义的 logging 函数,手动添加一个 `filename` 参数,并将其传递给 Formatter,而不是使用默认值。例如: ```python import logging def custom_logger(filename): logger = logging.getLogger(filename) logger.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y-%m-%d %H:%M:%S') file_handler = logging.FileHandler(filename + '.log') file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logger.addHandler(file_handler) return logger logger = custom_logger('my_module') logger.debug('This is a debug message') ``` 在上面的代码,我们在自定义的 logging 函数添加了一个 `filename` 参数,并将其传递给 FormatterFormatter 使用了 `% (asctime) s` 来添加记录时间,`%(name)s` 来添加 logger 名称,`%(levelname)s` 来添加日志级别,`%(message)s` 来添加日志消息。`%Y-%m-%d %H:%M:%S` 用于设置记录时间的格式。 这样,你就可以在调用 logging 函数时,指定要记录日志的文件名了。 希望这能帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值