0

I'm newbie with a newbie question that couldn't find the answer (here or on Google).

I'm learning write functions and don't understand why this happening.

The code:

#func

def draw(n):
    import random
    nbers=(random.sample(range(1,101), n))
    print(nbers)

ns=int(input("How many numbers you want?"))

draw(ns)
print(nbers)

The log:

 How many numbers you want?5
[57, 10, 76, 46, 66]

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-16-50675fd81745> in <module>
      9 
     10 draw(ns)
---> 11 print(nbers)

NameError: name 'nbers' is not defined

The question:

Why the print output (inside function) works, but if I call the list produced (printing the list again), it will be empty?

How can I use the output if the list has numbers in the first moment and when I print it again the numbers are gone?

What's happening here?

Thank you for your help!

Ludwig

Ludwig
  • 1
  • 1
  • If every function you defined would create names accessible at the outer scope it would be very difficult not to clash. Imagine a system with thousands of functions. You don't want names leaking out of every function. The name is only valid within the scope of the function, between the colon starting the block and the final dedent at the end of the function definition. – Peter Wood May 17 '21 at 20:46
  • You can return values from a function, and assign them to a name. – Peter Wood May 17 '21 at 20:47
  • But doesn't that make it impossible to use an output in another function, for example? How can I use the result of a function if it only works within the one that gave rise to it? – Ludwig May 17 '21 at 20:49
  • Peter Wood, Thank you all for your help! – Ludwig May 17 '21 at 20:52
  • 1
    See also: [Short description of the scoping rules](https://stackoverflow.com/questions/291978/short-description-of-the-scoping-rules) – G. Anderson May 17 '21 at 20:53
  • @Ludwig if another function needs a value, pass it as a parameter. All procedural code is a combination of inputs, processing, and outputs. Making inputs/outputs global is poor design as it can be difficult to understand. Design your functions to have well defined inputs and outputs. It makes it easier to use and test them. – Peter Wood May 18 '21 at 06:52

2 Answers2

1

nbers is not in the global scope, it's only in the scope of draw, meaning it can only be accessed from within draw. You could return it rather than printing it so that you can access it outside of draw:

def draw(n):
    import random
    return random.sample(range(1,101), n)

ns=int(input("How many numbers you want?"))

nbers=draw(ns)
print(nbers)

Or, you can use global scope instead:

#func

def draw(n):
    import random
    global nbers
    nbers=(random.sample(range(1,101), n))
    print(nbers)

ns=int(input("How many numbers you want?"))

draw(ns)
print(nbers) #at this point, draw() already printed nbers, so this just prints it again
Random Davis
  • 6,662
  • 4
  • 14
  • 24
-1

I found an easy fix to your issue. First of all, here is the code that you should be using...

nbers = 0  #this sets the variable so that it can be called globally in the definition

def draw(n):
     global nbers #this grabs the variable, and puts it on the global spectrum
     import random
     nbers=(random.sample(range(1,101), n))
     #print(nbers) used to be here, but I suggest removing it because then it will be printed twice

ns=int(input("How many numbers you want?"))

draw(ns)
print(nbers)

This should be a good fix to your issue, I was happy to help!

  • This is not a good fix. Global data generally makes it difficult to reason about code, to test code, to reorganise code. – Peter Wood May 18 '21 at 06:49