I am looking for a way to init a variable in a class. This variable is dependent of other variables that I init in the same class too. Here is an example.
Class class():
def __init__()
self.a = None
self.b = None
self.sum = self.a + self.b
def change_a_and_b()
self.a = input("a = ")
self.b = input("b = ")
def print_sum()
print(self.sum)
This is a simplified example. In my program self.sum is a complicated calculation which I want to use like a "shortcut" so I don't need to write it a lot of times. The problem is I input the variables after the init function. I just don't want to execute self.sum = self.a + self.b when I run __init__. I think there is a do_thing parameter, but I don't know how to use it.
You can make sum a property:
class my_class():
def __init__(self)
self.a = None
self.b = None
#property
def sum(self):
return self.a + self.b
def change_a_and_b(self)
self.a = input("a = ")
self.b = input("b = ")
def print_sum(self)
print(self.sum)
Related
I think to have a use case for the factory pattern method in python and have two ideas how to implement it (see below). Both work, but are they really the same? Option2 looks much clearer to me, despite having a few more lines. Is my gut feeling right? Or is there a third better option?
Option 1
def inner_factory_func(a):
class Inner:
def __init__(self, b):
self.a = a
self.b = b
def call(self):
return self.a + self.b
return Inner
inner_factory = inner_factory_func('a')
inner = inner_factory('b')
res = inner.call() # ='ab'
Option 2
class Inner:
def __init__(self,a,b):
self.a = a
self.b = b
def call(self):
return self.a+self.b
class InnerFactory:
def __init__(self,a ):
self.a = a
def create(self,b) -> Inner2:
return Inner(self.a,b)
inner_factory = InnerFactory('a')
inner = inner_factory.create('b')
res = inner.call() # ='ab'
I want to access a variable created inside some method from another method. For instance:
class text():
def __init__(self, text):
self.txt = text
def sp1(self):
self.a = self.txt.split(',')[0]
self.b = self.txt.split(',')[1]
return self.a
def sp2(self):
return self.b
Now when I try to apply this like in:
T = text('I woke up early, it is school today')
print(T.sp2())
I get an error that 'text' object has no attribute 'b'
I don't understand where the problem seems to be?
Perhaps you mean:
T = text('I woke up early, it is school today')
T.sp1()
print(T.sp2())
So I guess the solution in this case would be to call sp1 inside sp2
....
def sp2(self):
self.sp1()
return self.b
You did not define self.b prior to calling it.
(Edited to remove false assumption that you can only define the attributes in __init__)
class text():
def __init__(self, text):
self.txt = text
self.a = self.txt.split(',')[0]
self.b = self.txt.split(',')[1]
def sp1(self):
return self.a
def sp2(self):
return self.b
class text:
def init(self, text):
self.txt = text
def sp1(self):
self.a = self.txt.split(',')[0]
self.b = self.txt.split(',')[1]
return self.a
def sp2(self):
self.sp1()
return self.b
I have a need to allow the user to define a function that processes data in an object (the wisdom and security implications in this have been discussed at length in another question and would just be duplicate comments here.)
I'd like the function to act just like any other method. That is
def my_method(self):...
Would be invoked with:
obj_handle.my_method()
I almost have this achieved below except that the function that results need to be explicitly passed self as an argument, rather than receiving it as the first argument as is typical for a method.
You can see this in property p where I have the odd self.process(self) call.
I imagine that I need to provide something to exec that is like the globals() dictionary, but I'm not certain of several things:
Is this correct?
What is the equivalent of globals() in a class?
Does this solve the problem? If not what do I need to do?
So the question is, how do I get an exec() defined function to act as an object's method?
class test:
def __init__(self, a, b):
self.a=a
self.b=b
#property
def p(self):
return self.process(self)
def set_process(self,program):
func_dict={}
proc_fun = exec(program,func_dict)
setattr(self,'process',func_dict['process'])
def process(self):
return self.a+self.b
t=test(1,2)
prog = '''\
def process(self):
return self.a * self.b
'''
t.set_process(prog)
t.p
Answered in #juanpa.arrivillaga's comment above:
Set the function on the class if you want its descriptor protocol to work and bind tye instance when called on an instance. So one solution just make your set_process a classmethod. – juanpa.arrivillaga 1 hour ago
Working result
class test:
def __init__(self, a, b):
self.a=a
self.b=b
#property
def p(self):
return self.process()
#classmethod
def set_process(cls,program):
func_dict={}
proc_fun = exec(program,func_dict)
setattr(cls,'process',func_dict['process'])
def process(self):
return self.a+self.b
t=test(1,2)
prog = '''\
def process(self):
return self.a * self.b
'''
test.set_process(prog)
t.p
If you want to operate on instances rather than classes:
import types
class Test:
def __init__(self, a, b):
self.a = a
self.b = b
#property
def p(self):
return self.process()
def set_process(self, program):
d = dict()
exec(program, d)
self.process = types.MethodType(d["process"], self)
def process(self):
return self.a + self.b
prog = '''\
def process(self):
return self.a * self.b
'''
t = Test(1, 2)
t.set_process(prog)
print(t.p)
t = Test(1, 2)
print(t.p)
Have written a simple code like this:
class Operations:
#global a,b
a=1
b=2
def __init__(self):
print(self,"object has been created")
def add(self):
#a = 2
#b = 3
return a+b
obj1=Operations()
sum=obj1.add()
print(sum).
when i run this code, am getting this error NameError: name 'a' is not defined.
can you please explain why variables a and b are not accessible in the method 'add' which is defined in the same class?
Note:when am declaring variables as a global, am able to access the variables inside the 'add' method.
You need to use the self keyword.
What does self do?
a = 1
class Operations:
a = 2
def fun1(self):
return a
def fun2(self):
return self.a
obj = Operations()
print(obj.fun1())
print(obj.fun2())
Output:
1
2
Solution for you case:
class Operations:
a=1
b=2
def __init__(self):
print(self,"object has been created")
def add(self):
return self.a + self.b
obj1=Operations()
print(obj1.add())
Output:
<__main__.Operations object at 0x100663588> object has been created
3
Use the class reference
Value= self.a + self.b
Is this the answer that you need? if you're writing a class, use self.value instead global value:
class Operations:
def __init__(self):
self.a = 1
self.b = 2
print(self, "object has been created")
def add(self):
return self.a + self.b
obj1 = Operations()
print(obj1.add())
I want to pass a function to a class when I initialize it. Here's a toy example I came up with and it works:
def addition(self):
return self.a + self.b
def multiplication(self):
return self.a * self.b
class Test:
def __init__(self, a, b, fcn):
self.a = a
self.b = b
self.fcn = fcn
t = Test(3, 3, addition)
print t.fcn(t)
t = Test(3, 3, multiplication)
print t.fcn(t)
Is it possible to simply call t.fcn() as you would any other class method?
did you try it?
the answer is yes
def do_op(x,y,fn):
return fn(x,y)
def add(a,b):
return a+b
print do_op(5,4,add)
same with a class
class whatever:
def __init__(self,fn):
self.fn = fn
def do_it(self,*args,**kwargs):
return self.fn(*args,**kwargs)
#if you wanted the fn to have self as the first argument
#return self.fn(self,*args,**kwargs) #just pass self as first argument
x = whatever(add)
print x.do_it(5,8)
further along what you are asking for (if im reading it right)
def add(self):
return self.a + self.b
class whatever:
def __init__(self,fn,a,b):
self.__dict__[fn.__name__] = fn
self.a,self.b = a,b
def do_it(self):
return self.fn(self)
x = whatever(add,6,7)
x.do_it()
or perhaps you want something like
from functools import partial
def add(self):
return self.a + self.b
class whatever:
def __init__(self,fn,a,b):
self.__dict__[fn.__name__] = partial(fn,self)
self.a,self.b = a,b
x = whatever(add,5,6)
x.add()
this kind of introspection is somewhat risky in deployed code ...