Cython overload Special Methods? - overloading

Is there a possibility to overload __cinit__ or __add__ ?
Something like this:
cdef class Vector(Base):
cdef double x, y, z
def __cinit__(self, double all):
self.x = self.y = self.z = all
def __cinit__(self, double x, double y, double z):
self.x = x
self.y = y
self.z = z
def __str__(self):
return "Vector(%s, %s, %s)" % (self.x, self.y, self.z)
def __add__(self, Vector other):
return Vector(
self.x + other.x,
self.y + other.y,
self.z + other.z,
)
def __add__(self, object other):
other = <double>other
return Vector(
self.x + other.x,
self.y + other.y,
self.z + other.z,
)
Calling Vector(0) + Vector(2, 4, 7) tells me that a float is required here, so it seems like __add__(self, Vector other) is not recognized as an overloaded method.
Is this because Special methods should not be defined as cdef and only cdef-fed functions can be overloaded ?

I don't think that operator overloading of special functions is supported in cython.
your best bet is to create manually the type checking logic and cast the python object
accordingly.
def __add__(self, other):
if type(other) is float:
return self.__add__(<double> other)
elif isinstance(other,Vector):
return self.__add__(<Vector> other)
...

Related

Sympy container objects that respond to simplify(...)

I'm trying to create a sympy container object with multiple sympy expressions inside it, representing the x, y and z observables of a qubit.
I started by creating a class that extends sympy.Basic. I was hoping that pushing x, y and z into the sympy args would result in an object that would respond to simplify(qubit) by returning an object with the x, y, and z args simplified. When that didn't work naturally, I redefined the simplify(self, **kwargs) method.
Is there a recommended way to get simplify(qubit) working rather than qubit.simplify()?
from sympy import Symbol, cos, sin, Basic
aa = Symbol('aa')
# simplifies to 1
expression_to_simplify = sin(aa)**2 + cos(aa)**2
class Qubit(Basic):
def __new__(cls, qubitnumber, x, y, z):
obj = super().__new__(cls, qubitnumber, x, y, z)
obj.qubitnumber = qubitnumber
return obj
def simplify(self, **kwargs):
from sympy.simplify import simplify
return Qubit(
self.args[0],
simplify(self.args[1]),
simplify(self.args[2]),
simplify(self.args[3])
)
qb = Qubit(1, expression_to_simplify, expression_to_simplify, expression_to_simplify)
print(qb.simplify())
from sympy.simplify import simplify
print(simplify(qb))
Gives output:
Qubit(1, 1, 1, 1)
Qubit(1, sin(aa)**2 + cos(aa)**2, sin(aa)**2 + cos(aa)**2, sin(aa)**2 + cos(aa)**2)
simplify is not written to provide support for simplifying the contents of containers, but you can make it so (or only do so for Qubit as follows):
>>> from sympy import simplify as _simplify
>>> def simplify(x, *y, **k):
... if isinstance(x, Expr): return _simplify(x, *y, **k)
... elif isinstance(x, Qubit): return Qubit(*[_simplify(i, *y, **k) for i in x.args])
... raise NotImplementedError
This then gives Qubit(1, 1, 1, 1) for simplify(qb). The trick is in using the original simplify as _simplify inside the new simplify.

Bound task in celery is not able to access instance variable in django project

I have setup celery in my django project using official documentation at
http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#using-celery-with-django
So my MyApp/tasks.py have content
from celery import shared_task
class Someclass():
def __init__(self, x, y):
self.x = x
self.y = y
#shared_task(bind=True)
def func1(self):
'''This does not work'''
return self.x + self.y
#shared_task(bind=True)
def func2(self, a, b):
'''This works well'''
return a + b
When I run
In [9]: o = Someclass(3, 4)
In [10]: o.func1.delay()
Out[10]: <AsyncResult: afc6b151-d71c-4f46-a916-6917f98c681f>
I get the error
AttributeError: 'func1' object has no attribute 'x'
When I run
In [11]: o.func2.delay(3, 4)
Out[11]: <AsyncResult: 3b227f00-8d9c-472b-b7d8-8b4b6261f689>
This works perfectly
How can I make func1 working so that it can use instance variables e.g. x and y?
from celery import shared_task
#shared_task(bind=True)
def func(self, a, b):
return a + b
class Someclass():
def __init__(self, x, y):
self.x = x
self.y = y
def func1(self):
return func.delay(self.x, self.y)

Receiving the following error: TypeError: float argument required, not instance

