Can global variable be passed into Python function?

S

Sam

I need to pass a global variable into a python function. However, the global variable does not seem to be assigned after the function ends. Is it because parameters are not passed by reference? How can I get function parameters to be passed by reference in Python?
 
D

dieter

Sam said:
I need to pass a global variable into a python function.

Python does not really have the concept "variable".

What appears to be a variable is in fact only the binding of an
object to a name. If you assign something to a variable,
all you do is binding a different object to the name.

Thus, if you have:

i = 1
def f(x): x = 5

f(i)

Then "i" will remain "1" and not become "5".
The effect of "x = 5" is that the name "x" gets bound to "5"
(where is formerly was bound to "1").
However, the global variable does not seem to be assigned after the function ends. Is it because parameters are not passed by reference?

Python lacks the notion of "variable". Thus, it does not
pass variables into functions but objects.
The objects, however, get passed by reference.
How can I get function parameters to be passed by reference in Python?

You can implement your own concept of variable, e.g. like this:

class Variable(object):
def __init__(self, value): self.value = value

The little program above then becomes:

i = Variable(1)
def f(x): x.value = 5

f(i)
i.value # this is now 5
 
P

Peter Otten

Sam said:
I need to pass a global variable into a python function. However, the
global variable does not seem to be assigned after the function ends. Is
it because parameters are not passed by reference? How can I get function
parameters to be passed by reference in Python?

If the variable you want to process is always the same global variable you
can declare it:
.... global x
.... x += 1
....3

If you want to change ("rebind") varying global names you have to be
explicit:
.... return x + 1
....(1, 2)

Then there are ugly hacks that make your code hard to follow. Don't use
these:
.... globals()[name] += 1
....
.... setattr(module, name, getattr(module, name) + 1)
....6
 
G

Gary Herron

I need to pass a global variable into a python function. However, the global variable does not seem to be assigned after the function ends. Is it because parameters are not passed by reference? How can I get function parameters to be passed by reference in Python?

Are you passing a value *into* a function, or back *out of* the
function? These are two very different things, and your question
mentions both and seems to confuse them.

You can pass any value into a function through its parameters, whether
that value comes from a local variable, global variable, or the result
of some computation. (But consider: it is the value that is being passed
in -- not the variable that contains that value.) You can't pass values
back out from a function through assignment to any of the parameters.

The global statement is a way to allow a function to assign to a global
variable, but this would not be considered "passing" a global into a
function. It's just a way to access and assign to a global variable
from withing a function.

v = 123

def f(...):
global v # Now v refers to the global v
print(v) # Accesses and prints the global v
v = 456 # Assigns to the global v.

Gary Herron
 
S

Steven D'Aprano

I need to pass a global variable into a python function. However, the
global variable does not seem to be assigned after the function ends. Is
it because parameters are not passed by reference? How can I get
function parameters to be passed by reference in Python?

You cannot. Python does not support either pass-by-reference or pass-by-
value calling conventions. Instead, it supports the same calling
convention as Java, Ruby and other modern languages (which confusingly
those two languages both call something different), "call by object
sharing".

To understand more about Python's calling convention, and why neither
call-by-reference nor call-by-value are appropriate, please read these
articles:

https://mail.python.org/pipermail/tutor/2010-December/080505.html
http://effbot.org/zone/call-by-object.htm

and also see the Wikipedia article:

http://en.wikipedia.org/wiki/Evaluation_strategy


If you show us a sample of your code, together of a sample of how you
expect it to work, we can suggest an alternate way to solve that problem.
 
J

Jussi Piitulainen

dieter said:
Python does not really have the concept "variable".

What appears to be a variable is in fact only the binding of an
object to a name. If you assign something to a variable,
all you do is binding a different object to the name.

Thus, if you have:

i = 1
def f(x): x = 5

f(i)

Then "i" will remain "1" and not become "5".
The effect of "x = 5" is that the name "x" gets bound to "5"
(where is formerly was bound to "1").

In alleged contrast, the observable behaviour of languages that "have
variables" is the same. This is not considered confusing by the people
who insist that there are no variables in Python.

