开发者

String templates in Python: what are legal characters?

开发者 https://www.devze.com 2022-12-21 15:43 出处:网络
I can\'t quite figure out what\'s going on with string templates: t = Template(\'cannot teach an ${dog.old} ${tricks.new}. ${why} is this ${not} working\')

I can't quite figure out what's going on with string templates:

t = Template('cannot teach an ${dog.old} ${tricks.new}. ${why} is this ${not} working')
print t.safe_substitute({'dog.old': 'old dog', 'tricks.new': 'new tricks', 'why': 'OH WHY', 'not': '@#%@#% NOT'})

This prints:

cannot teach an ${dog.old} ${tricks.new}. OH WHY is this @#%@#% NOT working

I thought that the braces handled arbitrary strings. What characters are allowed in braces and is there any way I can subclass Template to do what I 开发者_开发知识库want?


From the documentation...

$identifier names a substitution placeholder matching a mapping key of "identifier". By default, "identifier" must spell a Python identifier. The first non-identifier character after the $ character terminates this placeholder specification.

The period is a non-identifier character, and braces are simply used to separate the identifier from adjacent non-identifier text.


Aha, I tried this experiment:

from string import Template
import uuid

class MyTemplate(Template):
    idpattern = r'[a-z][_a-z0-9]*(\.[a-z][_a-z0-9]*)*'

t1 = Template('cannot teach an ${dog.old} ${tricks.new}. ${why} is this ${not} working')
t2 = MyTemplate('cannot teach an ${dog.old} ${tricks.new}. ${why} is this ${not} working')
map1 = {'dog.old': 'old dog', 
    'tricks.new': 'new tricks', 'why': 'OH WHY', 'not': '@#%@#% NOT'}
map2 = {'dog': {'old': 'old dog'}, 
        'tricks': {'new': 'new tricks'}, 'why': 'OH WHY', 'not': '@#%@#% NOT'}  
print t1.safe_substitute(map1)
print t1.safe_substitute(map2)
print t2.safe_substitute(map1)
print t2.safe_substitute(map2)

which prints

cannot teach an ${dog.old} ${tricks.new}. OH WHY is this @#%@#% NOT working
cannot teach an ${dog.old} ${tricks.new}. OH WHY is this @#%@#% NOT working
cannot teach an old dog new tricks. OH WHY is this @#%@#% NOT working
cannot teach an ${dog.old} ${tricks.new}. OH WHY is this @#%@#% NOT working

so the third one (print t2.safe_substitute(map1)) works.


Python interprets the . in your name as "access the field old of the instance dog". Try _ instead or make dog an object with a field old.

AFAIR, only valid identifiers and . are safe between the braces.

[EDIT] It's on the page where you link to:

${identifier} is equivalent to $identifier. It is required when valid identifier characters follow the placeholder but are not part of the placeholder, such as "${noun}ification".

and

"identifier" must spell a Python identifier.

which means: It must be a valid identifier.

[EDIT2] It seems that the identifier isn't analyzed as I thought. So you must specify a simple valid Python identifier in the braces (and you can't use the field accessor syntax) unless you create your own implementation of the Template class.

0

精彩评论

暂无评论...
验证码 换一张
取 消