I am implementing a big circle class,which does operations like computes area,compares two circle,compares a circle and square etc,but i am having trouble with this small snippet.
class Circle(Point):
def __init__(self, x=0, y=0, r=0):
self.X = x
self.Y = y
self.R = r
self.area = math.pi*r*r
def __str__(self):
return ("A Circle which has centre at " + "(" + "%0.6f" % (self.X) + ", "
+ "%0.6f" % (self.Y) + ")" + "and its radius " + "%0.6f" % (self.R))
def getX(self):
return self.X
def getY(self):
return self.Y
def getR(self):
return self.R
def setR(self):
pass
def area(self):
return math.pi * self.R * self.R
def main():
x = float(input("Enter x coordinate of first circle's centre: "))
y = float(input("Enter y coordinate of the first circle's centre: "))
r = float(input("Enter first circle's radius: "))
pointx1 = x
pointy1 = y
radius1 = r
first_circle = Circle(x, y, r)
print(first_circle)
print("\nArea of first circle is %0.6f" % (first_circle, first_circle.area())
main()
However i get the following error on executing the below code:
print("\nArea of first circle is %0.6f" % (first_circle, first_circle.area))
TypeError: float argument required, not instance
How do i get rid of this.I have calculated self.area in constructor as because i am using it later(haven't shown the code here) to compare two circle's areas which are being sent as argument.Please help.
Remove the first argument in your string format:
print("\nArea of first circle is %0.6f" % (first_circle.area()))
I'm not sure why you put first_circle as an argument since %0.6f is the only part of the string requiring an argument.
Also you need to either rename self.area or rename the method area() because it causes conflicts if they have the same name.

Python Overloading Operations

I made a Rational class in python and made the __add__, __mull__, etc. operators for that class. Here is my code for the __init__ and __add__ functions:
class Rational(object):
def __init__(self, p, q=None): # p/q
if q is None: q = 1
if q == 0: raise ZeroDivisionError("division by zero!")
self.p = p
self.q = q
self.simplify() # simplify the fraction
def __iadd__(self, other): # +=
self.p = self.p * other.q + self.q * other.p
self.q = self.q * other.q
self.simplify()
return self
def __add__(self, other):
r = Rational(self.p, self.q)
r += other
return r
Now I would want python to understand things like 1 + Rational(1, 3) (one plus a third). How could I implement this? Do I have to add an __radd__ function and add cases to when other is int? Or is there a simpler way?
I believe this might be what you're looking for:
class Rational(object):
def __init__(self, p, q=None): # p/q
if q is None: q = 1
if q == 0: raise ZeroDivisionError("division by zero!")
self.p = p
self.q = q
self.simplify() # simplify the fraction
def __iadd__(self, other): # +=
self.p = self.p * other.q + self.q * other.p
self.q = self.q * other.q
self.simplify()
return self
def __add__(self, other):
if type(other) == int :
r = Rational(self.p + other * self.q , self.q)
else:
r = Rational(self.p, self.q)
r += other
return r
This way you can define what happens when you add your Rational to another type, in this case you're adding an int so it relies on the following identity:
(p/q)+r=(p+qr)/q
I hope this helps!
EDIT: made a dumb mathematical error, fixed now

Best approach to create an saturating integer in python?

What would be the best approach to create a type that is a saturated integer in python ?
i.e.:
v = SaturatedInteger(0, 100)
# That should create an integer that will always be in between 0 and 100,
# and have all default operations
v += 68719
print v #Should print '100'.
I can think of inheriting int type, but where should the saturating logic be implemented then ?
If you need a new (quick and dirty) class for it, I would implement it as follows.
class SaturatedInteger:
def __init__(self, val, lo, hi):
self.real, self.lo, self.hi = val, lo, hi
def __add__(self, other):
return min(self.real + other.real, self.hi)
def __sub__(self, other):
return max(self.real - other.real, self.lo)
...
Add as many of the other operators in the docs as you feel you will need (and their 'r' variants).
By storing the value in the instance name real, you can do your arithmetic with regular integers, floats, etc. too:
a = SaturatedInteger(60, 0, 100)
print(a)
60
print(a+30)
90
print(a+40)
100
print(a+50.)
100
print(a-70.)
0
print(a+a)
100
Though, of course you only add the real part if you're adding a complex number to your SaturatedInteger, so watch out. (For a much more complete and robust version, #jonrsharpe's answer is the way to go).
In general, I would implement using a #property to protect an instance's value attribute, then emulate a numeric type, rather than inheriting from int:
class SaturatedInteger(object):
"""Emulates an integer, but with a built-in minimum and maximum."""
def __init__(self, min_, max_, value=None):
self.min = min_
self.max = max_
self.value = min_ if value is None else value
#property
def value(self):
return self._value
#value.setter
def value(self, new_val):
self._value = min(self.max, max(self.min, new_val))
#staticmethod
def _other_val(other):
"""Get the value from the other object."""
if hasattr(other, 'value'):
return other.value
return other
def __add__(self, other):
new_val = self.value + self._other_val(other)
return SaturatedInteger(self.min, self.max, new_val)
__radd__ = __add__
def __eq__(self, other):
return self.value == self._other_val(other)
if __name__ == '__main__':
v = SaturatedInteger(0, 100)
v += 68719
assert v == 100
assert 123 + v == 100
I've only implemented __add__, __radd__ and __eq__, but you can probably see how the rest could be built out as required. You might want to think about what happens when two SaturatedIntegers are used together - should the result have e.g. min(self.min, other.min) as its own min?
I wrote a sample class that has an add function:
class SatInt:
def __init__(self, low, up):
self.lower = low
self.upper = up
self.value = 0
def add(self, n):
if n+self.value > self.upper:
self.value = self.upper
else:
self.value = self.value + n
x = SatInt(0,100)
x.add(32718)
print(x.value)
100