按功能更改字符串值

时间:2011-06-17 23:24:24

标签: python

也许是一个愚蠢的问题,但我注意到我的代码有很多这样的陈述:

var = "some_string"
var = some_func(var)
var = another_func(var)
print var # outputs "modified_string"

这真让我烦恼,它看起来很糟糕(与整个python相反) 如何避免使用它并以这样的方式开始使用它:

var = "some_string"
modify(var, some_func)
modify(var, another_func)
print var # outputs "modified_string"

提前谢谢

7 个答案:

答案 0 :(得分:3)

问题在于strintfloatlong,如果你在Py 2.x中(真和假是真的{{1} s,所以它们也是))你在Python中称为'不可变类型'。这意味着您无法修改其内部状态:int(或strint)的所有操作都将导致“new”实例float(或其他)的值,而旧值将保留在Python的缓存中,直到下一个垃圾收集周期。

基本上,你无能为力。遗憾。

答案 1 :(得分:2)

事实上,composefunctools添加了def compose(f1, f2): def composition(*args, **kwargs): return f1(f2(*args, **kwargs)) return composition def compose_many(*funcs): if len(funcs) == 1: return funcs[0] if len(funcs) == 2: return compose(funcs[0], funcs[1]) else: return compose(funcs[0], compose_many(*funcs[1:])) 功能。我想我明白为什么他们没有...但是,嘿,这并不意味着我们不能自己创造一个:

>>> def append_foo(s):
...     return s + ' foo'
... 
>>> def append_bar(s):
...     return s + ' bar'
... 
>>> append_bar(append_foo('my'))
'my foo bar'
>>> compose(append_bar, append_foo)('my')
'my foo bar'
>>> def append_baz(s):
...     return s + ' baz'
... 
>>> compose_many(append_baz, append_bar, append_foo)('my')
'my foo bar baz'

测试:

{{1}}

想一想,这可能不是解决问题的最佳方案。但写作很有趣。

答案 2 :(得分:2)

我认为这不是最“ pythonic”的事情,但是您可以将字符串“包装”在列表中,因为列表在python中是可变的。 例如:

var = "string"
var_wrapper = [var]

现在您可以将列表传递给函数并访问其唯一元素,并且更改后将在外部可见。

def change_str(lst):
    lst[0] = lst[0] + " changed!"

您将获得:

>>> change_str(var_wrapper)
>>> var_wrapper[0]
"string changed!"

答案 3 :(得分:1)

其他人已经解释了为什么这是不可能的,但你可以:

for modify in some_func, other_func, yet_another_func:
 var = modify(var)

或pst说:

var = yet_another_func(other_func(some_func(var)))

答案 4 :(得分:0)

字符串在python中是不可变的,所以你的第二个例子不能工作。在第一个示例中,您将名称var绑定到每行上的一个全新对象。

通常,对单个名称的多次分配就像代码气味一样。也许如果您发布了更大的代码示例,有人可以向您展示更好的方法吗?

答案 5 :(得分:0)

有一种方法可以通过在本地符号表中重写来修改不可变变量,但是,我认为它不是很好,应该尽可能避免。

def updatevar(obj, value, callingLocals=locals()):
    callingLocals[next(k for k, o in callingLocals.items() if o is obj)] = value

另一种方式,即使不那么pythonic,是使用带有格式化指令的exec。由于this solution

,它将变量名称作为字符串
def getname(obj, callingLocals=locals()):
    """
    a quick function to print the name of input and value.
    If not for the default-Valued callingLocals, the function would     always
    get the name as "obj", which is not what I want.
    """
    return next(k for k, v in callingLocals.items() if v is obj)

def updatevar2(k, v, callingLocals=locals()):
    n = getname(k, callingLocals)
    exec('global {};{}={}'.format(n, n, repr(v)))

结果如预期:

var = "some_string"
updatevar(var, "modified_string")
print(var) # outputs "modified_string"
updatevar2(var, var + '2')
print(var) # outputs "modified_string2"

答案 6 :(得分:-1)

我要把这个放在这里(因为没有一个答案似乎已经解决了)

如果您经常重复相同的功能序列,请考虑将它们包装在更高级别的功能中:

def metafunc(var):
    var = somefunc(var)
    var = otherfunc(var)
    var = thirdfunc(var)
    return lastfunc(var)

然后当您调用函数metafunc时,您确切知道var发生了什么:什么都没有。你从函数调用中得到的只是metafunc返回的内容。 此外,您可以确定您忘记的程序部分中没有任何事情发生。这非常重要,特别是在脚本语言中,在 知道/记住的幕后通常会发生很多事情。

这有利有弊,理论讨论属于纯函数式编程。一些真实世界的交互(例如i / o操作)需要非纯函数,因为它们需要超出代码执行范围的实际影响。 这背后的原理简要定义如下:

http://en.wikipedia.org/wiki/Functional_programming#Pure_functions