Note: I do not object to Python's choice of different preferred
terminology. Python seems to be doing fine with that. I do object to
the insistence that Python needs this different terminology because it
behaves differently from the languages where variables are called
variables. Python behaves the same.

Here's Java, where I demonstrate with both a class variable i and a
local variable j; I used String so that this same demonstration will
still serve after someone points out that Java's primite numbers are
not quite objects, which is true but irrelevant:

$ cat Var.java
public class Var {
public static String i = "1";
public static String f(String x) {
x = "5";
return x;
}
public static void main(String... args) {
String j = "2";
System.out.println("i == " + i + ", j == " + j);
System.out.println("f(i) == " + f(i) + ", " +
"f(j) == " + f(j));
System.out.println("i == " + i + ", j == " + j);
}
}
$ javac Var.java
$ java -cp . Var
i == 1, j == 2
f(i) == 5, f(j) == 5
i == 1, j == 2
$

This is C, where I again demonstrate with both a global and a local
variable, but here I leave them as ints; I think C might be a language
where the word "variable" has been used to mean something like a block
of memory, which is a different usage; still, would someone be willing
to explain the behaviour of this program by "C lacks variables":

$ cat var.c
#include <stdio.h>
int i = 1;
int f(int x) { x = 5; return x; }
main() {
int j = 2;
printf("i == %d, j == %d\n", i, j);
printf("f(i) == %d, f(j) == %d\n", f(i), f(j));
printf("i == %d, j == %d\n", i, j);
}
$ gcc -o var var.c
$ ./var
i == 1, j == 2
f(i) == 5, f(j) == 5
i == 1, j == 2
$

This is Scheme, which is where I come from; its variables behave the
same as the corresponding machinery in Python with regard to the
problem at hand:

$ cat var.scm
(define i 1)
(define (f x) (set! x 5) x)
(let ((j 2))
(display "i == ") (write i) (display ", j == ") (write j) (newline)
(display "f(i) == ") (write (f i))
(display ", f(j) == ") (write (f j)) (newline)
(display "i == ") (write i) (display ", j == ") (write j) (newline))
$ gsi var.scm
i == 1, j == 2
f(i) == 5, f(j) == 5
i == 1, j == 2
$
Python lacks the notion of "variable". Thus, it does not
pass variables into functions but objects.
The objects, however, get passed by reference.

I think the relevant answer is simply that i and x are different
variables. In Python terminology, I think you would have to say that
they are different names. With a slight change, you would need to
explain how i and i are different names (I think), and then you would
introduce the concept of different namespaces.

Python indeed does not pass variables (and this is a relevant), but
neither do the other languages that "have variables".

[snip]
 
M

Marko Rauhamaa

Jussi Piitulainen said:
In alleged contrast, the observable behaviour of languages that "have
variables" is the same. This is not considered confusing by the people
who insist that there are no variables in Python.

But of course there are variables in Python:

