Velocity Reviews > Using '__mul__' within a class

# Using '__mul__' within a class

Gerard Flanagan
Guest
Posts: n/a

 09-24-2005
Hello

I'm pretty new to Python and was wondering why the 'Square' method in
the following code doesn't work. It doesn't fail, just doesn't do
anything ( at least, not what I'd like! ). Why doesn't 'A.a' equal 2
after squaring?
TIA.

class FibonacciMatrix:
def __init__( self ):
self.a = 1
self.b = 1
self.c = 0

def __mul__( self, other ):
result = FibonacciMatrix()
result.a = self.a * other.a + self.b * other.b
result.b = self.a * other.b + self.b * other.c
result.c = self.b * other.b + self.c * other.c
return result

def Square( self ):
self *= self

A = FibonacciMatrix()
A.Square()

print A.a #prints '1'

A = FibonacciMatrix()
B = A * A

print B.a #prints '2'

------------------------------

jepler@unpythonic.net
Guest
Posts: n/a

 09-24-2005
For the same reason that
def f(z):
z *= z
c = 1
f(c)
print c
prints 1.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDNXm7Jd01MZaTXX0RAguqAJ9u9Txaz8AOJaBn4t3v1e +ExsQ0DACgiv2l
urtGBbqtiSXWM4SKoBcP77E=
=mTpx
-----END PGP SIGNATURE-----

Ivan Voras
Guest
Posts: n/a

 09-24-2005
Gerard Flanagan wrote:

> def Square( self ):
> self *= self

You probably mean
return self * self

> A = FibonacciMatrix()
> A.Square()

Make this
A = A.Square()

Terry Reedy
Guest
Posts: n/a

 09-24-2005

"Gerard Flanagan" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> def __mul__( self, other ):
> def Square( self ):
> self *= self

Among the other reasons cited, I believe that 'op=' maps to a different
special method than 'op'. __imul__? or something? do check.

tjr

James Stroud
Guest
Posts: n/a

 09-24-2005
I think the gist of your problem is that you are re-binding self in the
method. Here is a simpler example of your problem:

py> def doit(c):
.... c = 5
.... print "c in the method is", c
....
py> c = 42
py> print "c before calling the method is", c
c before calling the method is 42
py> doit(c)
c in the method is 5
py> print "c after calling the method is", c
c after calling the method is 42

James

On Saturday 24 September 2005 08:36, Gerard Flanagan wrote:
> Hello
>
> I'm pretty new to Python and was wondering why the 'Square' method in
> the following code doesn't work. It doesn't fail, just doesn't do
> anything ( at least, not what I'd like! ). Why doesn't 'A.a' equal 2
> after squaring?
> TIA.
>
>
> class FibonacciMatrix:
> def __init__( self ):
> self.a = 1
> self.b = 1
> self.c = 0
>
> def __mul__( self, other ):
> result = FibonacciMatrix()
> result.a = self.a * other.a + self.b * other.b
> result.b = self.a * other.b + self.b * other.c
> result.c = self.b * other.b + self.c * other.c
> return result
>
> def Square( self ):
> self *= self
>
>
> A = FibonacciMatrix()
> A.Square()
>
> print A.a #prints '1'
>
> A = FibonacciMatrix()
> B = A * A
>
> print B.a #prints '2'
>
> ------------------------------

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/

James Stroud
Guest
Posts: n/a

 09-24-2005
Additionally, your __mul__() returns a new FibonnacciMatrix. You do not want a
new FibbonacciMatrix, you want to operate on an existing matrix (otherwise,
you would want to go with Ivan Voras's solution, where you re-assign outside
of the class). If you don't want the overhead of creating a instance of your
class, you may want to be more explicit in Square(), eg:

def Multiply(self, other):
self.a = self.a * other.a + self.b * other.b
self.b = self.a * other.b + self.b * other.c
self.c = self.b * other.b + self.c * other.c

def Square(self, other):
self.Multiply(other)

With __imul__(), as Terry Reedy suggested, you can also save the overhead of
creating a new instance, but it works a little differently than Square()
above, because you need to return self (assuming Square() is as above):

def __imul__(self, other):
self.Multiply(other)
return self

With these methods, __mul__() can be factored:

def __mul__(self, other):
result = FibonacciMatrix()
result.Multiply(other)
return result

Leaving all of the messiest stuff in the Multiply method.

James

On Saturday 24 September 2005 08:36, Gerard Flanagan wrote:
> Hello
>
> I'm pretty new to Python and was wondering why the 'Square' method in
> the following code doesn't work. It doesn't fail, just doesn't do
> anything ( at least, not what I'd like! ). Why doesn't 'A.a' equal 2
> after squaring?
> TIA.
>
>
> class FibonacciMatrix:
> def __init__( self ):
> self.a = 1
> self.b = 1
> self.c = 0
>
> def __mul__( self, other ):
> result = FibonacciMatrix()
> result.a = self.a * other.a + self.b * other.b
> result.b = self.a * other.b + self.b * other.c
> result.c = self.b * other.b + self.c * other.c
> return result
>
> def Square( self ):
> self *= self
>
>
> A = FibonacciMatrix()
> A.Square()
>
> print A.a #prints '1'
>
> A = FibonacciMatrix()
> B = A * A
>
> print B.a #prints '2'
>
> ------------------------------

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/

Martin Miller
Guest
Posts: n/a

 09-24-2005
As others have pointed out, you are just reassigning a new value to the
self argument in the Square() method shown. Instead, what you need to
do is change the object that 'self' refers to within the method. To do
this, change it to:

def Square( self ):
result = self * self
self.a = result.a
self.b = result.b
self.c = result.c

You would also have to do something similar in an __imul__() method if
you decided to implement one.

Hope this helps,
-Martin
====

Gerard Flanagan wrote:
> Hello
>
> I'm pretty new to Python and was wondering why the 'Square' method in
> the following code doesn't work. It doesn't fail, just doesn't do
> anything ( at least, not what I'd like! ). Why doesn't 'A.a' equal 2
> after squaring?
> TIA.
>
>
> class FibonacciMatrix:
> def __init__( self ):
> self.a = 1
> self.b = 1
> self.c = 0
>
> def __mul__( self, other ):
> result = FibonacciMatrix()
> result.a = self.a * other.a + self.b * other.b
> result.b = self.a * other.b + self.b * other.c
> result.c = self.b * other.b + self.c * other.c
> return result
>
> def Square( self ):
> self *= self
>
>
> A = FibonacciMatrix()
> A.Square()
>
> print A.a #prints '1'
>
> A = FibonacciMatrix()
> B = A * A
>
> print B.a #prints '2'
>
> ------------------------------

James Stroud
Guest
Posts: n/a

 09-24-2005
Shoot, Square() should be:

def Square(self):
self.Multiply(self)

Forgot to proofread before hitting send.

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/

James Stroud
Guest
Posts: n/a

 09-24-2005
On Saturday 24 September 2005 09:07, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> For the same reason that
> def f(z):
> z *= z
> c = 1
> f(c)
> print c
> prints 1.
>
> Jeff

I don't mean to be rude, but this is a horrible example if your are intending
to help a neophyte:

py> 1*1
1

See what I mean?

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/

jepler@unpythonic.net
Guest
Posts: n/a

 09-24-2005
Oops!

I should have used '2' in the example, or some other number.

I was trying to make a point about what
x *= ...
means when it is in the context of a function (or method) body.
I think this is key to understanding what Python did in the case the user posted.

Being rude wasn't my intent at all.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDNbrxJd01MZaTXX0RAmD0AJ9/kqPDQPv9TsnIYjGWJ6+huc7kkACgit9R
Ux0e1O+8FeSx6oeEgBhyDiM=
=qFsK
-----END PGP SIGNATURE-----