python 变量内容在不打算更改时由函数更改 [英] python variable contents changed by function when no change is intended

查看:48
本文介绍了python 变量内容在不打算更改时由函数更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个代码示例,其中一个函数使用新信息重复运行,其中大多数输入变量除外,good_ens.永远不应该改变的输入变量 good_ens 被改变了.这里发生了什么?这违背了我对范围的理解.

def doFile(infileName, outfileName, goodens, timetype, flen):打印('infilename = %s' % infileName)打印('输出文件名 = %s' % 输出文件名)print('输入的goodens从%d到%d' % (goodens[0],goodens[1]))print('时间类型是 %s' % 时间类型)maxens = flen # 假文件长度print('%s 时间变量有 %d 个集合' % (infileName,maxens))# TODO - goodens[1] 具有处理多个文件时运行的前一个文件的文件大小!如果goodens[1] <0:goodens[1] = 最大print('调整输入文件长度的goodens从%d到%d' % (goodens[0],goodens[1]))nens = goodens[1]-goodens[0]print('用 %d 条记录创建新的 netCDF 文件 %s (应该匹配输入文件)' % (outfileName, nens))# 用户设置数据路径 = ""数据文件 = ['file0.nc',\'file1.nc',\'file2.nc',\'file3.nc']# 这个演示的假文件长度数据长度 = [357056, 357086, 357060, 199866]outfileroot = '输出文件'attFile = 数据路径 + 'attfile.txt'# 这变了!永远不应该改变!# 请求文件中的所有集合good_ens = [0,-1]# -------------- 超出这里用户应该不需要改变的东西对于范围内的文件数(len(数据文件)):打印('\n--------------\n')print('函数调用前的输入参数')打印(good_ens)inputFile = 数据路径 + 数据文件[filenum]打印(输入文件)l = 数据长度[文件编号]打印(升)outputFile = 数据路径 + ('%s%03d.cdf' % (outfileroot,filenum))打印(输出文件)print('从 %s 转换为 %s' % (inputFile,outputFile))# 变量 good_ens 被这个调用函数改变了,不应该被改变doFile(inputFile, outputFile, good_ens, 'CF', l)# 这有效,但在使用此功能时对我不起作用#doNortekRawFile(inputFile, outputFile, [0,-1], 'CF', l)

for 循环前两次迭代的输出如下.注意 good_ens 从 [0, -1] 变为函数内部的 goodens 值.为什么?别介意变量名的不同,它们甚至不共享相同的作用域.

--------------函数调用前的输入参数[0, -1]文件0.nc357056输出文件000.cdf从 file0.nc 转换为 outfile000.cdfinfilename = file0.ncoutfilename = outfile000.cdf输入的好处是从 0 到 -1时间类型是 CFfile0.nc 时间变量有 357056 个集合为输入文件长度调整的 goodens 从 0 到 357056使用 357056 条记录创建新的 netCDF 文件 outfile000.cdf(应匹配输入文件)--------------函数调用前的输入参数[0, 357056]文件1.nc357086输出文件001.cdf从 file1.nc 转换为 outfile001.cdfinfilename = file1.ncoutfilename = outfile001.cdf输入的好处是从 0 到 357056时间类型是 CFfile1.nc 时间变量有 357086 个集合输入文件长度调整的 goodens 从 0 到 357056使用 357056 条记录创建新的 netCDF 文件 outfile001.cdf(应匹配输入文件)--------------

这里有一个类似的问题:
下降时属性变化的Python问题值循环外作用域

但是我不想将变量 good_ens 嵌入到 for 循环中.我希望它的值由用户在脚本开头设置一次,然后在 for 循环中使用.

解决方案

当你调用 doFile 时试试这个:

doFile(inputFile, outputFile, list(good_ens), 'CF', l)

我是这样认为的:列表是指向列表中每个元素的值的东西.当您将列表传递给函数时,执行指向的事物 会被复制,但所指向事物的值 不会被复制.

doing list(good_ens) 实际上是在内存中复制列表的元素,并防止原始值被更改.见下文:

<预><代码>>>>def change_list(the_list):... the_list[0] = 77... 返回...>>>a=[0,1,2,3,4]>>>change_list(a)>>>一种[77, 1, 2, 3, 4]>>>>>>a=[0,1,2,3,4]>>>更改列表(列表(a))>>>一种[0, 1, 2, 3, 4]

