Python 3 changing value of dictionary key in for l

2019-04-10 21:39发布

问题:

I have python 3 code that is not working as expected:

def addFunc(x,y):
    print (x+y)

def subABC(x,y,z):
    print (x-y-z)

def doublePower(base,exp):
    print(2*base**exp)

def  RootFunc(inputDict):
    for k,v in inputDict.items():
        if v[0]==1:
            d[k] = addFunc(*v[1:])
        elif v[0] ==2:
            d[k] = subABC(*v[1:])
        elif  v[0]==3:
            d[k] = doublePower(*v[1:])


d={"s1_7":[1,5,2],"d1_6":[2,12,3,3],"e1_3200":[3,40,2],"s2_13":[1,6,7],"d2_30":[2,42,2,10]}
RootFunc(d)

#test to make sure key var assignment works
print(d)

I get:

{'d2_30': None, 's2_13': None, 's1_7': None, 'e1_3200': None, 'd1_6': None}

I expected:

{'d2_30': 30, 's2_13': 13, 's1_7': 7, 'e1_3200': 3200, 'd1_6': 6}

What's wrong?

Semi related: I know dictionaries are unordered but is there any reason why python picked this order? Does it run the keys through a randomizer?

回答1:

print does not return a value. It returns None, so every time you call your functions, they're printing to standard output and returning None. Try changing all print statements to return like so:

 def addFunc(x,y):
     return x+y

This will give the value x+y back to whatever called the function.

Another problem with your code (unless you meant to do this) is that you define a dictionary d and then when you define your function, you are working on this dictionary d and not the dictionary that is 'input':

def  RootFunc(inputDict):
    for k,v in inputDict.items():
        if v[0]==1:
            d[k] = addFunc(*v[1:])

Are you planning to always change d and not the dictionary that you are iterating over, inputDict?

There may be other issues as well (accepting a variable number of arguments within your functions, for instance), but it's good to address one problem at a time.


Additional Notes on Functions:

Here's some sort-of pseudocode that attempts to convey how functions are often used:

def sample_function(some_data):
     modified_data = []
     for element in some_data:
          do some processing
          add processed crap to modified_data
     return modified_data

Functions are considered 'black box', which means you structure them so that you can dump some data into them and they always do the same stuff and you can call them over and over again. They will either return values or yield values or update some value or attribute or something (the latter are called 'side effects'). For the moment, just pay attention to the return statement.

Another interesting thing is that functions have 'scope' which means that when I just defined it with a fake-name for the argument, I don't actually have to have a variable called "some_data". I can pass whatever I want to the function, but inside the function I can refer to the fake name and create other variables that really only matter within the context of the function.

Now, if we run my function above, it will go ahead and process the data:

 sample_function(my_data_set)

But this is often kind of pointless because the function is supposed to return something and I didn't do anything with what it returned. What I should do is assign the value of the function and its arguments to some container so I can keep the processed information.

my_modified_data = sample_function(my_data_set)

This is a really common way to use functions and you'll probably see it again.


One Simple Way to Approach Your Problem:

Taking all this into consideration, here is one way to solve your problem that comes from a really common programming paradigm:

def  RootFunc(inputDict):
    temp_dict = {}
    for k,v in inputDict.items():
        if v[0]==1:
            temp_dict[k] = addFunc(*v[1:])
        elif v[0] ==2:
            temp_dict[k] = subABC(*v[1:])
        elif  v[0]==3:
            temp_dict[k] = doublePower(*v[1:])
    return temp_dict


  inputDict={"s1_7":[1,5,2],"d1_6":[2,12,3,3],"e1_3200":[3,40,2],"s2_13":[1,6,7],"d2_30"[2,42,2,10]}
  final_dict = RootFunc(inputDict)


回答2:

As erewok stated, you are using "print" and not "return" which may be the source of your error. And as far as the ordering is concerned, you already know that dictionaries are unordered, according to python doc at least, the ordering is not random, but rather implemented as hash tables.

Excerpt from the python doc: [...]A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary. [...]

Now key here is that the order of the element is not really random. I have often noticed that the order stays the same no matter how I construct a dictionary on some values... using lambda or just creating it outright, the order has always remained the same, so it can't be random, but it's definitely arbitrary.