Using lambda to implement Singleton pattern - python

I'm trying to figure out why this code works, producing only a unique instance of class A.
def singleton_function (c):
print("singleton_function")
x = c()
return lambda : x
#singleton_function
class A:
pass
def test2 () :
x = A()
y = A()
assert x == y
test2()
Output:
python3 test.py
singleton_function
Why is singleton_function only accessed once? A is of type function, so my guess is that when calling A, A(), it returns x, which is the instance of class A, so, it should have printed two times "singleton_function", since I am accessing twice.
What am I thinking wrong?

Consider the decorator syntax:
def singleton_function (c):
print("singleton_function")
x = c()
return lambda : x
#singleton_function
class A:
pass
This is essentially saying that:
A = singleton_function(A)
And singleton_function() creates one instance of A and then returns a function that points to that instance.
So we get
A = lambda: x
Where x is an instance of the original class A. Calling A() returns x which is still that same instance that singleton_function() first created.

Related

unable to use attribute from a python function in another python script

I want to use one of the attributes returned by a function in a python script (x) into a python script (y)
The communication between both scripts works well; I can get functions and attributes, but doesn't allow me to attributes returned by a function.
Here is how I worked:
x.py
def func():
b = 10
a = 15
return [a,b]
c = 20
y.py
from x import func
import x
print (x.c)
print (func.b)
I get the "c" value and the following error AttributeError: 'function' object has no attribute 'b'
I have tried also to print x.b, and I've got AttributeError: module 'WorkingLSTM' has no attribute 'b'
Thanks in advance
The way to call func is by using func(), which would give you [a,b].
example:
funcResult = func()
a = funcResult[0]
b = funcResult[1]
funcResults is the return value from func(), that is the list [a,b].
That's not allowed, you have to call the function to get the value from the functions returned list.
a, b = func()
print(b)
# or just...
print(func()[1])
PS: It's "not allowed" because it doesn't make sense in any way; when there is no function call, there is not variable b at all. You might take a look at classes, they can hold static variables.
you cannot access local variables of a function.
these variables exist only during the the time where func is executed and are destroyed afterwards.
You can of course call the function and look at the result, but the result is just a list with two values
rslt = func()
print("A = ", rslt[0])
print("B = ", rslt[1])
The variable was declared inside a function making it a local variable and as such it can"t be accessed outside the function.
The variable is declared outside of the function making it a global variable and is not in anyway tied to your function.
The concept of attributes relates to Classes and you are dealing with a function so you might have to treat it as a class object.
If you are concerned bout accessing the local variables, you might as well do this:
y.py
from x import *
d = func() # func returns a list which is now
# identified/referenced by variable d
# displays the elements in the list using index position
print(d[0])
print(d[1])
If you want to use attributes, you may create a callable class instead of function:
class Func:
def __init__(self):
self.b = 10
self.a = 15
def __call__():
return [self.a, self.b]
func = Func()
Python has the concept of the scope. Local variables have no effect outside the function.
If you want to use it, use class and self or make getter function(but it's not Pythonic).
x.py
class X:
def __init__(self):
self.b = 10
self.a = 15
self.c = 20
def func(self):
return [self.a, self.b]
y.py
from x import X
x = X()
print(x.c)
print(x.func()[1])

How can I create an automatically updated variable in Python 3+?

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.

Global variable through classes?

I'm trying to call a method of a class using a global variable, but there seems to be something wrong with my logic.
In the code below, A calls B which calls C which calls a method of B.
x = None
class A():
def __init__(self):
global x
x = B()
class B():
def __init__(self):
C()
def bla(self):
print('bla')
class C():
def __init__(self):
global x
x.bla()
A()
The error I'm getting:
AttributeError: 'NoneType' object has no attribute 'bla'
What am I missing?
When you do x = B(), the result of calling B() cannot be assigned to x until after B is finished initialized. But B.__init__() is called when you create the B instance, and it immediately calls C(). In other words, when you do x = B(), things happen in this order:
call B.__init__()
call C.__init__() (because of C() call in B.__init__())
assign result of B() to x.
But step 3 never happens, because C.__init__() raises an error, because step 3 hasn't happened yet so the object hasn't been assigned to x yet.
It's not clear what you're trying to accomplish here, so it's hard to say how best to change your code. There is no way for C.__init__ to make use of a variable that will not be defined until after C.__init__ finishes running.
Here is your problem
you say
x = b()
well, x is None until b finishes initializing... which also means until c finishes initializing, which would cause a problem in class C when you do
x.bla()
This is because x is not completely initialized until it finishes calling the init function for each class. Here you tried to access global x, before completing its initialization.

Can I access variable X in function B, if it is located in function A, which call function B?

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.

Need help walking through logic of this code

I'm pretty new with Python and programming in general, so excuse the lack of "fu". :)
I'm having trouble understanding this class call:
snippet
class bar:
def __init__(self, a):
self.a = a
def __add__(self, b):
s = self.a + b.a
return s
end snippet
So, from the interpreter, if I issue:
x = bar(10)
y = bar(20)
z = x + y
print(z)
I get '30' back. That's correct.
I see how self.a is created, but I don't understand how b.a is getting created to do the addition.
Any guidance is appreciated.
When you call x + y it is actually translated to:
x.__add__(y)
Therefore, this method is called:
__add__(self, b) # __add__(x, y)
Which results in:
s = x.a + y.a # 30
return 30
In this code, b.a isn't being created, it is being accessed. You're basically passing in y as the argument b, which already has an a attribute associated with it since it is an object of type bar. If you want to step through your code go to http://www.pythontutor.com
x = bar(a) creates an object of the class bar with an a value of 'a'. Each bar object has a property/variable named a.
In x + y, the function add of x is called using y as the parameter.
So b = y, meaning b.a = y.a = 20.

Categories

Resources