msc87
msc87

Reputation: 1029

replacing a variable in multiple places in a string

I have a string that I want to put one variable in multiple places in it:

query_1 ='SELECT distinct ?a\
        WHERE { ?a rno:end_at ?b.\
        ?b rdf:type rno:Node; rno:is_extent_of ?x.\
        ?x rno:builds %s. %s a rno:Roundabout.\
        FILTER(NOT EXISTS {?a rno:builds %s})} ORDER BY ?a'%(ref_RaURI, ref_RaURI,ref_RaURI)
    print query_1

the above replacement works but I don't want to repeat the variable ref_RaURI, so I tried the following:

query_1 ='SELECT distinct ?a\
        WHERE { ?a rno:end_at ?b.\
        ?b rdf:type rno:Node; rno:is_extent_of ?x.\
        ?x rno:builds {0}. {0} a rno:Roundabout.\
        FILTER(NOT EXISTS {?a rno:builds {0}})} ORDER BY ?a'.format(ref_RaURI)
    print query_1

this one is returning:

    FILTER(NOT EXISTS {?a rno:builds {0}})} ORDER BY ?a'.format(ref_RaURI)
KeyError: ' ?a rno'

Using dictionary:

        query_1 ="SELECT distinct ?a\
        WHERE { ?a rno:end_at ?b.\
        ?b rdf:type rno:Node; rno:is_extent_of ?x.\
        ?x rno:builds %(s). %(s) a rno:Roundabout.\
        FILTER(NOT EXISTS {?a rno:builds %(s)})} ORDER BY ?a"%{'s':ref_RaURI}
    print query_1

returns:

    FILTER(NOT EXISTS {?a rno:builds %(s)})} ORDER BY ?a"%{'s':ref_RaURI}
ValueError: unsupported format character ' ' (0x20) at index 140

Is there any way to make it work?

Upvotes: 1

Views: 76

Answers (2)

Eugene V
Eugene V

Reputation: 3126

Also, when using % sign for string formatting, you can specify keyword arguments like this (taken right from your example):

pattern ='SELECT distinct ?a\
    WHERE { ?a rno:end_at ?b.\
    ?b rdf:type rno:Node; rno:is_extent_of ?x.\
    ?x rno:builds %(p1)s. %(p1)s a rno:Roundabout.\
    FILTER(NOT EXISTS {?a rno:builds %(p1)s})} ORDER BY ?a'
params = dict(p1=ref_RaURI)
# equal to 
# params = {'p1': ref_RaURI}
query_1 = pattern % params

String formatting operator % has multiple options. Most common case is using it as %s. WIt just inserts string representation of the variable. There are other options, like %c - character, %d - digit and so on. Besides this, it supports keyword arguments. This means, when you pass dictionary as a source for formatting, you can specify keys of the given dict for the % operator, like this:

d = {'one': 'first param', 'two': 'second param'}
print 'Few options here: %(one)s and %(two)s' % d

%(one)s means: take the value from the dict, by the key one, and put its string representation (%s). Same rule applies for all parameters. If you want just use %(one), this will not work, because you need to provide type, which value should be printed in, in this %s stands for string.

Upvotes: 1

Tom Dalton
Tom Dalton

Reputation: 6190

Al lthe comments about SQLInjection notwithstanding, in the general case you can use named parameters to string.format() like this:

>>> "Hello {myname} multi {myname} variable {myname}".format(myname="Tom")
'Hello Tom multi Tom variable Tom'

You can also use different formatting in different places:

>>> "0dp {v:.0f} 3dp {v:.3}".format(v=1.23)
'0dp 1 3dp 1.23'

Upvotes: 1

Related Questions