How to implement this mechanism: - python

i want to implement a dynamic relation mechanism with python something like:
a:=10
b:=30
c:=a+b
print c
a+=20
print c
output:
40
60
c is always result of a+b.
so if a or b change, then c automatically updates value. i write a code in C# and do this by set and get mechanism. now want to translate it to python code for using in another program (FontLab Studio 5). I'm not so familiar with Python. does he have a get,set feature like C#? if not ho to implement one?

This is probably overkill, but it illustrates how you should create getters/setters in Python and achieve the functionality you want:
class Calc(object):
def __init__(self, a = 0, b = 0):
self._a = a
self._b = b
#property
def a(self):
return self._a
#a.setter
def a(self, value):
self._a = value
#property
def b(self):
return self._b
#b.setter
def b(self, value):
self._b = value
#property
def c(self):
return self._a + self._b
def __str__(self):
return str(self.c)
calc = Calc()
calc.a = 1
calc.b = 2
print calc.c
calc.a += 10
print calc.c
If you don't want to make a and b a property, the code can be simplified:
class Calc(object):
def __init__(self, a = 0, b = 0):
self.a = a
self.b = b
#property
def c(self):
return self.a + self.b
def __str__(self):
return str(self.c)

In your situation, c actually is a function which must be called.
You could use something like this:
a = 10
b = 30
c = lambda: a + b
print c()
a += 20
print c()
If you dislike that the method call is made explicit for c, you could use a general Calc object, which hides this implementation:
class Calc(object):
def __init__(self):
object.__setattr__(self, '_params', dict())
def __getattr__(self, name):
param = self._params[name]
if callable(param):
return param()
else:
return param
def __setattr__(self, name, value):
self._params[name] = value
def __delattr__(self, name):
del self._params[name]
And then you could do:
c = Calc()
c.a = 10
c.b = 30
c.c = lambda: c.a + c.b
print c.c
c.a += 20
print c.c

New-style Python classes support properties.

something like this:
class C:
def __init__(self):
self.x = 0
self.y = 0
def get(self):
return self.x + self.y
def __str__(self):
return self.__unicode__()
def __unicode__(self):
return str(self.get())
c = C()
c.x = 1
print c
c.y =2
print c
With new style classes and annotations you can probably make it better.

Related

call outer class without using the variable in main file

