If I have many variables I want to initialize with the same value, I use:
a = b = c = ""
Is there a similar shorthand for defining many functions that do the same thing? That is, neither of the following works:
def x() = y() = z():
def x() = def y() = def z():
You can simply assign functions like you would assign variables.
def z():
whatever
x = y = z
You can't do it in one line if you want to use def, but if you can make it into a lambda you can make a one-liner:
x = y = z = lambda foo: bar()
How about:
def z():
pass
x = y = z
Uhm... functions are also objects, so you can do this:
def foo():
pass
bar = foo
As you can see, the syntax is the same.
Why would you WANT to, hell if I know.
you can do soemthing like this:
def X():
pass
Y = Z = X
Related
Code mock-up & expected results:
X = 10
Y = (X-10)/2
print(Y)
X = 12
print(Y)
I want this to print "0" and then "1", but obviously Y is not dynamically assigned.
I have tried utilizing lambda functions (a la Y = lambda i: (X-10)/2) to get this functionality, but I keep getting <function <lambda> at 0x7f5f6356eea0>.
This is just to avoid needing to run a function or redefine Y at the end of any function that alters the value of X.
Thanks in advance!
Alternatively, you can use properties as well:
class P:
def __init__(self, x):
self.__x = x
self.__y = x
#property
def x(self):
return self.__x
#property
def y(self):
return (self.__x - 10) / 2
#x.setter
def x(self, x):
self.__x = x
You will have to access the values through an instance of the P class, though.
p = P(10)
print(p.y)
p.x = 12
print(p.y)
I have tried utilizing lambda functions (a la Y = lambda i: (X-10)/2)
You need to call the function:
print(Y())
As for having print(Y) print the updated value? Mostly impossible, and what workarounds exist aren't anywhere near worth it. Just be explicit about recomputing the value.
You need to call the lambda:
print(Y())
Assigning a lamda to a variable is essentially the same as defining a function:
def Y():
return (X-10)/2
You can't do what you want with ordinary variables. Assigning a variable copies the value into it, it doesn't create a reference to the expression that was used.
You need to provide x argument to your lambda function. In your case this is 10 or 12.
y = lambda x: (x-10)/2
print(y(10))
>>> 0.0
Use a lambda with a dict to keep track of it:
>>> vars={}
>>> vars['x']=10
>>> vars['y']=lambda :(vars['x']-10.0)/2.0
>>> vars['y']()
0.0
>>> vars['x']=12.0
>>> vars['y']()
1.0
To assign the value using your lambda expression, you need to call it. You can do it in one line:
Y = (lambda i: (i-10)/2)(X)
There is no need for defining additional classes or functions, just add the parentheses and the argument.
The reason you are getting <function <lambda> at 0x7f5f6356eea0> is that a lambda expression produces a function, not the result of executing the function.
I am new to python and object language. I am learning class in python now. but the code below confused me.
class math:
def __init__(self, a, b):
self.a = a
self.b = b
math.add = self.a+self.b
def sum(self):
math.sum = self.a+self.b
s= math(2,1)
x = math.add
y = math.sum
the results look not right. x is 3 but y is not 3. where is my problem?
thanks
I'm guessing what you wanted to do was this.
class math:
def __init__(self, a, b):
self.a = a
self.b = b
self.add = self.a+self.b
def sum(self):
return self.a+self.b
s= math(2,1)
x = s.add
y = s.sum()
print(x)
print(y)
The errors were as follows
You were not calling your instance of math. As these are instance methods, they must reference an instance x = math.add should be x = s.add.
You created a method sum but did not call it y = s.sum simply creates a reference to the function and does not call it, instead you should use y = s.sum()
Your function sum doesn't return anything, so assigning a value to its return value will yield a value of None. To resolve this return a value from sum i.e. return self.a + self.b.
self.add is also quite strange, as it named like a function, but its actually a value, this will not be expected by others looking at your code. A better name for it might be total or remove it since it provides the same functionality as sum.
Sorry if it is confusing; making an example.
def functionA():
x=10
b()
def functionB():
Y=22
return Y
Is there a way to access x from B, without pass it as parameter when I call B?
I would like to avoid to have to do something like
def functionB(var):
From my understanding, I can't call super because B is not part of A, it is just called from it. I would like to call B from A, and access in B a variable in A (or more than one; I am exploring the concept); but without pass it as parameter to B.
Is this even possible in Python?
Yes, you actually can:
import inspect
def A():
X = 42
B()
def B():
print(inspect.stack()[1][0].f_locals['X'])
A()
But you shouldn't.
Here come the downvotes.
This is how you can make sure you only execute it when the caller is "functionA" and you retrieve it's last local value before the call.
This is very sketchy though. Don't do this.
import sys
def functionA():
x=10
x = 5
functionB()
x = 3
def functionB():
frame = sys._getframe()
outer = frame.f_back
if outer.f_code.co_name == "functionA":
print outer.f_locals["x"]
Y=22
return Y
if both are just functions, no. but if you made both functions methods of a containing class, you could make a's variable accessible to fuction b's.
class Wrapper(object):
def __init__():
self.a_val = None
def functionA(self):
self.a_val = 123
self.functionB()
def functionB(self):
# you can access self.a_val here fine.
once you have this, you would call functionA as
Wrapper().functionA()
Well yes, what you want is a global variable:
def functionA():
global x
x=10
functionB()
def functionB():
Y=22
print 'X from B:', x
return Y
functionA()
Of course as any responsible programmer would tell you, be careful with global variables as they can easily turn your code into spaghetti.
The standard way to do that is, naturally, to use a class...
However, for argument sake, there is another way to do it, that will make that variable shared between those two functions and still not be global, using a closure:
def defineFuns():
global functionA, functionB
x = 10
def functionA():
print 'X from A:', x
functionB()
def functionB():
Y=22
print 'X from B:', x
return Y
defineFuns()
functionA()
Or playing with the function's dictionary...
def functionA():
x = 10
print 'X from A:', x
functionB.func_globals['x'] = x
functionB()
def functionB():
Y=22
print 'X from B:', x
return Y
functionA()
This is a perfect case for nested functions.
def a():
x = 10
def b():
y = 22 + x
return y
b()
Function b returns 32 (22+10). The x in function b is the same as the x in a. You can't call b from outside of a, but that makes perfect sense because the value of x would be undefined in that case.
I am new to python. This might be a simple question, but if I have many functions that are dependent on each other how would I access lists from one function to use in another.
So...
def function_1():
list_1=[]
def function_2():
list_2= [2*x for x in list_1]
def function_3():
list_3= [x * y for x, y in zip(list_1, list_2)]
That is not the exact code but that is the idea of my problem. I would just put them all together in one function but I need them to be separate.
The correct way to do this would be to use a class. A class is an object that has internal variables (in your case, the three lists), and methods (functions that can access the internal methods). So, this would be:
class Foo(object):
def __init__(self, data=None):
self.list_1 = data if not data is None else []
def function_2():
self.list_2 = [2 * x for x in self.list_1]
And so on. For calling it:
foo = Foo() # list_1 is empty
foo2 = Foo([1,2,3]) # list_1 is not empty
foo2.function_2()
print foo2.list_2
# prints [2, 4, 6]
Make them arguments and return values:
def function_1():
return []
def function_2(list_1):
return [2*x for x in list_1]
def function_3(list_1, list_2):
return [x * y for x, y in zip(list_1, list_2)]
(this suggests that function_1 isn't much worth having...)
The exact way will depend on exactly how you want things to work, but here is a simple example:
def function_1():
return []
def function_2():
return [2*x for x in function_1()]
def function_3():
return [x * y for x, y in zip(function_1(), function_2())]
The key point is that functions do not generally just "do" things, they return things. If you have a value in one function that you want to use in another function, the first function should return that value. The second function should call the first function, and use its return value.
Functions are basically black boxes -- the outside world doesn't really know what goes on inside or what variables exist there. From the outside, other code only sees what goes in (the function's arguments) and what goes out (its return value).
So if your function computes some value that is to be used elsewhere, it should be returned as the result of the function.
E.g.,
def square(x):
return x * x
Takes a number, computes its square, and returns it.
Then you could do:
print(square(5))
and it will print 25.
So in your case you can return the lists and use them in the other functions, as the other answers showed:
def function_1():
return []
def function_2():
return [2*x for x in function_1()]
def function_3():
return [x * y for x, y in zip(function_1(), function_2())]
Is there a way in Python to manage scope so that variables in calling functions are visible within called functions? I want something like the following
z = 1
def a():
z = z * 2
print z
def b():
z = z + 1
print z
a()
print z
b()
I would like to get the following output
2
4
2
The real solution to this problem is just to pass z as a variable. I don't want to do this.
I have a large and complex codebase with users of various levels of expertise. They are currently trained to pass one variable through and now I have to add another. I do not trust them to consistently pass the second variable through all function calls so I'm looking for an alternative that maintains the interface. There is a decent chance that this isn't possible.
I think this is what you're looking for. If you control the inner functions, and the variable you're looking for is already in scope somewhere in the call chain, but you don't want your users to have to include the variable in the call itself. You clearly don't want the global keyword, because you don't want inner assignments to affect the outer scope.
Using the inspect module gets you access to the calling context. (But, be warned that it's somewhat fragile. You should probably use only for CPython unthreaded.)
import inspect
def calling_scope_variable(name):
frame = inspect.stack()[1][0]
while name not in frame.f_locals:
frame = frame.f_back
if frame is None:
return None
return frame.f_locals[name]
z = 1
def a():
z = calling_scope_variable('z')
z = z * 2
print z
def b():
z = calling_scope_variable('z')
z = z + 1
print z
a()
print z
b()
This does give the right answer of:
2
4
2
This might be the right place for a class:
class MyClass(object):
def __init__(self, z):
self.z = 1
def a(self):
self.z = self.z * 2
print self.z
def b():
self.z = self.z + 1
print self.z
self.a()
print self.z
You can get the same effect with globals but I'd suggest creating your own separate namespace (such as with a class) and using that for your scope.
This is a bit ugly, but it avoids using globals, and I tested it and it works. Using the code from the selected answer found here, the function getSetZ() has a "static" variable that can be used to store a value that is passed to it, and then retrieved when the function is called with None as the parameter. Certain restrictions are that it assumes None is not a possible value for z, and that you don't use threads. You just have to remember to call getSetZ() right before each call to a function that you want the calling function's z to be available in, and to get the value out of getSetZ() and put it in a local variable in that function.
def getSetZ(newZ):
if newZ is not None:
getSetZ.z = newZ
else:
return getSetZ.z
def a():
z = getSetZ(None)
z = z * 2
print z
def b():
z = getSetZ(None)
z = z + 1
print z
getSetZ(z)
a()
print z
getSetZ.z = 0
getSetZ(1)
b()
I hope this helps.
I don't quite understand what you're trying to achieve, but this prints 2, 4, 2:
z = 1
def a():
global z
y = z * 2
print y
def b():
global z
z = z + 1
print z
a()
print z
b()
In general, the best solution is always just to pass the values around - this will be much more predictable and natural, easier to work with and debug:
def a(z):
z = z * 2
print z
def b():
global z
z = z + 1
print z
a(z)
print z
b()
You could define a() in b() and do something similar:
def b():
global z
z = z + 1
print z
def a():
z = z * 2
print z
a()
print z
However, this isn't really optimal.