By “frozen†we mean that all local state is retained, including the
current bindings of local variables, [...] (<URL:
http://docs.python.org/3.2/reference/simple_stmts.html
#the-yield-statement>)

The public names defined by a module are determined by checking the
module’s namespace for a variable named __all__ (<URL:
http://docs.python.org/3.2/reference/simple_stmts.html
#the-import-statement>)

It would be impossible to assign to a global variable without global
(<URL: http://docs.python.org/3.2/reference/simple_stmts.html
#the-global-statement>)

etc etc.

However, your point about "observable behavior" is key, and Python users
of all people should get the principle (as it is related to duck
typing).
Python indeed does not pass variables (and this is a relevant), but
neither do the other languages that "have variables".

Maybe the idea comes from the fact that you can't easily pass a
variable to a function for modification.

Consider this C function:

void make_printable(const char **ref)
{
if (!*ref)
*ref = "<NULL>";
}

which allows:

make_printable(&x);
make_printable(&s->name);
make_printable(&a);


Marko
 
N

Ned Batchelder

Python does not really have the concept "variable".

What appears to be a variable is in fact only the binding of an
object to a name. If you assign something to a variable,
all you do is binding a different object to the name.

Man, do I hate this idea that Python has no variables. It has variables
(names associated with values, and the values can change over the course
of the program), they just don't work the same as C or Fortran
variables. In fact, they work exactly the same as Javascript or Ruby
variables.

Python's variables are names bound to values.
http://nedbatchelder.com/text/names.html has lots more details.
 
M

Marko Rauhamaa

Ned Batchelder said:
Man, do I hate this idea that Python has no variables. It has
variables (names associated with values, and the values can change
over the course of the program),

In classic functional programming, the values of variables can't change
but they are still called variables (even though "parameters" might be
more fitting).
they just don't work the same as C or Fortran variables. In fact, they
work exactly the same as Javascript or Ruby variables.

Apart from a fact that a C variable has an address (references are
first-class objects, if you will), I really don't see a difference
between a C variable and a Python variable.


Marko
 
T

Travis Griggs

Man, do I hate this idea that Python has no variables. It has variables (names associated with values, and the values can change over the course of the program), they just don't work the same as C or Fortran variables. In fact, they work exactly the same as Javascript or Ruby variables.

Thank you!

+11

I get tired of the “Python doesn’t have variables” line.

What makes Python variables/bindings/references/aliases/namedvalues/slots/bucketsofstuff surprising to new arrivals from other language kingdoms, is that accessing is pragmatically implicit (walks the scope tree for you) and assignment may require explicitness. IOW, for some “variables”, you have to do something explicit to make the variable you want to refer to, vary. Some might say there is a lack of symmetry. Pros and cons.

Personally, I don’t care. It’s one of those lessons you just learn as you go.
 
C

Chris Angelico

What makes Python variables/bindings/references/aliases/namedvalues/slots/bucketsofstuff surprising to new arrivals from other language kingdoms, isthat accessing is pragmatically implicit (walks the scope tree for you) and assignment may require explicitness. IOW, for some “variablesâ€, you have to do something explicit to make the variable you want to refer to, vary. Some might say there is a lack of symmetry. Pros and cons.

What you're looking at there, I think, is actually quite tangential to
the question of Python having/not having variables, and it's to do
with scoping rules. Correct me if I'm wrong.

g = "global"
c = 0
def f():
print(g) # References two globals
l = "local"
print(l) # References one global and one local
global c
c = 1 # References one global

As an alternative, Python could have asked us to declare the other way:

def f():
print(g) # References two globals
local l
l = "local"
print(l) # References one global and one local
c = 1 # References one global

It would still be the same name binding / object reference model, with
just a different keyword used to change the default behaviour of name
lookups. And the difference is comparatively slight. We get an
encouragement to use locals rather than globals, but on the flip side,
we need two keywords (global/nonlocal) where a single one (local, or
as ECMAScript puts it, "var") could handle the other case. It's a lack
of symmetry, but having worked with PHP (where you have to declare
*every* global, except for the magical superglobals, and except for
functions (which are in a completely different namespace), and except
for constants), I am very much glad that Python puts everything in
together as just "names", and then allows us to reference global names
like "print" without declarations. It's a miswart.

ChrisA
 
M

Marko Rauhamaa

On the question of how variables can be passed to functions, C, of
course, has the & operator and Pascal has the "var" keyword.

An analogous thing can be achieved in Python 3 (but not in Python 2, I'm
afraid). The & operator corresponds to an ad hoc property class as in
the program below (not intended to be serious).

The program demonstrates how to write a universal "swap" function that
interchanges two references.


Marko

==clip=clip=clip========================================================
#!/usr/bin/env python3

import sys

def main():
some_list = [ 'a', 'b', 'c' ]
some_dict = { 'few' : 'ding',
'good' : 'dang',
'men' : 'dong' }
some_value = 'certainly'

class SomeListElementProperty:
"""&some_list[1]"""
def get(self):
return some_list[1]
def set(self, value):
some_list[1] = value

class SomeDictEntryProperty:
"""&some_dict["men"]"""
def get(self):
return some_dict['men']
def set(self, value):
some_dict['men'] = value

class SomeValueProperty:
"""&some_value"""
def get(self):
return some_value
def set(self, value):
nonlocal some_value
some_value = value

swap(SomeListElementProperty(), SomeDictEntryProperty())
swap(SomeListElementProperty(), SomeValueProperty())

sys.stdout.write("{}\n".format(some_list))
sys.stdout.write("{}\n".format(some_dict))
sys.stdout.write("{}\n".format(some_value))

def swap(px, py):
x = px.get()
y = py.get()
px.set(y)
py.set(x)

if __name__ == '__main__':
main()
==clip=clip=clip========================================================
 
D

Dennis Lee Bieber

Thank you!

+11

I get tired of the “Python doesn’t have variables†line.

If one is coming from the world where "variable" means "name
identifying a fixed location in memory" then Python does not have
"variables".

BASIC, C, FORTRAN, COBOL, Assembly... A "variable" is synonym for an
address [a box that holds things].

Even Python's mutable types (list, dictionary, for example) do not
follow the "fixed location" metaphor. Each cell in a list merely references
some object, and assignment to that cell changes the reference, not the
object.
 
N

Ned Batchelder

Thank you!

+11

I get tired of the “Python doesn’t have variables†line.

If one is coming from the world where "variable" means "name
identifying a fixed location in memory" then Python does not have
"variables".

BASIC, C, FORTRAN, COBOL, Assembly... A "variable" is synonym for an
address [a box that holds things].

Even Python's mutable types (list, dictionary, for example) do not
follow the "fixed location" metaphor. Each cell in a list merely references
some object, and assignment to that cell changes the reference, not the
object.

So we agree: variables in Python work differently than they do in those
languages.

If one is coming from the world where "variable" means "name bound to a
value", then Python does have "variables".

Javascript, Ruby, Lisp, Perl, PHP, Smalltalk, Lua, Julia... a
"variable" is a name bound to a value.
 
S

Steven D'Aprano

Man, do I hate this idea that Python has no variables. It has variables
(names associated with values, and the values can change over the course
of the program), they just don't work the same as C or Fortran
variables. In fact, they work exactly the same as Javascript or Ruby
variables.

I sympathise with your view. It seems quite ridiculous to claim that
Python has no variables. If it has no variables, what on earth does it
mean when we say "x = 42"?

But the very ridiculousness is what gives it the attention-grabbing power
that makes it a useful meme. "Python variables don't behave like C
variables" might be true, but it's also wish-washy and forgettable.

In my own case, I never quite got Python's name binding semantics until I
was introduced to the "Python has no variables" meme. That got my
attention long enough to listen to the actual message: my assumptions
about how variables behave was based on Pascal semantics, and Python
doesn't quite follow the same rules. Consequently, if I implicitly define
"variable" to mean "Pascal variables", as I had been, then Python has no
variables, it has these things called "name bindings".

That's when I got it.

I went through a phase where I too insisted that Python had no variables.
But then my natural laziness asserted itself, and I decided that the word
"variable" is too useful to always reject it (and besides, C- and Pascal-
like languages don't have a monopoly on the word "variable"). Now, I use
the terms "variable" or "reference" or "name binding" as I feel makes the
most sense in context, depending on my best guess of the risk of
misunderstanding or confusion.
 
N

Ned Batchelder

I sympathise with your view. It seems quite ridiculous to claim that
Python has no variables. If it has no variables, what on earth does it
mean when we say "x = 42"?

But the very ridiculousness is what gives it the attention-grabbing power
that makes it a useful meme. "Python variables don't behave like C
variables" might be true, but it's also wish-washy and forgettable.

In my own case, I never quite got Python's name binding semantics until I
was introduced to the "Python has no variables" meme. That got my
attention long enough to listen to the actual message: my assumptions
about how variables behave was based on Pascal semantics, and Python
doesn't quite follow the same rules. Consequently, if I implicitly define
"variable" to mean "Pascal variables", as I had been, then Python has no
variables, it has these things called "name bindings".

That's when I got it.

I went through a phase where I too insisted that Python had no variables.
But then my natural laziness asserted itself, and I decided that the word
"variable" is too useful to always reject it (and besides, C- and Pascal-
like languages don't have a monopoly on the word "variable"). Now, I use
the terms "variable" or "reference" or "name binding" as I feel makes the
most sense in context, depending on my best guess of the risk of
misunderstanding or confusion.

This is an interesting perspective, thanks.

I think it might be that the OP's question, "Can a global variable be
passed into a function", really had nothing to do with the
name/value/variable distinction, and we've done it again: taken a simple
question and spun off into pedantry and trivia.
 
S

Steven D'Aprano

I think it might be that the OP's question, "Can a global variable be
passed into a function", really had nothing to do with the
name/value/variable distinction, and we've done it again: taken a simple
question and spun off into pedantry and trivia.

You might be right, but the OP's question isn't really clear. Surely he
didn't mean something as trivial as this?

x = 1 # This is a global
some_function(x) # Passing a global into a function


His description, especially the comment about pass by reference, suggests
that there is more to it than just passing a global variable as argument
to a function. I think he is trying to *write* to the variable as well,
as an output variable, something like this:

x = 1
y = 2
some_function(x)
assert x == 99
some_function(y)
assert y == 99


Sadly, it appears to have been a drive-by question: Sam tossed a question
out the window as he drove by, and may never come back for the answer...
I hope I'm wrong, but it's been nearly 24 hours since the question was
asked and not a peep from the OP.


Sam, if you're out there reading this, please respond with more detail
about what you are trying to do!
 
C

Chris Angelico

On the question of how variables can be passed to functions, C, of
course, has the & operator and Pascal has the "var" keyword.

That doesn't pass a variable into a function, though. It passes the
address of that variable, and C lets you stuff something into an
address. That's not the same thing.

ChrisA
 
S

Steven D'Aprano

On the question of how variables can be passed to functions, C, of
course, has the & operator and Pascal has the "var" keyword.

An analogous thing can be achieved in Python 3 (but not in Python 2, I'm
afraid). The & operator corresponds to an ad hoc property class as in
the program below (not intended to be serious).

I'm glad you added that comment about not being serious. But even so,
your code is extremely unPythonic and doesn't even succeed in doing what
you try to accomplish:

The program demonstrates how to write a universal "swap" function that
interchanges two references.

For the record, there is no need for such a universal swap function in
Python, as the right way to do it is:

x, y = y, x


But your code doesn't succeed at doing what it sets out to do. If you try
to call it like this:

py> x = 23
py> y = 42
py> swap(x, y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in swap
AttributeError: 'int' object has no attribute 'get'

not only doesn't it swap the two variables, but it raises an exception.
Far from being a universal swap, it's merely an obfuscated function to
swap a few hard-coded local variables.
 
S

Steven D'Aprano

That doesn't pass a variable into a function, though. It passes the
address of that variable, and C lets you stuff something into an
address. That's not the same thing.

Be careful about conflating the implementation with the interface. As I
understand it, the interface C literally is that &x gives you the address
of x. But that's not what the var keyword is for in Pascal (although that
may be how it is implemented).

In Pascal, if you have a function or procedure:

procedure plus(a:integer, var b:integer);
begin
b := a+b;
end;


and a couple of variables in some other scope, for simplicity lets make
them global:

var
foo: int;
bar: int;

begin
foo := 23;
bar := 1;
plus(bar, foo);
writeln(foo);
end.

the output will be 24. If we could peek into procedure plus, we would see
that argument a was a *copy* of global bar, while argument b wasn't
merely a copy of foo, it actually was foo. So assigning to b inside plus
is the same as assigning to foo in the global scope.

If we added a call:

plus(2, bar);

to the main program, then inside plus argument a would have the value 2,
and argument b would now be precisely the same variable as global bar.
After the procedure returns, bar would have the value 3.

Now I daresay that under the hood, Pascal is passing the address of foo
(or bar) to the procedure plus, but inside plus you don't see that
address as the value of b. You see the value of foo (or bar).

C does not do that -- you have to manually manage the pointers yourself,
while Pascal does it for you. And Python also has nothing like that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top