这样做的原因是,正如其他答案所表明的那样,列表是 python 中的可变数据类型.可变数据类型可以更改,而不可变数据类型不能更改,而是在尝试更新时返回新对象.

Here is a sample of code where a function is run repeatedly with new information for most of the input variables except one, good_ens. The input variable good_ens that should never be changed, gets changed. What is going on here? This defies my understanding of scope.

def doFile(infileName, outfileName, goodens, timetype, flen):

    print('infilename = %s' % infileName)
    print('outfilename = %s' % outfileName)
    print('goodens at input are from %d to %d' % (goodens[0],goodens[1]))
    print('timetype is %s' % timetype)

    maxens = flen # fake file length
    print('%s time variable has %d ensembles' % (infileName,maxens))

    # TODO - goodens[1] has the file size from the previous file run when multiple files are processed!
    if goodens[1] < 0:
        goodens[1] = maxens

    print('goodens adjusted for input file length are from %d to %d' % (goodens[0],goodens[1]))

    nens = goodens[1]-goodens[0]
    print('creating new netCDF file %s with %d records (should match input file)' % (outfileName, nens))


# user settings
datapath = ""

datafiles = ['file0.nc',\
             'file1.nc',\
             'file2.nc',\
             'file3.nc']
# fake file lengths for this demonstration
datalengths = [357056, 357086, 357060, 199866]
outfileroot = 'outfile'
attFile = datapath + 'attfile.txt'
# this gets changed!  It should never be changed!
# ask for all ensembles in the file
good_ens = [0,-1]

# --------------  beyond here the user should not need to change things
for filenum in range(len(datafiles)):

    print('\n--------------\n')
    print('Input Parameters before function call')
    print(good_ens)
    inputFile = datapath + datafiles[filenum]
    print(inputFile)
    l = datalengths[filenum]
    print(l)
    outputFile = datapath + ('%s%03d.cdf' % (outfileroot,filenum))
    print(outputFile)

    print('Converting from %s to %s' % (inputFile,outputFile))
    # the variable good_ens gets changed by this calling function, and should not be
    doFile(inputFile, outputFile, good_ens, 'CF', l)
    # this works, but will not work for me in using this function
    #doNortekRawFile(inputFile, outputFile, [0,-1], 'CF', l)

Output for the first two iterations of the for loop is below. Note good_ens gets changed from [0, -1] to the value of goodens that is inside the function. Why? Never mind the difference in variable names, they don't even share the same scope.

--------------

Input Parameters before function call
[0, -1]
file0.nc
357056
outfile000.cdf
Converting from file0.nc to outfile000.cdf
infilename = file0.nc
outfilename = outfile000.cdf
goodens at input are from 0 to -1
timetype is CF
file0.nc time variable has 357056 ensembles
goodens adjusted for input file length are from 0 to 357056
creating new netCDF file outfile000.cdf with 357056 records (should match input file)

--------------

Input Parameters before function call
[0, 357056]
file1.nc
357086
outfile001.cdf
Converting from file1.nc to outfile001.cdf
infilename = file1.nc
outfilename = outfile001.cdf
goodens at input are from 0 to 357056
timetype is CF
file1.nc time variable has 357086 ensembles
goodens adjusted for input file length are from 0 to 357056
creating new netCDF file outfile001.cdf with 357056 records (should match input file)

--------------

There is a similar question here:
Python issue value of property changes when falling out of loop scope

However I do not want to embed the variable good_ens down in a for loop. I want its value to be set by the user once at the head of a script, then used in the for loop.

解决方案

When you call doFile try this instead:

doFile(inputFile, outputFile, list(good_ens), 'CF', l)

I think of it this way: A list is a thing which points to the value of each element within the list. When you pass a list into a function, the thing that does the pointing gets copied, but the values of the things pointed to do not get copied.

doing list(good_ens) actually makes copies in memory of the elements of the list, and will keep the original values from getting changed. See below:

>>> def change_list(the_list):
...     the_list[0] = 77
...     return
...
>>> a=[0,1,2,3,4]
>>> change_list(a)
>>> a
[77, 1, 2, 3, 4]
>>>
>>> a=[0,1,2,3,4]
>>> change_list(list(a))
>>> a
[0, 1, 2, 3, 4]

EDIT: The reasoning for this is that, as the other answers have indicated, list is a mutable data type in python. Mutable data types can be changed, whereas immutable data types cannot be changed but rather return new objects when attempting to update.

这篇关于python 变量内容在不打算更改时由函数更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