I had meet the problem that, when calling method in class A, I need to set the value or call some functions in other classes, but I need all of them in the same python file, which is really long and ugly
. Are there some appropriate ways to write it clean?
Ideally, I hope this classes can be in seperate python file.
class A:
def __init__(self):
super(A, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
c.b.set(new_value * 2)
# set C value = new_value / 2
c.value = new_value / 2
class B:
def __init__(self):
super(B, self).__init__()
self.value = 10
def set(self, new_value):
self.value = new_value
class C:
def __init__(self):
super(C, self).__init__()
self.value = 1
self.a = A()
self.b = B()
if __name__ == '__main__':
c = C()
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
There are many solutions to your design constraints, but here is one where dependencies are eliminated:
# imagine each of these classes are in their own projects (/A,/B,/C), in their own files (A.py, B.py, C.py)
class A:
def __init__(self, c):
self.value = 10
self.c = c
def set(self, new_value):
self.value = new_value
# set B value = new_value * 2
self.c.b.set(new_value * 2)
# set C value = new_value / 2
self.c.value = new_value / 2
# class B as before
class C:
def __init__(self, A, B):
self.value = 1
self.a = A()
self.b = B()
# Now main.py
from A.A import A
from B.B import B
from C.C import C
if __name__ == '__main__':
c = C(A, B) # Pass in the classes A and B which C will instantiate
# class a function is called then class B and class C do somethings ...
c.a.set(100)
print(c.value)
print(c.a.value)
print(c.b.value)
btw: A class which does not derive from another does not need to call super init.

How to memoize a property in Python?

Consider the following minimal example:
class Foo(object):
def __init__(self):
self.b = self.a = 1
#property
def sum(self):
print 'Recalculating sum'
return self.a + self.b
foo = Foo()
print foo.sum
print foo.sum # Prints 'Recalculating sum' even though neither a or b has changed since previous call
foo.a = 2
print foo.sum # a has been changed to 2 so recalculation is necessary
I would like to memoize sum such that if self.a and self.b doesn't change, then we don't need to keep recalculating the property.
The property should only be recalculated when either self.a or self.b has changed -- is there an simple way to do this?
python3:
from functools import lru_cache as memoized
#property
#memoized(maxsize=1)
def sum(self):
return self.a + self.b
python 3.8
from functools import cached_property
#cached_property
def sum(self):
return self.a + self.b
Use properties for a and b too and clear up your cache in the setters:
class Foo(object):
def __init__(self):
self.a = 1
self.b = 1
#property
def a(self):
return self._a
#a.setter
def a(self, value):
self._a = value
self._clearsum()
#property
def b(self):
return self._b
#b.setter
def b(self, value):
self._b = value
self._clearsum()
def _clearsum(self):
self._sum = None
#property
def sum(self):
if self._sum is None:
self._sum = self.a + self.b
return self._sum
Or if you want something a bit more generic, you can check this too:
Storing calculated values in an object
Edit : someone recently suggested adding self._sum = None in __init__ to "avoid an error when accessing sum", but that's actually not necessary - __init__ invokes a.setter, which invokes _clearsum, which sets the _sum attribute, so it's garanteed self._sum will be created whatever.
there is a module that does this. Pypi link here: https://pypi.org/project/memoized-property/
For the above code I have this with using the module:
In [2]: from memoized_property import memoized_property
In [3]: class test():
...: def __init__(self):
...: self.a = 0
...: self.b = 0
...: #memoized_property
...: def sum(self):
...: print('calculating...')
...: return self.a + self.b
In [4]: t=test()
calculating...
In [5]: t.sum
Out[5]: 0
In [7]: t.a=5
In [8]: t.sum
Out[8]: 0

Python: how to count the access of an instance variable

I have a python class as below.
class A(object):
def __init__(self, logger):
self.b = B()
self.logger = logger
def meth1(self):
self.b.mymethod1()
def meth2(self):
self.meth1()
self.b.mymethod2()
.........
class B(object):
---------
How can I count how many time I accessed self.b variable on the invocation of meth2() or any method of class A. Is there any way, I can log the usage of self.b variable?
make 'b' a property and and increase the counter corresponding to be in the setter.
#property
def b(self):
self.b_counter += 1
return self._b
and in your class replace b with _b
If you don't want to make a property, you can log the read/write access using __getattribute__ (not __getattr__ since b exists and would not be called) and __setattr__:
class A(object):
def __init__(self):
# initialize counters first !
self.b_read_counter = 0
self.b_write_counter = 0
# initialize b
self.b = 12
def __getattribute__(self,attrib):
# log read usage
if attrib=="b":
self.b_read_counter+=1
# now return b value
return object.__getattribute__(self, attrib)
def __setattr__(self,attrib,value):
if attrib=="b":
self.b_write_counter+=1
return object.__setattr__(self, attrib,value)
a = A()
a.b = 23 # second write access (first is in the init method)
if a.b == 34: # first read access
print("OK")
if a.b == 34:
print("OK")
if a.b == 34: # third read access
print("OK")
print(a.b_read_counter)
print(a.b_write_counter)
result:
3
2
You can use descriptors for this or just make a property which is basically is descriptor.
class A(object):
def __init__(self, logger):
self._b = B()
self._b_counter = 0
self.logger = logger
#property
def b(self):
self._b_counter += 1
return self._b
def meth1(self):
self.b.mymethod1()
def meth2(self):
self.meth1()
self.b.mymethod2()
You can use property, somtehing like:
class A(object):
def __init__(self, logger):
self._b = B()
self._count = 0
self.logger = logger
#property
def b(self):
self._count += 1
return self._b
...
...

Using property decorator to set and get object values in Python [duplicate]

Could anyone find a problem with this #property decorator? I cannot seem to get it to assert correctly. I'm sure I'm doing some really simple thing wrong, but can anyone point my tired eyes in the right direction please?
class A:
def __init__(self):
self.a = 0
self._b = 0
#property
def b(self):
return self.b
#b.getter
def b(self):
if self._b is None:
return 0
return self._b
#b.setter
def b(self, val):
self._b = (val * 20)
def test_getter_setter():
obj = A()
obj.a = 1
#obj.b = 2
print obj.a, obj.b
obj.b = 2
print obj.a, obj.b
assert obj.b == 40
test_getter_setter()
The #property decorator only works on new style classes. Inherit from object:
class A(object):
With that change your test function passes.

How to pass a function as a parameter to a class in python

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 ...

Categories

Resources