简体   繁体   中英

Python keeps overwriting argument, even when copied in or outside of function

My first question here. I hope I can make it as clear and informative as possible.

I am currently using python, and new to it. I love the language though, a lot of simplifications that keep your code very concise.

I currently have a function that accepts an argument. That argument gets overwritten even if I copy it to a local variable inside the function. Even when copied outside of the function (and the argument passed to the function) it overwrites the original argument.

Here the function: The argument I'm talking of is resultsvalidationparam . It might be a straightforward mistake as I've been staring at this for a while now, but I couldn't find an answer to my problem on the Internet.

    def mean_cluster_validation(resultsvalidationparam, validationmethods, mean_methods = 'relative'):
resultsvalidation = resultsvalidationparam
n_clusters = np.arange(2,2 + len(resultsvalidation.keys()))
clustermethods = tuple(resultsvalidation[str(2)].keys())
'''
First we find the best and worst score for each validation method (which gives a certain clustern and clustermethod). After which all scores are made
relative to those scores (giving them values between 0 and 1). Some validations methods are best when low or high values, this is taken into account. 
'''    
# Find max and min
validationMax = {}
validationMin = {}
for t in validationmethods:
    currentMax = (0,)# list containing max value, clustering method and number of clusters where value is max for certain validation method
    currentMin = (100000,)
    for i in n_clusters:
        for j in clustermethods: 
            if resultsvalidation[str(i)][j][t] is not None:
                if resultsvalidation[str(i)][j][t] > currentMax[0]:
                    currentMax = (resultsvalidation[str(i)][j][t],i,j)
                if resultsvalidation[str(i)][j][t] < currentMin[0]:
                    currentMin = (resultsvalidation[str(i)][j][t],i,j)
    validationMax[t] = currentMax
    validationMin[t] = currentMin

for t in validationmethods:
    for i in n_clusters:
        for j in clustermethods:
            if resultsvalidation[str(i)][j][t] is not None:
                resultsvalidation[str(i)][j][t] = (resultsvalidation[str(i)][j][t] - validationMin[t][0])/(validationMax[t][0] - validationMin[t][0])
return validationMax, validationMin, resultsvalidation

Even when I use a copy (eg 't') outside of the function of the variable, it still overwrites the original variable

I'm pretty stuck, again, apologies if I incorrectly formulated the question, my english is pretty poor.

In python, the assignment resultsvalidation = resultsvalidationparam doesn't make a copy, but rather an alias: resultsvalidation and resultsvalidationparam are the same object. You can check this using the is operator.

It looks like resultsvalidationparam is a dict, so you can create a copy of it using resultsvalidation = resultsvalidationparam.copy() . However, this only makes a shallow copy, so any objects contained within it will not be copied. This will make a deep copy:

import copy
resultsvalidation = copy.deepcopy(resultsvalidationparam)

For this, having a good understanding of mutable and immutable types help. See here for a nice explanation

In a nutshell, let's say your argument that you are passing is this

param = {'a': 2, 'b': 3}

Now if we:

temp = param 
print temp # {'a': 2, 'b': 3}

And we change the value of temp :

temp['a'] = 8

Now we check param again and:

print param
{'a': 8, 'b': 3}

As with your problem, param changes even when we copy it to a temp variable and change the temp.

From the Python Data model

Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable. (The value of an immutable container object that contains a reference to a mutable object can change when the latter's value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle.) An object's mutability is determined by its type; for instance, numbers, strings and tuples are immutable, while dictionaries and lists are mutable.

So you are making both your variables point to the same object - and when it's changed, both change as they are pointing to the same thing. If you want to make a copy to work on of a dict, for example, try

dict2 = dict(dict1)

Or also dict2 = dict1.copy()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM