Conditions on class parameters - python

I am creating a Class qubit which has 2 parameters: a and b. I want to make sure everytime user changes parameters, the condition a^2 +b^2=1 must hold . If the condition does not hold then it is an invalid input.
A related Problem: Is there a way to run some function update() everytime the user changes parameters?
class Qubit(object):
def __init__(self):
self.a = 1
self.b = 0

Sure thing. Use propertys so you get getter/setter behavior:
class Qubit(object):
def __init__(self, a=1, b=0):
self._validate(a, b)
self._a = a
self._b = b
#staticmethod
def _validate(a, b):
if a ** 2 + b ** 2 != 1:
raise ValueError('{}^2 + {}^2 != 1'.format(a, b))
# Getter for `a`
#property
def a(self):
return self._a
# Setter for `a`
#a.setter
def a(self, value):
self._validate(a=value, b=self._b)
self._a = value
# (Repeat for `b`.)

Related

Correct usage of self in Python classes [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 4 months ago.
In the example below, classes AA and BB are instantiated with params a and b and feature the foo method. The only difference between classes AA and BB is that in the AA foo method, the intermediate variable z is prefixed with the class instance reference self while in class BB it is not. What is the correct methodology here? When should self be used within class methods and when should it not be used? I've always been confused by this!
class AA:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
self.z = self.a + self.b
return self.z * self.a
class BB:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
z = self.a + self.b
return z * self.a
Neither one is "correct" per se. It depends what you want to do: If you want to keep the value around, then you could assign it to the instance. If not, then don't.
Although, if you do assign it as a public instance attribute, you'll probably want to set an initial value in __init__(), like None.
the use of the self will appear when you initiate an object from the class, so in order that the object will have an access to the variable you need to use the self
class AA:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
self.z = self.a + self.b
return self.z * self.a
class BB:
def __init__(self, a, b):
self.a = a
self.b = b
def foo(self):
z = self.a + self.b
return z * self.a
A = AA(1, 2)
A.foo()
print(A.z) # will print the value
B = BB(1, 2)
B.foo()
print(B.z) # will not print the value, "z" attribute is not defined

Calling a method in setter in python

I want to implement a class property that is computed from other properties.
class Sum(object):
#property
def a(self):
return self._a
#a.setter
def a(self, val):
self._a = a
self._constructSeries()
#property
def b(self):
return self._b
#b.setter
def b(self, val):
self._b = b
self._constructSeries()
def _constructSeries(self):
# Some calculations involving a and b
self._series = function(a, b)
def __init__(self, a, b):
self.a = a
self.b = b
One way I know of is to define series as a property
#property
def series(self):
return fun(a,b)
But I want to avoid calling fun each and every time as it takes a lot of computations. What is the standard way to handle such a case?
If I got it right you want to be able to change a and b without computing the fun everytime but when you request the result of the fun is the most updated one, is it correct?
In such a case you can use property
def get_series(self):
if self._series is None or self.updated is False:
self._series = fun(self.a,self.b)
self.updated = True
return self._series
series = property(get_series)
And when you set a and b you update the flag
#property
def a(self):
self.updated = False
return self._a
#property
def b(self):
self.updated = False
return self._b
Then self.series returns the updated values but it runs fun just if the input changes from the last time it has been computed.

Dependent properties that are CPU intensive

I am very often confronted to this case and did not manage to discover a stable way to deal with it.
Suppose I have a class defined like that:
class MyClass(object):
def __init__(self, a, b):
self.a = a
self.b = b
#property
def c(self):
"""This method performs some heavy computations based on a and b properties"""
# Some heavy computations only with a and b attributes
return c
Property c may be now be retrieved by:
>>> obj = MyClass(a, b)
>>> print obj.c
However, every time I ask for obj.c, the heavy computations will be performed, resulting in a poor performance code as c results from heavy computations and it would preferably be calculated only while a or b is set or modified.
What would the better way to deal with this case ? I am thinking of creating a c_update method to use as a decorator for some #a.setter and #b.setter decorated methods but is that the better way ?
Regards,
But what if I have a lot of XX dependent properties that rely on a and b values. Do I have to write an update_XX method for each of them and add this method to init and to each a.setter and b.setter ? That seems to me quite verbose...
You can have the c value (and any other number of dependent properties) updated everytime either a or b is mutated, I implemented an update_properties() method below:
class MyClass(object):
def __init__(self, a, b):
self._a = a
self._b = b
self.update_properties()
#property
def a(self):
return self.a
#a.setter
def a(self, value):
self._a = value
self.update_properties()
#property
def b(self):
return self._b
#b.setter
def b(self, value):
self._b = value
self.update_properties()
def update_properties(self):
self.c = self._a + self._b
self.d = self._a * self._b
self.e = self._a - self._b
# self.f = ...
# ...
# self.z = ...
# Can go on as long as you want
Do you think it would be possible to implement this machinery as some decorators in order to lighten the code
The verbosity seems to be only on the side that tracks the free variables (e.g. here a and b), so if I had to support an arbitrary number of those, I would implement a MyClass.set_value(name, value)
def set_value(self, name, value):
setattr(self, name, value)
self.update_properties()
So the idea here is that our set_value() can work with an arbitrary number of attributes. And it's possible to call it from __init__ if you use **kwargs to unpack the key-values passed to the constructor.
One requirement here, since we haven't set the free variables as #property we're required to use obj.set_value('a', 42) instead of obj.a = 42
There is a small pypi package that fits well: cached-property
from cached_property import cached_property
class MyClass(object):
def __init__(self):
pass
#cached_property
def c(self):
# Heavy computation based on self.a / self.b
return ...
#property
def a(self):
return self._a
#a.setter
def a(self, value):
self._a = value
del self.c
#property
def b(self):
return self._b
#b.setter
def b(self, value):
self._b = value
del self.c
Of course you could also build an abstraction for the a/b properties on top of that, that utilizes del self.c.
One benefit of using cached_property is that you can easily make the cache thread-safe by changing it to threaded_cached_property.
I'd simply store the actual value of c in a private attribute and check if this is not None. Set this to None when either a or b changes.
So the "proper" way of doing this using properties would be:
class MyClass(object):
def __init__(self, a, b):
self._a = a
self._b = b
self._c = None
#property
def a(self):
return self._a
#a.setter
def a(self, value):
self._a = value
self._c = None
#property
def b(self):
return self._b
#b.setter
def a(self, value):
self._b = value
self._c = None
#property
def c(self):
if self._c is None:
self._c = # compute c here
return self._c
If you want to avoid creating all these properties and setters you probably want to hijack the __getattr__ and __setattr__ methods instead:
class MyClass(object):
def __init__(self, a, b):
self.a = a
self.b = b
self._c = None
def __getattr__(self, name):
if name == 'c':
if self._c is None:
self._c = # compute c here
return self._c
raise AttributeError(name)
def __setattr__(self, name, value):
if name == 'c':
raise TypeError('You cannot modify property c directly')
super(MyClass, self).__setattr__(name, value)
if name in ('a', 'b'):
super(MyClass, self).__setattr__('_c', None)
Note that this last solution could be extended to like 10 attributes a1, ..., a10 without having to define 10 properties and setters.
It's probably a bit less robust.
So based on your answers, I managed to build a new answer using a dict for dependent properties.
class MyClass(object):
def __init__(self, a, b):
self._properties = dict()
self._a = a
self._b = b
def _update_dependent_properties(self):
# Do computations for c1, c2...
self._properties['c1'] = # c1 value
self._properties['c2'] = # c2 value
# ...
#property
def a(self):
return self._a
#property
def b(self):
return self._b
#a.setter
def a(self, value):
self._properties.clean()
self._a = value
#b.setter
def b(self, value):
self._properties.clean()
self._b = value
#property
def c1(self):
try:
return self._properties['c1']
except KeyError:
_update_dependent_properties()
return self._properties['c1']
#property
def c2(self):
try:
return self._properties['c2']
except KeyError:
_update_dependent_properties()
return self._properties['c2']
This seem to do the trick but it is still quite verbose... and I have still to write a property for each of the dependent property I am expecting. However, it does force the calculation of update_dependent_properties() when either attribute a or b is modidied.
I wonder if it does not exist a module to do it. It seem that my problem sounds like memoize technique... and may a decorator lighten the code by systematizing the procedure ?

pythonic class instance attribute calculated from other attributes

I have a class instance with attributes that are calculated from other attributes. The attributes will change throughout the life of the instance. All attributes are not necessarily defined when the object is initialized.
what is the pythonic way to calculate attributes from other attributes?
This is a simple example, the calculations have numerous input variables ("a" below) and calculations ("b" & "c").
a = something
b = function of a (a+5)
c = function of a and b (a*b)
I've tried numerous implementations. Here is a decent one to communicate my intention.
class CalcAttr(object):
def __init__(self):
self._a = None
self._b = None
self._c = None
#property
def a(self):
return self._a
#a.setter
def a(self,value):
self._a = value
#property
def b(self):
self.calc_b()
return self._b
#property
def c(self):
self.calc_c()
return self._c
def calc_b(self):
self._b = self._a + 5
def calc_c(self):
self._c = self._a * self._b
def test():
abc = CalcAttr()
a = 5
return abc.c
Note: t.c works if I first call t.b first.
> >>> t=abc.test()
> >>> t.c Traceback (most recent call last): File "<stdin>", line 1, in <module> File "abc.py", line 22, in c
> self.calc_c() File "abc.py", line 29, in calc_c
> self._c = int(self._a) * int(self._b) TypeError: int() argument must be a string or a number, not 'NoneType'
> >>> t.b 10
> >>> t.c 50
> >>>
Keep in mind most of the real calculations are dependent on multiple attribures (5-10 input variables & as many calculated ones).
My next iteration will include a "calculate_model" function that will populate all calculated attributes after checking that all inputs are defined. Maybe that will be the pyhonic answer?
Thanks!
Update - working solution
I created a method that calculates each attribute in order:
def calc_model(self):
self.calc_b()
self.calc_c()
Each calculated attribute calls that method
#property
def c(self):
self.calc_model()
return self._c
I'm not sure if this is proper, but it works as desired...
If I understand your question correctly, you should compute b and c in their getters. You should also probably require that the user passes a value for a in the initializer, since b and c can't be computed without a. Also, it doesn't seem like there is much of a reason to keep _a, _b, and _c around -- unless b and c are expensive to compute and you'd like to cache them.
For example:
class CalcAttr(object):
def __init__(self, a):
self.a = a
#property
def b(self):
return self.a + 5
#property
def c(self):
return self.a * self.b
Such that
>>> x = CalcAttr(42)
>>> x.c
1974
I understand what #jme suggested in the accepted answer is more elegant, but I still try to fix the original example and get it to work. Here is the code.
class CalcAttr(object):
def __init__(self):
self._a = None
self._b = None
self._c = None
#property
def a(self):
return self._a
#a.setter
def a(self,value):
self._a = value
#property
def b(self):
self.calc_b()
return self._b
#property
def c(self):
self.calc_c()
return self._c
def calc_b(self):
self._b = self._a + 5
def calc_c(self):
self._c = self.a * self.b
def test():
abc = CalcAttr()
abc.a = 5
return abc.c
test()
The code will work and 50 is the resulted value.

"Private" arguments to __init__()?

I have a class that takes a single parameter a on instantiation, which is stored in the _a attribute. For a number of methods (operators), I need to set also a _b attribute on the result. This is currently implemented in a straight-forward way:
class SomeClass(object):
def __init__(self, a=0):
self._a = a
self._b = 0
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
Now, I have an number of members like _b, such as _c and _d, so __add__ will need an extra line for each of these attributes. Being able to pass these on object instantiation would result in cleaner code:
class SomeClass(object):
def __init__(self, a=0, _b=0):
self._a = a
self._b = 0
def __add__(self, other):
return self.__class__(_b=self._a + other._a)
However, I don't want the user to pass values for all of the parameters, except for a as _b, _c and _d are implementation specifics. I could simply state in the docstring not to pass more than one argument. Preceding the 'private' attributes with an underscore is intended to reflect this.
Alternatively, I can try to make it harder for the user to misbehave, by providing a second, private constructor:
class SomeClass(object):
def __init__(self, a=0):
self._a = a
self._init()
def _init(self, _b=0):
self._b = _b
#classmethod
def _constructor(cls, a, _b):
obj = cls(a)
obj._init(b)
return obj
def __add__(self, other):
return self.__class__._constructor(_b=self._a + other._a)
I'm thinking this is a rather clunky solution.
What would be the preferred way to solve this problem? Are there other, more elegant, solutions? Is this really a problem; should I just use the first option and end up with some more lines of code?
The _ underscore convention is clear and prevalent through the python world.
You document your 'public' attributes, and just use default arguments with underscores to your __init__ method. Keep it simple.
If someone wants to screw up a class by using those private parameters anyway, you are not going to stop them, not in Python.
To tidy it up a tiny bit, you could set _b before __init__:
class SomeClass(object):
_b = 0
def __init__(self, a=0):
self._a = a
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
Or if there are heaps of private variables, put them into a list and do some magic?
class SomeClass(object):
calculated_vars = ['_b'] # All your calculated variables
def __init__(self, a=0):
self._a = a
def __getattr__(self, k):
if k in self.calculated_vars:
return 0 # Default value for calculated variables
else:
raise AttributeError('{} not found'.format(k))
def __add__(self, other):
result = self.__class__()
result._b = self._a + other._a
return result
if __name__ == '__main__':
i = SomeClass(1)
print '_a attr: ', i._a # 1
print '_b attr: ', i._b # 0 (Default value)
print '_c attr: ', i._c # AttributeError: _c not found
i2 = SomeClass(3)
i3 = i + i2
print '_b attr: ', i3._b # 4 (Calculated value)

Categories