3

newbie here. can someone please explain to me why 'none' is printed at the end of this code, but only when called inside a function?

background: I have a variable (share_data) which contains some lists:

share_data = 
[['Date', 'Ticker', 'Company', 'Mkt Cap', 'VM Rank', 'Value Rank', 'Momentum Rank'],  
['2016-08-27', 'BEZ', 'Beazley', '2,063', '89', '72', '76'], 
['2016-08-30', 'BEZ', 'Beazley', '2,063', '89', '72', '76'], 
['2016-08-31', 'BEZ', 'Beazley', '2,050', '89', '72', '75'], 
['2016-09-01', 'BEZ', 'Beazley', '2,039', '96', '73', '93'], 
['2016-09-02', 'BEZ', 'Beazley', '2,069', '90', '72', '77'], 
['2016-09-03', 'BEZ', 'Beazley', '2,120', '96', '70', '94'], 
['2016-09-06', 'BEZ', 'Beazley', '2,106', '90', '71', '77'], 
['2016-09-07', 'BEZ', 'Beazley', '2,085', '89', '71', '76'], 
['2016-09-08', 'BEZ', 'Beazley', '2,091', '89', '72', '77'], 
['2016-09-09', 'BEZ', 'Beazley', '2,114', '89', '71', '77'], 
['2016-09-10', 'BEZ', 'Beazley', '2,084', '94', '71', '89'], 
['2016-09-12', 'BEZ', 'Beazley', '2,084', '94', '71', '89']]

I am interested in printing the last 5 lines.

If I use this in the main program:

for row in share_data[-5:]:
    print(row)

I get the correct data:

['2016-09-07', 'BEZ', 'Beazley', '2,085', '89', '71', '76']
['2016-09-08', 'BEZ', 'Beazley', '2,091', '89', '72', '77']
['2016-09-09', 'BEZ', 'Beazley', '2,114', '89', '71', '77']
['2016-09-10', 'BEZ', 'Beazley', '2,084', '94', '71', '89']
['2016-09-12', 'BEZ', 'Beazley', '2,084', '94', '71', '89']

...however when I created a function to do this:

def share_details(share_data, n=5):
    ''' Prints the last n rows of a share's records'''
    for row in share_data[-n:]:
        print(row)
    return

and called the function this way:

print(share_details(share_data))

...what I get is this (note the 'None' at the end):

['2016-09-07', 'BEZ', 'Beazley', '2,085', '89', '71', '76']
['2016-09-08', 'BEZ', 'Beazley', '2,091', '89', '72', '77']
['2016-09-09', 'BEZ', 'Beazley', '2,114', '89', '71', '77']
['2016-09-10', 'BEZ', 'Beazley', '2,084', '94', '71', '89']
['2016-09-12', 'BEZ', 'Beazley', '2,084', '94', '71', '89']
None

I think it's the 'return' statement at the end of the function that triggers it, but don't know how/why.

EDIT - now that's it's clear what my error was (ie. printing inside the function, and then also the return value outside) can I follow up with an additional question? Is it good practice to delegate all the printing to a function? Maybe a function called, for extra readability:

print_share_details(share_data)

Or there is a better way which is more readable/pythonic?

Patrick
  • 1,265
  • 7
  • 21
  • 33
  • Are you running this from the REPL? The REPL will print/display/show the value of expression executed (and in this case that's..); this is distinct from the side-effect output of the print statement used within the method itself. – user2864740 Sep 13 '16 at 00:48

4 Answers4

5

Every function in Python returns something, with a default return value of None. So

print(share_details(share_data))

calls share_details, share_details prints the last 5 rows of share_data, share_details returns None (by default), then print prints that return value.

Craig Burgler
  • 1,749
  • 10
  • 19
2

print(share_details(share_data)) will print the return of that method call. Inside your method, you simply have return, which will return None. Simply doing:

return

Will return None, which is the equivalent of not having a return, since None is returned by methods without a return.

You need to determine what it is you want to return as your response to your method call. If you do not want to return anything, and simply just print from within your method, then you do not need to actually explicitly call the return and you don't need to print your method call.

So, instead of doing this:

print(share_details(share_data))

Simply call it without the print:

share_details(share_data)

And remove the return at the end of your method, so you will have:

def share_details(share_data, n=5):
    ''' Prints the last n rows of a share's records'''
    for row in share_data[-n:]:
        print(row)
idjaw
  • 25,487
  • 7
  • 64
  • 83
2

When you write print(share_details(share_data)) - it means print the value returned by share_details function. The function returns None after printing the values.

If the function doesn't return anything that needs to be printed, it is better to omit the print and just call the function like:

share_details(share_data)
masnun
  • 11,635
  • 4
  • 39
  • 50
1

just remove the outer print statement. it's useless, and is printing the None value from the empty return statement.

Jules G.M.
  • 3,624
  • 1
  • 21
  • 35