我知道python函数参数是通过引用传递的,而可变参数可以修改函数内的超出范围的变量,除非你重新绑定局部变量。
我的问题是我想将函数参数转换为其他类型,并影响传递的范围外变量。但我尝试的两种方式只是重新绑定本地范围内的参数。
def change_type(my_var):
try:
if float(my_var) > 0:
my_var = float(my_var) #just rebinds!
except ValueError:
pass
some_var = '0.5'
change_type(some_var)
print(type(some_var)) #gives 'str'; I want it to be 'float'
我还尝试在float(my_var)
区域中执行if
而没有分配,但也没有做任何事情。
有没有办法让我修改像这样的范围外变量的数据类型,还是我必须直接在我的函数之外的some_var
上进行?
谢谢!
答案 0 :(得分:2)
从函数作为元组返回 修改的参数是Python的好方法。这更加冗长,也可以让您实现自己想要的目标。与例如不同在C或C ++中,您可以使用内置类型tuple
从函数返回多个值,因此您不必通过引用修改参数。
所以这就是诀窍(没有覆盖ValueError
):
def change_type(my_var):
if float(my_var) > 0:
return float(my_var)
else:
return my_var
my_var = '0.5'
my_var = change_type(my_var)
答案 1 :(得分:1)
您可以传入一个可变容器,如下所示:
def change_type(my_var):
try:
if float(my_var[0]) > 0:
my_var[0] = float(my_var[0])
except ValueError:
pass
some_var = ['0.5']
change_type(some_var)
print(type(some_var[0]))
有一种记录的方法可以影响另一个框架中局部变量的绑定:inspect
模块。这可能适合你:
import inspect
def change_type(my_var):
try:
if float(my_var) > 0:
my_var = float(my_var)
inspect.stack()[1][0].f_locals['some_var'] = my_var
except ValueError:
pass
some_var = '0.5'
change_type(some_var)
print(type(some_var))
我希望很明显以这种方式使用inspect
是一个坏主意。
答案 2 :(得分:0)
是的,您可以在Python中更改浮点数,但这是非常糟糕的主意,因为它们应该是不可变的。
import sys, struct, ctypes
def set_float(obj, value):
assert isinstance(obj, float), 'Object must be a float!'
assert isinstance(value, float), 'Value must be a float!'
stop = sys.getsizeof(obj)
start = stop - struct.calcsize('d')
array = ctypes.cast(id(obj), ctypes.POINTER(ctypes.c_ubyte))
for args in zip(range(start, stop), struct.pack('d', value)):
array.__setitem__(*args)
代码来自Python Cookbook中的How to Mutate a Float食谱。以下是如何使用set_float
函数的示例。
>>> a = 1.2
>>> set_float(a, 3.4)
>>> a
3.4
请注意,此解决方案旨在与CPython一起使用,并且可能无法与语言运行时的其他变体一起使用。