I have a function in python and I want to declare 2 variables only the first time I call this function and then change their values, something like this :
def function():
x=0
z=2
if(x>z):
other_function()
else:
x+=1
With this way,every time I call the function()
, x becomes 0 and z becomes 2.
I tried to make them global outside of the function() but it gives me error :
UnboundLocalError: local variable 'x' referenced before assignment
How can I declare the values the first time I call the function()?
7 Answers 7
I disagree with the other answers, that only try to give a direct answer to your question.
You have a combination of state (the variables) with a function / functions using that state. That's what a class is for.
class myclass:
def __init__(self):
self.x = 0
self.z = 2
def myfunction(self):
if self.x > self.z:
other_function() # Possibly self.other_function()
# if that one also uses x or z
else:
self.x += 1
Use as:
instance = myclass()
instance.myfunction()
instance.myfunction() # Etc
1 Comment
Welcome to closure
You should write some like this:
def f(x):
def g(y):
return x + y
return g
def h(x):
return lambda y: x + y
a = f(1)
b = h(1)
f(1)(5)
h(1)(5)
Comments
You can make use of lexical scope and global in Python:
x = 0
z = 2
def foo():
global x
if (x > z):
bar()
else:
x += 1
foo()
Comments
You could use default function arguments
i.e.)
def function(x = None, z = None):
if x is None:
x=0
if z is None:
z=2
If you pass the value of x or z the passed value is used else it is initialized to the value given in the function
Comments
If you want to get x and z from somewhere outside of the function then they'll have to be passed to function
as arguments. For example:
def function(a,b):
if(a>b):
other_function()
else:
a+=1
return a, b
which can then be called with
x, z = function(0,2)
2 Comments
a+=1
won't work. Yet your thinking is good.I would put them in a dictionary for better readability:
_VALS = {'x': 0, 'z': 2}
def function():
if _VALS['x'] > _VALS['z']:
other_function()
else:
_VALS['x'] += 1
Comments
You can abuse the mighty mutable default value with caution.
def func(vals = {'x': 0, 'z': 2}):
print vals['x']
vals['x'] += 1
func()
>> 0
func()
>> 1
func()
>> 2
Although I guess the proper way of doing this will be using a decorator:
def default_value_decorator(func):
def inner(*args, **kwargs):
returned_val = func(*args, **kwargs)
inner.x += 1
return returned_val
inner.x = 0
inner.z = 2
return inner
@default_value_decorator
def func():
print func.x
func()
>> 0
func()
>> 1
And a more reusable version where the starting values of x
and z
can be passed to the decorator:
def default_value_decorator(x, z):
def a(func):
def inner(*args, **kwargs):
returned_val = func(*args, **kwargs)
inner.x += 1
return returned_val
inner.x = x
inner.z = z
return inner
return a
@default_value_decorator(0, 2)
def func():
print func.x
func()
>> 0
func()
>> 1