6

I just want to use the for loop for the t variable in my function:

l = []

def func(s):   
    for i in range(1, 100):
        t = i
        p = t * 2 + s * 2
    return p

l.append(func(10))

print l

I want the value of t to go from 1 to 99 and and print a list of all the value, but I always end up getting l = [218].

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
p.kumar
  • 113
  • 1
  • 8
  • 2
    @AlbertoBonsanto: the problem with fixing indentation should now be apparent. Was that `return` really part of the `for` loop in the function? And why did you not indent the function body? – Martijn Pieters Mar 19 '16 at 01:50
  • @MartijnPieters I'm sorry I was editing in the exact moment! I didn't pretend to overwrite yours! – Alberto Bonsanto Mar 19 '16 at 01:51
  • Consider this? `func = lambda s: [(t*2)+s*2 for t in range(1, 100)]` – Jason Mar 19 '16 at 01:54
  • @Signal Cheers mate but can you help me make some changes in the code itself. I am a bit new to this so i don't quite understand func = lambda s: [(t*2)+s*2 for t in range(1, 100)] – p.kumar Mar 19 '16 at 01:58

3 Answers3

41

I assume you have NumPy installed (at least your original question suggested it), so I'll present a way how you can get your result using numpy-arrays in a very efficient manner (without any list-comprehensions and explicit iterations):

> import numpy as np
> s = 10
> l = np.arange(1, 100) * 2 + s * 2 # Arrange produces an array. Syntax is like "range".
> print(l)

array([ 22,  24,  26,  28,  30,  32,  34,  36,  38,  40,  42,  44,  46,
        48,  50,  52,  54,  56,  58,  60,  62,  64,  66,  68,  70,  72,
        74,  76,  78,  80,  82,  84,  86,  88,  90,  92,  94,  96,  98,
       100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124,
       126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150,
       152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176,
       178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202,
       204, 206, 208, 210, 212, 214, 216, 218])

I used the fact that mathematical operations on NumPy arrays affect all elements. Therefore it is so easy to write the operation: np.arange(1, 100) * 2, because it multiplies every element with 2 and numpy.arange is a possibility to create an array containing all the numbers between a given start and stop with an optional step (just like the python range).

With NumPy it wouldn't be a good choice to append single values (because this recreates the whole array and not just appends values). In most cases it's best to create an array with the final size and shape and operate directly on it. Of course you can concatenate or append different NumPy arrays, but as mentioned it always creates a completely new array and is therefore not very efficient (if used regularly).


So now a few observations on your initial attempt and why it didn't work: Your function created lots of numbers, but it overrides them in each loop and only returns the last one:

def func(s):
    for i in range(1, 100):
        t = i
        p = t * 2 + s * 2
        # Next iteration of the loop just overwrites p
    # Returns only the last p
    return p

You could make this a generator (with yield instead of return), but that's probably overkill here, I'll show it nevertheless :-)

l = []
def func(s):
    for i in range(1, 100):
        p = i * 2 + s * 2
        yield p

l.append(list(func(10))) # Need to convert the generator to a list here.
# In this case a simple "l = list(func(10))" would be easier if you don't need to append.
aestrivex
  • 5,170
  • 2
  • 27
  • 44
MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • when using the generator 'yield', the results come out as one 1 element in a list. how can I print 'def func(s)' so I can plot it against another list – p.kumar Mar 20 '16 at 15:25
  • @p.kumar how do you use the generator? At least that way with `list(func(s))` seems to work fine on my computer, the result is a list containing 99 elements. About the `plotting`, maybe have a look at [`matplotlib.pyplot.plot`](http://matplotlib.org/api/pyplot_api.html). – MSeifert Mar 20 '16 at 15:33
4

You are computing a value multiple times (while not appending it to a list), then appending the final value to a list.

Instead, we want to append to the list as we go.

def func(s):
    l = []
    for i in range(1, 100):
        l.append(i*2+s*2)
    return l

You can also do this in one line using a list comprehension if you're going for shortness.

func = lambda s: [(t*2)+s*2 for t in range(1, 100)]

Output:

[22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218]

Note the 218 at the end. Like I said before, you were only returning the last value, thus, your program outputted 218.

Community
  • 1
  • 1
Jason
  • 2,278
  • 2
  • 17
  • 25
  • 4
    Even if you insist on needless one-lining, it's best to do it with `def`, not `lambda`; `lambda` means the function doesn't know its own name, which breaks simple stuff like pickling (implicitly involved in stuff like `multiprocessing` or `concurrent.futures` or even `copy.deepcopy` in some cases). `def func(s): return [(t*2)+s*2 for t in range(1, 100)]` is just as one-lined, similarly concise, and more functional (in the English sense, not the language design sense). – ShadowRanger Mar 19 '16 at 02:14
0

Since there are plenty of solution that. With different libraries or generators. You had only indentation problem in your code and it was ready to fly. Here is the just small modification in your code.

#In Python3
def func(s):
    for i in range(1,100):
        p = i * 2 + s * 2
        l.append(p)
    return l
l =[]
print(func(10))
Hayat
  • 1,539
  • 4
  • 18
  • 32