Python Forum
Weird issues with return
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Weird issues with return
#1
I am very confused on what return is and what it does. I have read A LOT.

The challenge is to take a string of input from the user and create nested dictionaries. There should be 1 dictionary that has each letter, and for each letter there are 2 key value pairs. How far that letter is from the front and how far it is from the back.

Now this code works although I was told it is creating the dictionary 8 times (I don't understand why, I assumed it would continue to append to the dictionary)

def wedothemathz (datstring):
    whatlen = len(datstring)
    fromfront = "Numbers from front"
    fromback = "Numbers from back"

    for letter in datstring:
        where = datstring.find(letter)
        fromback1 = int(whatlen) - int(where)
        fromback1 = fromback1 - 1
        numbersdict = {letter:{fromback:fromback1, fromfront:where}}
        print (numbersdict)
wedothemathz(input ("Please tell me the string you want to use:  "))
Here is the output:
Please tell me the string you want to use: asdf
{'a': {'Numbers from back': 3, 'Numbers from front': 0}}
{'s': {'Numbers from back': 2, 'Numbers from front': 1}}
{'d': {'Numbers from back': 1, 'Numbers from front': 2}}
{'f': {'Numbers from back': 0, 'Numbers from front': 3}}

What I was told was:
01) It is creating 8 dictionaries
02) It doenst return anything (this is where I am super confused.)
03) To test if the problem is solved i should be able to run this statement outside the function and get zero: print(letter_dict['a']['distance_from_first_letter']) (I swapped out the names already. I am calling the dictionary and the key something different).

The moment i add return my code breaks
def wedothemathz (datstring):
    whatlen = len(datstring)
    fromfront = "Numbers from front"
    fromback = "Numbers from back"

    for letter in datstring:
        where = datstring.find(letter)
        fromback1 = int(whatlen) - int(where)
        fromback1 = fromback1 - 1
        numbersdict = {letter:{fromback:fromback1, fromfront:where}}
        return (numbersdict)
    print (numbersdict)
wedothemathz(input ("Please tell me the string you want to use:  "))

print(numbersdict[a][fromfront])
print(numbersdict[a][fromfront])
NameError: name 'numbersdict' is not defined

I also notice the loop dies.

So I guess my question are
01) What does return do?
02) How do I loop through all of this information to create my nested dictionaries?
03) Where does the return go?

Sorry for the long post. I have been at this for 4 hours and I feel retarded.

I thought return would return numbersidct outside the loop so I could use it in the main program but it does not appear so.
Reply
#2
A couple basic statements.

return is a statement used in functions.
All functions return something.
If you don't explicitly return something the object returned is None.
Functions that return None are generally doing work on objects "in place".

For example list.sort returns None
>>> a = [5,9,12,5,2,67,3]
>>> a
[5, 9, 12, 5, 2, 67, 3]
>>> b = a.sort()
>>> a
[2, 3, 5, 5, 9, 12, 67]
>>> b
>>> repr(b)
'None'
>>>
We sorted the list a in place. b however got set to None from the return value of list.sort. This is a common mistake.

As for your problem, as far as I can tell you should create one main dictionary. Then you create a subdictionary in your main dictionary for each letter in your input. Finally you return the whole dictionary.

Something like:
from pprint import pprint


def wedothemathz (datstring):
    whatlen = len(datstring)
    fromfront_txt = "Numbers from front"
    fromback_txt = "Numbers from back"
    numbersdict = {}
    for i,letter in enumerate(datstring):
        fromback = whatlen - i
        numbersdict[letter] = {fromback_txt : fromback, fromfront_txt : i}
    return numbersdict

pprint(wedothemathz(input ("Please tell me the string you want to use:  ")))
Output:
Please tell me the string you want to use: asdf {'a': {'Numbers from back': 4, 'Numbers from front': 0}, 'd': {'Numbers from back': 2, 'Numbers from front': 2}, 'f': {'Numbers from back': 1, 'Numbers from front': 3}, 's': {'Numbers from back': 3, 'Numbers from front': 1}} Press any key to continue . . .
Reply
#3
This was very helpful. I feel like I understand return a bit better but how come if I try to call numbersdict outside of the function it still fails? I would think that return allows me to use numberdict anywhere.

Also it seems like people love zip and enumerate. I understand them but possibly need to look into enumerate more.

I never heard of pprint so this gives me a lot of new things to read.

Also I see i screwed up how to make the dictionary.

It is confusing how sometimes you can just declare things on the fly and other times you need to declare them at the start like numbersdict = ().

Anyway thank you so much this gave me a lot of help and a lot of things to study so thanks. Hopefully one day I can help the next generation also.
Reply
#4
Quote:how come if I try to call numbersdict outside of the function it still fails? I would think that return allows me to use numberdict anywhere.
You are trying to use it with variables that are out of scope.
I'm guessing you are getting this error:
Error:
Traceback (most recent call last): File "dictydcdsgs.py", line 58, in <module> print(numbersdict[a][fromfront]) NameError: name 'numbersdict' is not defined
Try adding this after my previous code:
my_dict = wedothemathz("asdf")
print(my_dict["a"]["Numbers from back"])
Reply
#5
You are right on both. I am not sure why but this is a lot for me to take in. The whole creating functions
def blah (argument, argument)

is strange to me

Also then when you call it:
blah (argument, argument)
you have to pass the arguments which seems logical I guess.

Then yours works cause I am guessing we are doing everything out of the loop? I played around with it and if I just put 'a' the test works and of course if I put zxcv it wont work.

How come we can't make the numbdicts be like global in scope? I used the global keyword once and someone here told me that was a huge no no. I understand why but like sometimes don't we want to take whatever transformations we have made and be able to use them everywhere? Not sure if that makes sense.

Also is it normal for a newbie to struggle with these concepts? I am about 1 week into python. I started last wed.
Reply
#6
(Jan-30-2018, 01:29 AM)fad3r Wrote: How come we can't make the numbdicts be like global in scope? I used the global keyword once and someone here told me that was a huge no no. I understand why but like sometimes don't we want to take whatever transformations we have made and be able to use them everywhere? Not sure if that makes sense.

You can pass the variable you want to access as a parameter to the function along with the other parameters. The function argument name is just like another name pointing to the same object in the memory.

In [1]: powered = {}

In [2]: def power_nums(text, result):
   ...:     print(text)
   ...:     for num in range(1, 6):
   ...:         result[num] = num**2
   ...:         

In [3]: power_nums('Rise and shine', powered)
Rise and shine

In [4]: powered
Out[4]: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020