Using '__mul__' within a class

Discussion in 'Python' started by Gerard Flanagan, Sep 24, 2005.

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

    ------------------------------
    Gerard Flanagan, Sep 24, 2005
    #1
    1. Advertising

  2. Gerard Flanagan

    Guest

    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-----
    , Sep 24, 2005
    #2
    1. Advertising

  3. Gerard Flanagan

    Ivan Voras Guest

    Gerard Flanagan wrote:

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


    You probably mean
    return self * self

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


    Make this
    A = A.Square()
    Ivan Voras, Sep 24, 2005
    #3
  4. Gerard Flanagan

    Terry Reedy Guest

    "Gerard Flanagan" <> wrote in message
    news:...
    > 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
    Terry Reedy, Sep 24, 2005
    #4
  5. Gerard Flanagan

    James Stroud Guest

    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, Sep 24, 2005
    #5
  6. Gerard Flanagan

    James Stroud Guest

    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/
    James Stroud, Sep 24, 2005
    #6
  7. 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'
    >
    > ------------------------------
    Martin Miller, Sep 24, 2005
    #7
  8. Gerard Flanagan

    James Stroud Guest

    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, Sep 24, 2005
    #8
  9. Gerard Flanagan

    James Stroud Guest

    On Saturday 24 September 2005 09:07, 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/
    James Stroud, Sep 24, 2005
    #9
  10. Gerard Flanagan

    Guest

    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-----
    , Sep 24, 2005
    #10
  11. >>>>> James Stroud <> (JS) wrote:

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


    I gues this will give the wrong result because the calculation of self.b is
    supposed to use the original value of self.a, not the newly calculated one.
    Similar for self.c. The following should do that:

    self.a, self.b, self.c = (self.a * other.a + self.b * other.b,
    self.a * other.b + self.b * other.c,
    self.b * other.b + self.c * other.c)
    --
    Piet van Oostrum <>
    URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C4]
    Private email:
    Piet van Oostrum, Sep 24, 2005
    #11
  12. Thanks for all the replies - you are very nice people!

    Don't worry Jeff, I assumed you weren't telling me what 1*1 equals! I
    got your point.

    James Stroud impressively got to the heart of what I was trying to do -
    which was just to wrap up the code here:

    en.wikipedia.org/wiki/Fibonacci_number_program#Matrix_equation

    in object-oriented fashion but without too much overhead - I appreciate
    you taking the time James! Thanks.

    I managed to do what i wanted with the code below, though there's
    definitely a lack of understanding on my part with respect to how
    Python works - binding/re-binding? - that I'll have to study.

    Cheers 'n' all

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

    def Copy( self ):
    copy = FibonacciMatrix()
    copy.a = self.a
    copy.b = self.b
    copy.c = self.c
    return copy

    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 __pow__( self, N ):
    if N == 1:
    return self
    if N & 1 == 0:
    return pow( self * self, N/2 )
    else:
    return self * pow( self * self, (N-1)/2 )


    A = FibonacciMatrix() ** 8

    print '------------------------------'
    print A.a
    Gerard Flanagan, Sep 24, 2005
    #12
  13. Gerard Flanagan

    John J. Lee Guest

    "Gerard Flanagan" <> writes:
    [...]
    > class FibonacciMatrix:

    [...]
    > def Copy( self ):

    [...]

    __copy__ would be a more standard name. Then:

    import copy
    fm = FibonacciMatrix()
    fm2 = copy.copy(fm)


    I suppose you could also add:

    __deepcopy__ = __copy__


    in the body of the class definition.


    John
    John J. Lee, Sep 25, 2005
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,716
    Thomas Weidenfeller
    Oct 12, 2005
  2. jd
    Replies:
    3
    Views:
    340
  3. Thomas Philips

    Using __mul__

    Thomas Philips, Jul 3, 2004, in forum: Python
    Replies:
    2
    Views:
    371
    Peter Otten
    Jul 3, 2004
  4. Muhammad Alkarouri

    Is __mul__ sufficient for operator '*'?

    Muhammad Alkarouri, Oct 20, 2009, in forum: Python
    Replies:
    7
    Views:
    412
    Mick Krippendorf
    Oct 26, 2009
  5. dmitrey
    Replies:
    1
    Views:
    919
    Terry Reedy
    Dec 11, 2009
Loading...

Share This Page