1

Possible Duplicate:
Function printing correct Output and None

Trying to print mutual users in a pretend twitter feed program. Homework. The numbers are users (ex 1111 is a user). The following set in the dictionary is a set of the key's friends.

I'd like this output:

Most friends in common
1111:   222 33333 5454
222:    1111 33333 5454
33333:  1111 222
5454:   1111 222

But instead have this output:

Most friends in common
1111 :  222 33333 5454  1111 None
222 :   1111 33333 5454  222 None
33333 :  1111 222  33333 None
5454 :   1111 222  5454 None

Here is my program:

all_users = {'1111': set(['5454', '222']), '33333': set(['5454']), '5454': set(['1111', '33333', '222']), '222': set(['1111', '5454'])}



def findmutual(id, all_users):
    users = []
    for key in all_users:
        mutual = all_users[id].intersection(all_users[key])
        rank = len(mutual)
        templist = [rank, key.strip()]
        users.append(templist)
    users = sorted(users)

    print users

    for item in users:
        if  id == item[1]:
            print "" ,
        if item[0] == 0:
            print "",
        else:
            print item[1],


users = []
for key in all_users:
    users.append(key)
users = sorted(users)
print "Most friends in common"
for item in users:
    print item, ":\t", findmutual(item, all_users)

Please help me to understand this issue!

Community
  • 1
  • 1
pearbear
  • 1,025
  • 4
  • 18
  • 23
  • 4
    Printing something in a function is different to *returning* a value. Because you don't have any `return` statements in `findmutual`, it returns `None`. – Marius Nov 08 '12 at 03:16
  • @Marius, sorry, I'll rephrase- if the twitter user name, or id, is equal to the mutual friend it is testing against, I do not want it to print that user ID (because it's not a mutual friend, it's itself) – pearbear Nov 08 '12 at 03:18
  • It still prints the id because you have a print statement. It prints the id, then it returns None, which gets printed by the calling function. – abarnert Nov 08 '12 at 03:20
  • As a general rule, functions take inputs and return outputs. Don't put side effects like print statements in functions. Have the caller (the user interface) print the result it gets. – Keith Nov 08 '12 at 03:25
  • @pearbear: It's a different language (PHP instead of Python), but I think [this answer](http://stackoverflow.com/a/9388327/128397) does a good job of explaining what is going on here. – Daniel Pryden Nov 08 '12 at 03:38
  • Also, this has been asked lots of times before. In a quick search I turned up [Function printing correct output and None](http://stackoverflow.com/questions/12466233/function-printing-correct-output-and-none) which is a pretty exact duplicate. – Daniel Pryden Nov 08 '12 at 03:41

2 Answers2

1

findmutual doesn't return anything, which in Python is equivalent to returning None. So "None" is appearing in the output because you're telling it to print the return value of findmutual(item, all_users), which is always None.

The numbers are still being printed because findmutual itself prints them. This is very rarely what you want, because it denies you the flexibility of calling findmutual to find the user ids and do anything else with them; every time you call it it will print them (even if you didn't want it to), and you don't get access to the numbers in Python to further manipulate.

Ben
  • 68,572
  • 20
  • 126
  • 174
  • I fixed the none- but I actually do want it to print. I'm trying to figure out now why the id reprints again as it goes through `findmutual` – pearbear Nov 08 '12 at 03:26
  • 1
    @pearbear In `findmutual` you print things. You also print the return value of `findmutual`. If you don't want one of these things to print, don't print it. – Ben Nov 08 '12 at 03:40
0
for item in users:
    print item, ":\t", findmutual(item, all_users) # << That's why it shows None

What is happening here?

  1. item = users[n]
  2. print:
    1. item
    2. enter the function
    3. the function prints some more
    4. function ends and (automatically) returns None
    5. print the return value (which is None) of the function!

You probably want to change step 3-4! instead of all print statements smth like:

result=''
...
result += '' #whatever
...
return result

UPDATE:

If i get you right, you are trying to establish a rank depending on who's the most popular?

In that case you might look int othat solution:

all_users = {'1111': set(['5454', '222']),
             '33333': set(['5454']),
             '5454': set(['1111', '33333', '222']),
             '222': set(['1111', '5454'])}

from collections import defaultdict, Counter

def findmutual(user_relation_map):    
    user_list = set(sorted(user_relation_map.keys()))
    user_ranking = defaultdict(int)
    for user in user_list:
        for friend in user_relation_map[user]:
            user_ranking[friend] += 1
    return user_ranking

c=Counter(findmutual(all_users))
print("Ranking : {0}".format(c.most_common()))

>>> Ranking : [('5454', 3), ('1111', 2), ('222', 2), ('33333', 1)]
Don Question
  • 11,227
  • 5
  • 36
  • 54