Using '__mul__' within a class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Gerard Flanagan

    #1

    Using '__mul__' within a class

    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

    #2
    Re: Using '__mul__' within a class

    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)

    iD8DBQFDNXm7Jd0 1MZaTXX0RAguqAJ 9u9Txaz8AOJaBn4 t3v1e+ExsQ0DACg iv2l
    urtGBbqtiSXWM4S KoBcP77E=
    =mTpx
    -----END PGP SIGNATURE-----

    Comment

    • Ivan Voras

      #3
      Re: Using '__mul__' within a class

      Gerard Flanagan wrote:
      [color=blue]
      > def Square( self ):
      > self *= self[/color]

      You probably mean
      return self * self
      [color=blue]
      > A = FibonacciMatrix ()
      > A.Square()[/color]

      Make this
      A = A.Square()

      Comment

      • Terry Reedy

        #4
        Re: Using '__mul__' within a class


        "Gerard Flanagan" <grflanagan@yah oo.co.uk> wrote in message
        news:1127576164 .489710.291280@ g49g2000cwa.goo glegroups.com.. .[color=blue]
        > def __mul__( self, other ):
        > def Square( self ):
        > self *= self[/color]

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

        tjr



        Comment

        • James Stroud

          #5
          Re: Using '__mul__' within a class

          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:[color=blue]
          > 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'
          >
          > ------------------------------[/color]

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


          Comment

          • James Stroud

            #6
            Re: Using '__mul__' within a class

            Additionally, your __mul__() returns a new FibonnacciMatri x. You do not want a
            new FibbonacciMatri x, 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(o ther)


            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(o ther)
            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:[color=blue]
            > 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'
            >
            > ------------------------------[/color]

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


            Comment

            • Martin Miller

              #7
              Re: Using '__mul__' within a class

              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:[color=blue]
              > 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'
              >
              > ------------------------------[/color]

              Comment

              • James Stroud

                #8
                Re: Using '__mul__' within a class

                Shoot, Square() should be:

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

                Forgot to proofread before hitting send.

                James

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


                Comment

                • James Stroud

                  #9
                  Re: Using '__mul__' within a class

                  On Saturday 24 September 2005 09:07, jepler@unpython ic.net wrote:[color=blue]
                  > For the same reason that
                  > def f(z):
                  > z *= z
                  > c = 1
                  > f(c)
                  > print c
                  > prints 1.
                  >
                  > Jeff[/color]

                  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


                  Comment

                  • jepler@unpythonic.net

                    #10
                    Re: Using '__mul__' within a class

                    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)

                    iD8DBQFDNbrxJd0 1MZaTXX0RAmD0AJ 9/kqPDQPv9TsnIYjG WJ6+huc7kkACgit 9R
                    Ux0e1O+8FeSx6oe EgBhyDiM=
                    =qFsK
                    -----END PGP SIGNATURE-----

                    Comment

                    • Piet van Oostrum

                      #11
                      Re: Using '__mul__' within a class

                      >>>>> James Stroud <jstroud@mbi.uc la.edu> (JS) wrote:
                      [color=blue]
                      >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[/color]

                      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 <piet@cs.uu.n l>
                      URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C 4]
                      Private email: piet@vanoostrum .org

                      Comment

                      • Gerard Flanagan

                        #12
                        Re: Using '__mul__' within a class

                        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.or g/wiki/Fibonacci_numbe r_program#Matri x_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

                        Comment

                        • John J. Lee

                          #13
                          Re: Using '__mul__' within a class

                          "Gerard Flanagan" <grflanagan@yah oo.co.uk> writes:
                          [...][color=blue]
                          > class FibonacciMatrix :[/color]
                          [...][color=blue]
                          > def Copy( self ):[/color]
                          [...]

                          __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

                          Comment

                          Working...