私信  •  关注

dreftymac

dreftymac 最近创建的主题
dreftymac 最近回复了
4 年前
回复了 dreftymac 创建的主题 » python:无法格式化类似json的字符串[duplicate]

使用自定义占位符标记 Jinja2

上下文

  • 巨蟒3.x
  • 替代品 string.format()
  • 这种方法使用 金贾2 为了提高性能的灵活性和额外的Python依赖性

我们希望在python中使用自定义占位符分隔符 str.format()

  • string.format() 功能强大,但不支持占位符分隔符修改。
  • string.format() Delimiter collision
  • string.format() 默认的解决方法是将分隔符加倍。 这可能会很麻烦,因为它需要更改原始源代码,而更改默认占位符分隔符可能更直接。

解决方案

金贾2 作为python的替代 str.格式()

  • 将jinja2作为附加依赖项导入
  • 用一个定制类包装jinja2,使sytnax与
  • 允许其他增强功能,如自定义函数和筛选器

优势

缺点

  • 内置python的性能更低 str.format
  • Jinja2有着与纯python不同的调试经验

示例:基于自定义Jinja2的演示使用 可供替代的

  • 我们写了一个习惯 TPLjinja 使Jinja更像python的类
# import custom class
import TPLjinja
import textwrap
#;;

# prepare source data
ddmydata = dict()
ddmydata['fname'] = 'Huomer'
ddmydata['lname'] = 'Huimpson'
ddmydata['motto'] = 'I love donuts!'
#;;

# prepare template
sgtemplate = textwrap.dedent('''\
Hello @{fname} @{lname}!
We love your motto: ```@{motto}``` and we agree with you!
''')
#;;

# show output
vout = TPLjinja(template=sgtemplate,delimiter="@",wrap="{").format(**ddmydata)
print(vout)
#;;

# show how easy it is to change the delimiter syntax
# vout = TPLjinja(template='''Hello $<fname> !''',delimiter="$",wrap="<").format(**ddmydata)
# vout = TPLjinja(template='''Hello ~(fname) !''',delimiter="~",wrap="(").format(**ddmydata)
# vout = TPLjinja(template='''Hello &<%fname%> !''',delimiter="&",wrap="<%").format(**ddmydata)
#;;

另见

6 年前
回复了 dreftymac 创建的主题 » 在python3中如何将单词向后翻转?在这种情况下[副本]

快速回答(tl;dr)

例子

### example01 -------------------
mystring  =   'coup_ate_grouping'
backwards =   mystring[::-1]
print backwards

### ... or even ...
mystring  =   'coup_ate_grouping'[::-1]
print mystring

### result01 -------------------
'''
gnipuorg_eta_puoc
'''

详细答案

背景

提供此答案是为了解决@odigty提出的以下问题:

真的。起初我对保罗提出的解决方案感到震惊,但是 坐在后座上看第一本书时我感到很害怕 点评:“那是非常蟒蛇。干得好!”我很不安 一个聪明的群体认为用这种神秘的方法 基本的是个好主意。为什么不只是s.reverse()?

问题

  • 语境
    • Python 2 x
    • Python 3 x
  • 脚本:
    • 开发人员希望转换字符串
    • 转换是将所有字符的顺序颠倒

解决方案

陷阱

  • 开发人员可能希望 string.reverse()
  • 土生土长的成语 pythonic )解决方案可能对新开发人员不可读
  • 开发人员可能会尝试实现自己的版本 string.reverse() 以避免切片符号。
  • 在某些情况下,切片表示法的输出可能与直觉相反:
    • 参见示例02
      • print 'coup_ate_grouping'[-4:] ## => 'ping'
      • 相比于
      • print 'coup_ate_grouping'[-4:-1] ## => 'pin'
      • 相比于
      • print 'coup_ate_grouping'[-1] ## => 'g'
    • 索引的不同结果 [-1] 可能会让一些开发人员失望

理论基础

python有一个特殊的情况需要注意:字符串是 iterable 类型。

排除 string.reverse() 方法是让python开发人员有动力利用这种特殊情况的能力。

简而言之,这仅仅意味着字符串中的每个字符都可以作为元素顺序排列的一部分轻松操作,就像其他编程语言中的数组一样。

为了理解这是如何工作的,回顾example2可以提供一个很好的概述。

例02

### example02 -------------------
## start (with positive integers)
print 'coup_ate_grouping'[0]  ## => 'c'
print 'coup_ate_grouping'[1]  ## => 'o' 
print 'coup_ate_grouping'[2]  ## => 'u' 

## start (with negative integers)
print 'coup_ate_grouping'[-1]  ## => 'g'
print 'coup_ate_grouping'[-2]  ## => 'n' 
print 'coup_ate_grouping'[-3]  ## => 'i' 

## start:end 
print 'coup_ate_grouping'[0:4]    ## => 'coup'    
print 'coup_ate_grouping'[4:8]    ## => '_ate'    
print 'coup_ate_grouping'[8:12]   ## => '_gro'    

## start:end 
print 'coup_ate_grouping'[-4:]    ## => 'ping' (counter-intuitive)
print 'coup_ate_grouping'[-4:-1]  ## => 'pin'
print 'coup_ate_grouping'[-4:-2]  ## => 'pi'
print 'coup_ate_grouping'[-4:-3]  ## => 'p'
print 'coup_ate_grouping'[-4:-4]  ## => ''
print 'coup_ate_grouping'[0:-1]   ## => 'coup_ate_groupin'
print 'coup_ate_grouping'[0:]     ## => 'coup_ate_grouping' (counter-intuitive)

## start:end:step (or start:end:stride)
print 'coup_ate_grouping'[-1::1]  ## => 'g'   
print 'coup_ate_grouping'[-1::-1] ## => 'gnipuorg_eta_puoc'

## combinations
print 'coup_ate_grouping'[-1::-1][-4:] ## => 'puoc'

结论

这个 cognitive load 对于一些不想花太多时间学习这种语言的采用者和开发人员来说,理解切片表示法在python中的工作原理可能确实是太多了。

然而,一旦理解了基本原理,这种方法相对于固定字符串操作方法的威力就相当大了。

对于那些不这么认为的人,有其他方法,比如lambda函数、迭代器或简单的一次性函数声明。

如果需要的话,开发人员可以实现自己的string.reverse()方法,但是理解python这方面背后的原理是很好的。

也见