Passing a string to a function as a parameter - is it really a string?


#1



Part of the Whole #8


The code executes properly but I do not get the logic.


I am struggling with the "students list":
As required, I have created the list, it does however look like it's ultimately a concatenation of the three dictionaries that have been defined previously. A print(students)-command seems to prove this point:
{'homework': [90.0, 97.0, 75.0, 92.0], 'name': 'Lloyd', 'quizzes': [88.0, 40.0, 94.0], 'tests': [75.0, 90.0]}
{'homework': [100.0, 92.0, 98.0, 100.0], 'name': 'Alice', 'quizzes': [82.0, 83.0, 91.0], 'tests': [89.0, 97.0]}
{'homework': [0.0, 87.0, 75.0, 22.0], 'name': 'Tyler', 'quizzes': [0.0, 75.0, 78.0], 'tests': [100.0, 100.0]}

If I now print(i) in...

def getclass_average(students):_
_ results = []_
_ for i in students:_
_ print(i)_
_ results.append(get_average(i))_
_ print(results)_
_ return average(results)_

...I do also get the values {'homework': [90.0, 97.0, 75.0, 92.0], 'name': 'Lloyd', 'quizzes': [88.0, 40.0, 94.0], 'tests': [75.0, 90.0]} for the first iteration.
And here is my point: I would have expected to have the value "lloyd" passed to the function get_average in the first run since get_average requires the dict name "lloyd" in order to work.
Instead, it seems to pass on all key-value combinations though in my understanding.

What am I getting wrong here?
I appreciate your input everybody, many thanks in advance!


lloyd = {
    "name": "Lloyd",
    "homework": [90.0, 97.0, 75.0, 92.0],
    "quizzes": [88.0, 40.0, 94.0],
    "tests": [75.0, 90.0]
}
alice = {
    "name": "Alice",
    "homework": [100.0, 92.0, 98.0, 100.0],
    "quizzes": [82.0, 83.0, 91.0],
    "tests": [89.0, 97.0]
}
tyler = {
    "name": "Tyler",
    "homework": [0.0, 87.0, 75.0, 22.0],
    "quizzes": [0.0, 75.0, 78.0],
    "tests": [100.0, 100.0]
}

totalavg=0

def get_letter_grade(score):
    if score>=90:
        return "A"
    elif score>=80:
        return "B"
    elif score>=70:
        return "C"
    elif score>=60:
        return "D"
    else:
        return "F"

def average(numbers):
    total=float(sum(numbers))
    total=total/len(numbers)
    return total
    
def get_average(student):
    homework=average(student["homework"])
    quizzes=average(student["quizzes"])
    tests=average(student["tests"])
    totalavg=homework*0.1+quizzes*0.3+tests*0.6
    return totalavg

students = [lloyd, alice, tyler]

def get_class_average(students):
    results = []
    for i in students:
         print(i)
         results.append(get_average(i))
         print(results)
    return average(results)

print(len(students))
get_class_average(students)


#2

Those are three separate values, printing a single value will not cause three values to be printed.
They were probably in a list but you then edited what was printed to instead be three values. Or, you didn't print that variable but another one three times, in which case that doesn't say much about whether students is a list, because you didn't print students.

You'd also need to think about what concatenating dictionaries would mean. Seems like you mean concatenated string representations of dictionaries, but why would you have something like that in your program?

Values don't have names, so a dict can't be named lloyd. What makes you say that get_average has special interest in lloyd? It shouldn't be concerned with that, it should just look up homework/quizzes/tests and compute some number from that.


#3

Hi there, let me focus on your last paragraph; this might be the origin of my confusion:
Values don't have names, so a dict can't be named lloyd. What makes you say that getaverage has special interest in lloyd? It shouldn't be concerned with that, it should just look up homework/quizzes/tests and compute some number from that_

Well I thought that I was creating a dict named "lloyd" below?
lloyd = {
"name": "Lloyd",
"homework": [90.0, 97.0, 75.0, 92.0],
"quizzes": [88.0, 40.0, 94.0],
"tests": [75.0, 90.0]
}

The get_average function requires the dict name as its parameter...
def get_average(student):
homework=average(student["homework"]) => I read this as dictname["key"] - am I wrong?
quizzes=average(student["quizzes"])
tests=average(student["tests"])
totalavg=homework*0.1+quizzes*0.3+tests*0.6
return totalavg

So if I'd pass on the dict name "lloyd" to the function by executing "get_average(lloyd)", then it works fine.

I was now expecting the same to happen in the loop in get_class_average: I thought it passes on the dict-names on by one into get_average in order for the latter to work.

But based on your answer I seem to have some basic misunderstandings of the concept here.
Still not quite clear about it.

Hope I am making any sense :slight_smile:


#4

No, you have a variable refering to a dict.
The dict does not contain information about what external things have references to it

Is this 5 named bob?

bob = 5
lisa = 5

No, but bob refers to 5. As does lisa.

You would send it the dicts, not names


#5

Thanks again for your help, I really appreciate it!
The clarification with "bob" was a good one.

I suppose I am still struggling with the understanding of the second point "You would send it the dicts, not names":
So in my understanding, I need to send the get_average function references to the dicts; i.e. the variables "lloyd, alice, tyler". In order to to so in a for-loop, the three references are packaged into a list; i.e. we now have a list containing three variables that refer to particular dicts:
students = [lloyd, alice, tyler]

I guess what confuses me is the point that I can't see the variable-names (lloyd, alice, tyler) when I print the students-list but instead the contents of the dicts.
For example: print(students[0]) returns the dict (key-values) contained in the variable lloyd:
{'quizzes': [88.0, 40.0, 94.0], 'homework': [90.0, 97.0, 75.0, 92.0], 'name': 'Lloyd', 'tests': [75.0, 90.0]}.

According to me not seeing the variable names when I print the list "students", I assume that the above is what actually gets passed onto the function get_average by the loop in get_class_average(students):

def getclass_average(students):_
_ for i in students:_
_ results.append(get_average(i))_

I expected "i" to be "lloyd" in the first run though instead of the dict key-value chain contained in llyod since the function def_average also requires the variable name in order to access the respective dict:
def get_average(student):
homework=average(student["homework"]) => So the first call should equate to homework=average(lloyd["homework"]) but to me it looks like it equates to homework=average({'quizzes': [88.0, 40.0, 94.0], 'homework': [90.0, 97.0, 75.0, 92.0], 'name': 'Lloyd', 'tests': [75.0, 90.0]}["homework"]).

Once again, I hope that you can spot the mistake in my thought process - thanks a lot for your patience and your time!


#6

You'd send the reference, not the variable.
A list doesn't contain variables, it contains references to other values.

A variable is a name which has a reference to a value. Same as a dictionary (and a lot of times that's exactly what it is)

And also note that this varies between languages. Some indeed can pass along the actual variable, some use integers as an address to memory where the value is stored, or send the value directly as a copy. With python you always send the same value, not a copy


#7

A list doesn't contain variables, it contains references to other values.

Ok, that was a very important statement that helped my understanding.
Thanks for your support!


#8

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.