Mike
Mike

Reputation: 11

Globals as function input instead arguments

I'm just learning about how Python works and after reading a while I'm still confused about globals and proper function arguments. Consider the case globals are not modified inside functions, only referenced.

Can globals be used instead function arguments? I've heard about using globals is considered a bad practice. Would it be so in this case?

Calling function without arguments:

def myfunc() :
    print myvalue

myvalue = 1
myfunc()

Calling function with arguments

def myfunc(arg) :
    print arg

myvalue = 1
myfunc(myvalue)

Upvotes: 0

Views: 760

Answers (4)

pypat
pypat

Reputation: 1116

It depends on what you want to do.

If you need to change the value of a variable that is declared outside of the function then you can't pass it as an argument since that would create a "copy" of that variable inside the functions scope.
However if you only want to work with the value of a variable you should pass it as an argument. The advantage of this is that you can't mess up the global variable by accident.

Also you should declare global variable before they are used.

Upvotes: 0

rmunn
rmunn

Reputation: 36688

There are several reasons why using function arguments is better than using globals:

  1. It eliminates possible confusion: once your program gets large, it will become really hard to keep track of which global is used where. Passing function arguments lets you be much more clear about which values the function uses.
  2. There's a particular mistake you WILL make eventually if you use globals, which will look very strange until you understand what's going on. It has to do with both modifying and reading a global variable in the same function. More on this later.
  3. Global variables all live in the same namespace, so you will quickly run into the problem of overlapping names. What if you want two different variables named "index"? Calling them index1 and index2 is going to get real confusing, real fast. Using local variables, or function parameters, means that they all live in different namespaces, and the potential for confusion is greatly reduced.

Now, I mentioned modifying and reading a global variable in the same function, and a confusing error that can result. Here's what it looks like:

record_count = 0  # Global variable
def func():
    print "Record count:", record_count
    # Do something, maybe read a record from a database
    record_count = record_count + 1  # Would normally use += 1 here, but it's easier to see what's happening with the "n = n + 1" syntax

This will FAIL: UnboundLocalError: local variable 'record_count' referenced before assignment

Wait, what? Why is record_count being treated as a local variable, when it's clearly global? Well, if you never assigned to record_count in your function, then Python would use the global variable. But when you assign a value to record_count, Python has to guess what you mean: whether you want to modify the global variable, or whether you want to create a new local variable that shadows (hides) the global variable, and deal only with the local variable. And Python will default to assume that you're being smart with globals (i.e., not modifying them without knowing exactly what you're doing and why), and assume that you meant to create a new local variable named record_count.

But if you're accessing a local variable named record_count inside your function, Python won't let you access the global variable with the same name inside the function. This is to spare you some really nasty, hard-to-track-down bugs. Which means that if this function has a local variable named record_count -- and it does, because of the assignment statement -- then all access to record_count is considered to be accessing the local variable. Including the access in the print statement, before the local variable's value is defined. Thus, the UnboundLocalError exception.

Now, an exercise for the reader. Remove the print statement and notice that the UnboundLocalError exception is still thrown. Can you figure out why? (Hint: before assigning to a variable, the value on the right-hand side of the assignment has to be calculated.)

Now: if you really want to use the global record_count variable in your function, the way to do it is with Python's global statement, which says "Hey, this variable name I'm about to specify? Don't ever make it a local variable, even if I assign to it. Assign to the global variable instead." The way it works is just global record_count (or any other variable name), at the start of your function. Thus:

record_count = 0  # Global variable
def func():
    global record_count
    print "Record count:", record_count
    # Do something, maybe read a record from a database
    record_count = record_count + 1  # Again, you would normally use += 1 here

This will do what you expected in the first place. But hopefully now you understand why it will work, and the other version won't.

Upvotes: 0

Aya
Aya

Reputation: 41950

I've heard about using globals is considered a bad practice. Would it be so in this case?

It depends on what you're trying to achieve. If myfunc() is supposed to print any value, then...

def myfunc(arg):
    print arg

myfunc(1)

...is better, but if myfunc() should always print the same value, then...

myvalue = 1

def myfunc():
    print myvalue

myfunc()

...is better, although with an example so simple, you may as well factor out the global, and just use...

def myfunc():
    print 1

myfunc()

Upvotes: 2

Sukrit Kalra
Sukrit Kalra

Reputation: 34493

Yes. Making a variable global works in these cases instead of passing them in as a function argument. But, the problem is that as soon as you start writing bigger functions, you quickly run out of names and also it is hard to maintain the variables which are defined globally. If you don't need to edit your variable and only want to read it, there is no need to define it as global in the function.

Read about the cons of the global variables here - Are global variables bad?

Upvotes: 0

Related Questions