开发者

Python: modify strings stored in various objects inplace in a loop

I have strings stored in various objects, for example a, b, c[2:7] (ie 5 different strings c[2],...c[6]), d.s, e.s[:] (ie all strings stored in the e.s list). I need to loop over all these strings on various places in the code and mo开发者_运维技巧dify these variables in the loops. (Assigning the modified strings to new variables would not work as there are other functions expecting the modified strings in the original variables.) How can I do that efficiently in Python?

If I could create a list of references to the strings then I could just always iterate over it:

str_ref_lst=[reference(a), reference(b), reference(d.s)]
str_ref_lst.extend[reference(c[2:7])]
str_ref_lst.extend[reference(e.s[:])]
...
for ref_strng in str_ref_lst:
  do_string_modifications1(dereference(ref_strng))
...
function_using_the_modified_variables1()
...
for ref_strng in str_ref_lst:
  do_string_modifications2(dereference(ref_strng))
...
function_using_the_modified_variables2()
etc

However, I am not aware of reference()/dereference() analogues in Python (and I guess it would not be the right way in Python anyway)


The recommended answer should be "use a dictionary", but if you have to do it that way:

class cls(object):
    pass

a = "<a>"
b = "<b>"
c = ["", "", "<c>"]
d = cls()
d.s = "<d.s>"
e = cls()
e.s = "<e.s>"

var_list = "a b c[2:7] d.s e.s".split()

for var in var_list:
    exec "%s+='Mod'" % var             # Modify the variables

print a,b,c,d.s,e.s
# >>> <a>Mod <b>Mod ['', '', '<c>', 'M', 'o', 'd'] <d.s>Mod <e.s>Mod

IIRC this way doesn't work in Python 3.0 because of internal optimizations

With slices, it should be somewhat like

import re

class cls(object):
    pass

def fn(var):      # function to apply to the strings
    return "[%s mod]" % var

a = "<a>"
b = "<b>"
c = "01234567890"
d = cls()
d.s = "<d.s>"
e = cls()
e.s = "<e.s>"

var_list = "a b c[2:7] d.s e.s".split()

for var in var_list:
    # Modify the variables
    try:
        # exec "%s='Hi there'" % var             # Modify the variables
        exec "%(var)s=fn(%(var)s)" % { "var": var }
    except TypeError:
        # Assume Slice...
        slice_ = re.findall("\[(\d+)\:(\d+)\]", var)[0]   # Get slice
        var_with_slice = var
        var = var.split("[")[0]                 # Remove slice
        # Look ma, I can code in Perl too! :)
        line = \
             "%(var)s=%(var)s[:%(slice1)s]+fn(%(var_with_slice)s)+%(var)s[%(slice2)s+1:]" % \
             { "var": var, "var_with_slice": var_with_slice, "slice1": slice_[0], "slice2": slice_[1] }
        # somewhat like c = c[:2] + fn(c[2:7]) + c[7+1:]
        exec line

print a,b,c,d.s,e.s
# >>> [<a> mod] [<b> mod] 01[23456 mod]890 [<d.s> mod] [<e.s> mod]


Your do_string_modifications functions need to be changed so that they return the new string value instead of attempting to modify it in place (since that is not possible). Use your new functions to modify the list, and reassign the original string references to the new values in the list after the modification (if necessary):

str_lst = [a, b, d.s, c[2:7], e.s]
str_lst = [do_string_modifications1(x) for x in str_lst]
str_lst = [do_string_modifications2(x) for x in str_lst]
a, b, d.s, c[2:7], e.s = str_lst


You could do something like this.

def stringMod(inStr):
  return inStr.replace('f', 'g')

str_list = map(stringMod, str_list)


It is not possible in the generality that you want. The biggest hurdle are the slice operations you gave, c[2:7] and e.s[:]. These expressions are no lvalues, you cannot assign to them. They just produce new string values, which you have to capture or they are gone.

If you just had lvalues (a, b, d.s), expressions you can assign to, you could think of something, but with c[2:7] and e.s[:], it is not possible.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