也许是一个愚蠢的问题,但我注意到我的代码有很多这样的陈述:
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"
提前谢谢
答案 0 :(得分:3)
问题在于str
,int
和float
(long
,如果你在Py 2.x中(真和假是真的{{1} s,所以它们也是))你在Python中称为'不可变类型'。这意味着您无法修改其内部状态:int
(或str
或int
)的所有操作都将导致“new”实例float
(或其他)的值,而旧值将保留在Python的缓存中,直到下一个垃圾收集周期。
基本上,你无能为力。遗憾。
答案 1 :(得分:2)
事实上,compose
向functools
添加了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