how to get all the "variables" of a string formating?

G

GHUM

imagine:


template=""" Hello %(name)s, how are you %(action)s"""


we can use it to do things like:

print template % dict (name="Guido", action="indenting")


Is there an easy (i.e.: no regex) way to do get the names of all
parameters?

get_parameters(template) should return ["name", "action"]


Python has to do this somewhere internally..... how to access this
knowledge?

Harald
 
C

Calvin Spealman

imagine:


template=""" Hello %(name)s, how are you %(action)s"""


we can use it to do things like:

print template % dict (name="Guido", action="indenting")


Is there an easy (i.e.: no regex) way to do get the names of all
parameters?

get_parameters(template) should return ["name", "action"]


Python has to do this somewhere internally..... how to access this
knowledge?

Harald

I am not aware of anything in the stdlib to do this easily, but its
pretty easy to get them. See this example:

class format_collector(object):
def __init__(self):
self.names = []
def __getitem__(self, name):
self.names.append(name)
return ''

collector = format_collector()
"%(foo)s %(bar)s" % collector
assert collector.names == ['foo', 'bar']

Of course, wrapping this functionality into a simple function is
straightforward and will look better.
 
D

Duncan Booth

GHUM said:
Is there an easy (i.e.: no regex) way to do get the names of all
parameters?

get_parameters(template) should return ["name", "action"]


Python has to do this somewhere internally..... how to access this
knowledge?

How about:

class gpHelper:
def __init__(self):
self.names = set()
def __getitem__(self, name):
self.names.add(name)
return 0

def get_parameters(template):
hlp = gpHelper()
template % hlp
return hlp.names
template=""" Hello %(name)s, how are you %(action)s"""
get_parameters(template) set(['action', 'name'])
 
D

Duncan Booth

Calvin Spealman said:
I am not aware of anything in the stdlib to do this easily, but its
pretty easy to get them. See this example:

class format_collector(object):
def __init__(self):
self.names = []
def __getitem__(self, name):
self.names.append(name)
return ''

collector = format_collector()
"%(foo)s %(bar)s" % collector
assert collector.names == ['foo', 'bar']

Of course, wrapping this functionality into a simple function is
straightforward and will look better.

You should return a value like 0 instead of ''.

Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
"%(foo)s %(bar)d" % collector
TypeError: int argument required
 
C

Calvin Spealman

Calvin Spealman said:
I am not aware of anything in the stdlib to do this easily, but its
pretty easy to get them. See this example:

class format_collector(object):
def __init__(self):
self.names = []
def __getitem__(self, name):
self.names.append(name)
return ''

collector = format_collector()
"%(foo)s %(bar)s" % collector
assert collector.names == ['foo', 'bar']

Of course, wrapping this functionality into a simple function is
straightforward and will look better.

You should return a value like 0 instead of ''.

Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
"%(foo)s %(bar)d" % collector
TypeError: int argument required

Good thinking with returning 0 and using a set. Maybe something added
to the stdlib would be welcome instead of anyone needing it writing
this little class?
 
D

dakman

"Is there an easy (i.e.: no regex) way to do get the names of all
parameters? "

....regexp is the easy way :D
 
T

Tim Chase

Is there an easy (i.e.: no regex) way to do get the names of all
parameters?

get_parameters(template) should return ["name", "action"]

How about:

class gpHelper:
def __init__(self):
self.names = set()
def __getitem__(self, name):
self.names.add(name)
return 0

def get_parameters(template):
hlp = gpHelper()
template % hlp
return hlp.names
set(['action', 'name'])

(darn, if I didn't have nearly identical code/reply, but two
posts beat me to the Send button)

Duncan's solution is a slightly more robust solution (returning 0
rather than returning the empty string), as format strings allow
for things like

"%(food)s costs $%(x)05.2f" % {
'x':3.14159,
'food':'a slice of pie'
}

which will choke if it gets a string instead of a number for
attempts to get "x".

It sure beats trying to hammer out a regexp or some stab at
pyparsing it. Though I suppose one could do something like

r = re.compile(r'%\(([^)]*)\)')

as most of the edge-cases that I can think of that would cause
problems in a general case would be problems for the string
formatting as well (balanced parens, etc)

-tkc
 
S

Steven D'Aprano

"Is there an easy (i.e.: no regex) way to do get the names of all
parameters? "

...regexp is the easy way :D

I'd like to see this regex. And make sure it works correctly with this
format string:

"""%(key)s
%%(this is not a key)d
%%%(but this is)f
%%%%%%%(%(and so is this)%()%%)u
and don't forget the empty case %()c
but not %%%%%%()E
and remember to handle %(new
lines)X correctly
and %(percentages)%."""

It should list the keys as:

'key'
'but this is'
'%(and so is this)%()%%'
''
'new\nlines'
'percentages'


I love easy regexes :)
 
T

Tim Chase

I'd like to see this regex. And make sure it works correctly with this
format string:

"""%(key)s
%%(this is not a key)d
%%%(but this is)f
%%%%%%%(%(and so is this)%()%%)u
and don't forget the empty case %()c
but not %%%%%%()E
and remember to handle %(new
lines)X correctly
and %(percentages)%."""

It should list the keys as:

'key'
'but this is'
'%(and so is this)%()%%'
''
'new\nlines'
'percentages'


I love easy regexes :)
>>> r = re.compile(r'(?<!%)(?:%%)*%\(([^)]*)\)')

works on all but your pathological '%(and so is this)%()%%' and
if any programmer working for me used that as their formatting
variable, they'd either be out of a job, or I would be for hiring
such a psychopath. :)
@@@%(key)@@@s
%%(this is not a key)d
@@@%%%(but this is)@@@f
@@@%%%%%%%(%(and so is this)@@@@@@%()@@@%%)u
and don't forget the empty case @@@%()@@@c
but not %%%%%%()E
and remember to handle @@@%(new
lines)@@@X correctly
and @@@%(percentages)@@@%.['key', 'but this is', '%(and so is this', '', '', 'new\nlines',
'percentages']

The extra empty item (keys[3]) is from that pathological case.
Otherwise, it seems to do the trick.

-tkc
ps: you're a cruel, cruel fellow for throwing out such a
mind-bender this early in my morning. :) Thanks for the fun!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top