更改python函数参数的类型而不重新绑定

时间:2015-09-16 15:00:06

标签: python types

我知道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上进行?

谢谢!

3 个答案:

答案 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一起使用,并且可能无法与语言运行时的其他变体一起使用。