OO in Python? ^^

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matthias Kaeppler

    #1

    OO in Python? ^^

    Hi,

    sorry for my ignorance, but after reading the Python tutorial on
    python.org, I'm sort of, well surprised about the lack of OOP
    capabilities in python. Honestly, I don't even see the point at all of
    how OO actually works in Python.

    For one, is there any good reason why I should ever inherit from a
    class? ^^ There is no functionality to check if a subclass correctly
    implements an inherited interface and polymorphism seems to be missing
    in Python as well. I kind of can't imagine in which circumstances
    inheritance in Python helps. For example:

    class Base:
    def foo(self): # I'd like to say that children must implement foo
    pass

    class Child(Base):
    pass # works

    Does inheritance in Python boil down to a mere code sharing?

    And how do I formulate polymorphism in Python? Example:

    class D1(Base):
    def foo(self):
    print "D1"

    class D2(Base):
    def foo(self):
    print "D2"

    obj = Base() # I want a base class reference which is polymorphic
    if (<need D1>):
    obj = D1()
    else:
    obj = D2()

    I could as well leave the whole inheritance stuff out and the program
    would still work (?).

    Please give me hope that Python is still worth learning :-/

    Regards,
    Matthias
  • Heiko Wundram

    #2
    Re: OO in Python? ^^

    Matthias Kaeppler wrote:[color=blue]
    > <snip a whole lot of talk of someone still thinking in terms of C>[/color]

    Let this enlighten your way, young padawan:

    modelnine@phoen ix ~/gtk-gnutella-downloads $ python
    Python 2.4.2 (#1, Oct 31 2005, 17:45:13)
    [GCC 3.4.4 (Gentoo 3.4.4-r1, ssp-3.4.4-1.0, pie-8.7.8)] on linux2
    Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
    >>> import this[/color][/color][/color]
    The Zen of Python, by Tim Peters

    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one --obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea -- let's do more of those![color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]

    And, _do_ (don't only read) the tutorial, and you'll understand why the
    short example code you posted isn't pythonic, to say the least:
    The official home of the Python Programming Language

    and why inheritance in Python is necessary, but on a whole different level
    of what you're thinking.

    Oh, and on a last note, if you're german, you might as well join
    de.comp.lang.py thon.

    --- Heiko.

    Comment

    • Fredrik Lundh

      #3
      Re: OO in Python? ^^

      Matthias Kaeppler wrote:
      [color=blue]
      > polymorphism seems to be missing in Python[/color]

      QOTW!

      </F>



      Comment

      • Brian Beck

        #4
        Re: OO in Python? ^^

        Matthias Kaeppler wrote:[color=blue]
        > class Base:
        > def foo(self): # I'd like to say that children must implement foo
        > pass[/color]

        def foo(self):
        raise NotImplementedE rror("Subclasse s must implement foo")

        Now calling foo on a child instance will fail if it hasn't implemented foo.
        [color=blue]
        > And how do I formulate polymorphism in Python? Example:
        >
        > class D1(Base):
        > def foo(self):
        > print "D1"
        >
        > class D2(Base):
        > def foo(self):
        > print "D2"
        > obj = Base() # I want a base class reference which is polymorphic
        > if (<need D1>):
        > obj = D1()
        > else:
        > obj = D2()[/color]

        I have no idea what you're trying to do here and how it relates to
        polymorphism.

        --
        Brian Beck
        Adventurer of the First Order

        Comment

        • Heiko Wundram

          #5
          Re: OO in Python? ^^

          Fredrik Lundh wrote:[color=blue]
          > Matthias Kaeppler wrote:[color=green]
          >> polymorphism seems to be missing in Python[/color]
          >
          > QOTW![/color]

          Let's have some UQOTW: the un-quote of the week! ;-)

          --- Heiko.

          Comment

          • Heiko Wundram

            #6
            Re: OO in Python? ^^

            Brian Beck wrote:[color=blue][color=green]
            >>
            >> class D1(Base):
            >> def foo(self):
            >> print "D1"
            >>
            >> class D2(Base):
            >> def foo(self):
            >> print "D2"
            >> obj = Base() # I want a base class reference which is polymorphic
            >> if (<need D1>):
            >> obj = D1()
            >> else:
            >> obj = D2()[/color]
            >
            > I have no idea what you're trying to do here and how it relates to
            > polymorphism.
            >[/color]

            He's translating C++ code directly to Python. obj = Base() creates a
            variable of type Base(), to which you can assign different object types (D
            (), D2()) which implement the Base interface (are derived from Base).
            Err... At least I think it's what this code is supposed to mean...

            In C++ you'd do:

            Base *baseob;

            if( <i want d1> ) {
            baseob = (Base*)new D1();
            } else {
            baseob = (Base*)new D2();
            }

            baseob->foo();

            (should, if foo is declared virtual in Base, produce "d1" for D1, and "d2"
            for D2)

            At least IIRC, it's been quite some time since I programmed C++... ;-)
            *shudder*

            --- Heiko.

            Comment

            • Tony Nelson

              #7
              Re: OO in Python? ^^

              In article <dnfmcm$aqp$02$ 1@news.t-online.com>,
              Matthias Kaeppler <void@void.co m> wrote:
              ...[color=blue]
              > obj = Base() # I want a base class reference which is polymorphic[/color]

              obj now refers to an instance of Base.
              [color=blue]
              > if (<need D1>):
              > obj = D1()[/color]

              obj now refers to an instance of D1(). The Base instance is
              unreferenced.
              [color=blue]
              > else:
              > obj = D2()[/color]

              obj now refers to an instance of D2(). The Base instance is
              unreferenced.

              Note that there is no code path that results in obj still referring to
              an instance of Base. Unless making a Base had side effects, there is no
              use in the first line.

              [color=blue]
              > I could as well leave the whole inheritance stuff out and the program
              > would still work (?).[/color]

              That program might.

              [color=blue]
              > Please give me hope that Python is still worth learning :-/[/color]

              Python has inheritance and polymorphism, implemented via dictionaries.
              Python's various types of namespace are implemented with dictionaries.

              Type this in to the Python interpreter:

              class Base:
              def foo(self):
              print 'in Base.foo'

              class D1(Base):
              def foo(self):
              print 'in D1.foo'
              Base.foo(self)

              class D2(Base):
              def foo(self):
              print 'in D2.foo'
              Base.foo(self)

              def makeObj():
              return needD1 and D1() or D2()

              needD1 = True
              makeObj().foo()

              needD1 = False
              makeObj().foo()
              _______________ _______________ _______________ _______________ ____________
              TonyN.:' *firstname*nlsn ews@georgea*las tname*.com
              ' <http://www.georgeanels on.com/>

              Comment

              • Martin Christensen

                #8
                Re: OO in Python? ^^

                -----BEGIN PGP SIGNED MESSAGE-----
                Hash: SHA1
                [color=blue][color=green][color=darkred]
                >>>>> "Matthias" == Matthias Kaeppler <void@void.co m> writes:[/color][/color][/color]
                Matthias> sorry for my ignorance, but after reading the Python
                Matthias> tutorial on python.org, I'm sort of, well surprised about
                Matthias> the lack of OOP capabilities in python. Honestly, I don't
                Matthias> even see the point at all of how OO actually works in
                Matthias> Python.

                It's very common for Python newbies, especially those with backgrounds
                in languages such as C++, Java etc. to not really 'get' the Python way
                of handling types until they've had a fair amount of experience with
                Python. If you want to program Pythonically, you must first unlearn a
                number of things.

                For instance, in e.g. the Java tradition, if a function needs a
                triangle object, it'll take a triangle object as an argument. If it
                can handle any type of shape, it'll either take a shape base class
                instance as an argument or there'll be some kind of shape interface that
                it can take. Argument types are strictly controlled. Not so with
                Python. A Python solution will typically take any type of object as an
                argument so long as it behaves as expected, and if it doesn't, we deal
                with the resulting exception (or don't, depending on what we're trying
                to accomplish). For instance, if the function from before that wants a
                shape really only needs to call an area method, anything with an area
                method can be used successfully as an argument.

                Some have dubbed this kind of type check 'duck typing': if it walks
                like a duck and quacks like a duck, chances are it'll be a duck. To
                those who are used to (more or less) strong, static type checks, this
                will seem a reckless approach, but it really works rather well, and
                subtle type errors are, in my experience, as rare in Python as in any
                other language. In my opinion, the tricks the C*/Java people
                occasionally do to get around the type system, such as casting to the
                fundamental object type, are worse because they're seldom expected and
                resulting errors thus typically more subtle.

                In my very first post on this news group a number of years ago, I
                asked for an equivalent of Java's interfaces. The only reply I got was
                that I didn't need them. While the reason was very obvious, even with
                what I knew about Python, it still took a while to sink in. From what
                I can tell, you're in somewhat the same situation, and the two of us
                are far from unique. As I said in the beginning, Python newbies with a
                background in statically typed languages typically have a lot to
                unlearn, but in my opinion, it's well worth it.


                Martin
                -----BEGIN PGP SIGNATURE-----
                Version: GnuPG v1.4.1 (GNU/Linux)
                Comment: Using Mailcrypt+GnuPG <http://www.gnupg.org>

                iEYEARECAAYFAkO ba8oACgkQYu1fMm OQldXzcgCg0JEGT EG7xC/yAx8C1VFO8H1R
                LWwAnRJ8AxHBe8Y oHcDC5oGRfYaPHT fX
                =HdTR
                -----END PGP SIGNATURE-----

                Comment

                • Paul Boddie

                  #9
                  Re: OO in Python? ^^

                  Heiko Wundram wrote:[color=blue]
                  > Matthias Kaeppler wrote:[color=green]
                  > > <snip a whole lot of talk of someone still thinking in terms of C>[/color][/color]

                  Well, unless you are (or he is) in with the GNOME crowd, C probably
                  isn't really the object-oriented language acting as inspiration here.

                  [Zen of Python]

                  Of course the ZoP (Zen of Python) is deep guidance for those
                  languishing in some design dilemma or other, but not exactly helpful,
                  concrete advice in this context. (I'm also getting pretty jaded with
                  the recent trend of the ZoP being quoted almost once per thread on
                  comp.lang.pytho n, mostly as a substitute for any real justification of
                  Python's design or any discussion of the motivations behind its
                  design.) That said, the questioner does appear to be thinking of
                  object-oriented programming from a statically-typed perspective, and
                  I'd agree that, ZoP or otherwise, a change in perspective and a
                  willingness to accept other, equally legitimate approaches to
                  object-orientation will lead to a deeper understanding and appreciation
                  of the Python language.

                  Anyway, it appears that the questioner is confusing declarations with
                  instantiation, amongst other things:
                  [color=blue]
                  > And how do I formulate polymorphism in Python? Example:
                  >
                  > class D1(Base):
                  > def foo(self):
                  > print "D1"
                  >
                  > class D2(Base):
                  > def foo(self):
                  > print "D2"
                  >
                  > obj = Base() # I want a base class reference which is polymorphic[/color]

                  Well, here one actually gets a reference to a Base object. I know that
                  in C++ or Java, you'd say, "I don't care exactly what kind of Base-like
                  object I have right now, but I want to be able to hold a reference to
                  one." But in Python, this statement is redundant: names/variables
                  potentially refer to objects of any type; one doesn't need to declare
                  what type of objects a name will refer to.
                  [color=blue]
                  > if (<need D1>):
                  > obj = D1()
                  > else:
                  > obj = D2()[/color]

                  Without the above "declaratio n", this will just work. If one needs an
                  instance of D1, one will assign a new D1 object to obj; otherwise, one
                  will assign a new D2 object to obj. Now, when one calls the foo method
                  on obj, Python will just find whichever implementation of that method
                  exists on obj and call it. In fact, when one does call the method, some
                  time later in the program, the object held by obj doesn't even need to
                  be instantiated from a related class: as long as the foo method exists,
                  Python will attempt to invoke it, and this will even succeed if the
                  arguments are compatible.

                  All this is quite different to various other object-oriented languages
                  because many of them use other mechanisms to find out whether such a
                  method exists for any object referred to by the obj variable. With such
                  languages, defining a base class with the foo method and defining
                  subclasses with that method all helps the compiler to determine whether
                  it is possible to find such a method on an object referred to by obj.
                  Python bypasses most of that by doing a run-time check and actually
                  looking at what methods are available just at the point in time a
                  method is being called.
                  [color=blue]
                  > I could as well leave the whole inheritance stuff out and the program would still work
                  > (?).[/color]

                  Correct. Rewinding...
                  [color=blue]
                  > Does inheritance in Python boil down to a mere code sharing?[/color]

                  In Python, inheritance is arguably most useful for "code sharing", yes.
                  That said, things like mix-in classes show that this isn't as
                  uninteresting as one might think.

                  Paul

                  Comment

                  • Leif K-Brooks

                    #10
                    Re: OO in Python? ^^

                    Heiko Wundram wrote:[color=blue]
                    > Fredrik Lundh wrote:[color=green]
                    >>Matthias Kaeppler wrote:[color=darkred]
                    >>>polymorphi sm seems to be missing in Python[/color]
                    >>
                    >>QOTW![/color]
                    >
                    > Let's have some UQOTW: the un-quote of the week! ;-)[/color]

                    +1

                    Comment

                    • Heiko Wundram

                      #11
                      Re: OO in Python? ^^

                      Paul Boddie wrote:[color=blue]
                      > Heiko Wundram wrote:[color=green]
                      >> Matthias Kaeppler wrote:[color=darkred]
                      >> > <snip a whole lot of talk of someone still thinking in terms of C>[/color][/color]
                      >
                      > Well, unless you are (or he is) in with the GNOME crowd, C probably
                      > isn't really the object-oriented language acting as inspiration here.[/color]

                      Pardon this glitch, I corrected it in a followup-post somewhere along the
                      line, it's been some time since I've last used C/C++ for more than just
                      Python module programming and as such the term C has come to be synonymous
                      to "everything not Python" for me. ;-)
                      [color=blue]
                      > [Zen of Python][/color]

                      I find pointing to the ZoP pretty important, especially for people who start
                      to use the language. I know the hurdle that you have to overcome when you
                      grew up with a language which forces static typing on you (I learnt Pascal
                      as my first language, then used C, C++ and Java extensively for quite some
                      time before moving on to Perl and finally to Python), and when I started
                      using Python I had just the same feeling of "now why doesn't Python do this
                      like C++ does it, I loose all my security?" or something similar.

                      What got me thinking was reading the ZoP and seeing the design criteria for
                      the language. That's what actually made me realize why Python is the way it
                      is, and since that day I am at ease with the design decisions because I can
                      rationally understand and grip them and use the design productively. Look
                      at namespaces: I always understood what a namespace was (basically a
                      dictionary), but it took Tim Peters three lines

                      """
                      Simple is better than complex.
                      Flat is better than nested.
                      Namespaces are one honking great idea -- let's do more of those!
                      """

                      to actually get a hint at what the designer thought about when he
                      implemented namespaces as they are now, with the simplicity that they
                      actually have. It's always better to follow the designers thoughts about
                      something he implemented than to just learn that something is the way it is
                      in a certain language.

                      I still have that awkward feeling for Perl. TIMTOWTDI just doesn't cut it
                      when it's yelled at me, I still can't see a single coherent vision which
                      Larry Wall followed when he designed the language. That's why I decided to
                      drop it. ;-)

                      Maybe I'm assuming things by thinking that others also follow my line of
                      thought, but I've actually had very positive responses so far when telling
                      people that a certain feature is a certain way and then pointing them to
                      the ZoP, they all pretty much told me after a certain time of thought that
                      "the decision made sense now."

                      --- Heiko.

                      Comment

                      • Matthias Kaeppler

                        #12
                        Re: OO in Python? ^^

                        Heiko Wundram wrote:[color=blue]
                        > Brian Beck wrote:
                        >[color=green][color=darkred]
                        >>>class D1(Base):
                        >>> def foo(self):
                        >>> print "D1"
                        >>>
                        >>>class D2(Base):
                        >>> def foo(self):
                        >>> print "D2"
                        >>>obj = Base() # I want a base class reference which is polymorphic
                        >>>if (<need D1>):
                        >>> obj = D1()
                        >>>else:
                        >>> obj = D2()[/color]
                        >>
                        >>I have no idea what you're trying to do here and how it relates to
                        >>polymorphis m.
                        >>[/color]
                        >
                        >
                        > He's translating C++ code directly to Python. obj = Base() creates a
                        > variable of type Base(), to which you can assign different object types (D
                        > (), D2()) which implement the Base interface (are derived from Base).
                        > Err... At least I think it's what this code is supposed to mean...
                        >
                        > In C++ you'd do:
                        >
                        > Base *baseob;
                        >
                        > if( <i want d1> ) {
                        > baseob = (Base*)new D1();
                        > } else {
                        > baseob = (Base*)new D2();
                        > }
                        >
                        > baseob->foo();
                        >
                        > (should, if foo is declared virtual in Base, produce "d1" for D1, and "d2"
                        > for D2)
                        >
                        > At least IIRC, it's been quite some time since I programmed C++... ;-)
                        > *shudder*[/color]

                        Yes, that's what I tried to express (the cast to Base* is redundant here
                        by the way, since D1/D2 are also of type Base; you can always hold a
                        base class pointer to derived types without type conversion).

                        I have also read the other answers to my question, and I am really sorry
                        if I have sounded ignorant in my post, but it's harder than I thought to
                        move to a language where all these techniques one had learned in years
                        of hard work suddenly become redundant :)
                        I'm so used to statically typed languages that the shift is very
                        confusing. Looks as if it isn't as easy to learn Python afterall, for
                        the mere reason of unlearning rules which don't apply in the world of
                        Python anymore (which seem to be quite a lot!).

                        Regards,
                        Matthias

                        Comment

                        • Matthias Kaeppler

                          #13
                          Re: OO in Python? ^^

                          Brian Beck wrote:[color=blue]
                          > def foo(self):
                          > raise NotImplementedE rror("Subclasse s must implement foo")[/color]

                          That's actually a good idea, though not as nice as a check at
                          "compile-time" (jesus, I'm probably talking in C++ speech again, is
                          there such a thing as compile-time in Python at all?!)

                          Another thing which is really bugging me about this whole dynamically
                          typing thing is that it seems very error prone to me:

                          foo = "some string!"

                          # ...

                          if (something_fuba r):
                          fo = "another string"

                          Oops, the last 'o' slipped, now we have a different object and the
                          interpreter will happily continue executing the flawed program.

                          I really see issues with this, can anyone comment on this who has been
                          working with Python more than just a day (like me)?

                          Regards,
                          Matthias

                          Comment

                          • Matthias Kaeppler

                            #14
                            Re: OO in Python? ^^

                            That was quite insightful Martin, thanks.

                            Regards,
                            Matthias

                            Comment

                            • Torsten Bronger

                              #15
                              Re: OO in Python? ^^

                              Hallöchen!

                              Matthias Kaeppler <void@void.co m> writes:
                              [color=blue]
                              > [...]
                              >
                              > Another thing which is really bugging me about this whole
                              > dynamically typing thing is that it seems very error prone to me:
                              >
                              > foo = "some string!"
                              >
                              > # ...
                              >
                              > if (something_fuba r):
                              > fo = "another string"
                              >
                              > Oops, the last 'o' slipped, now we have a different object and the
                              > interpreter will happily continue executing the flawed program.
                              >
                              > I really see issues with this, can anyone comment on this who has
                              > been working with Python more than just a day (like me)?[/color]

                              There are even a couple of further checks which don't happen
                              (explicitly) in a dynamic language like Python, and which do happen
                              in most statically typed languages like C++. And yes, they are a
                              source of programming mistakes.

                              However, in everyday programming you don't feel this. I don't make
                              more difficult-to-find mistakes in Python than I used to make in my
                              C++ code. But what you do feel is the additional freedom that the
                              dynamic approach gives to you.

                              Basically it's a matter of taste and purpose whether you want to be
                              controlled heavily or not. Python is particularly liberal, which I
                              appreciate very much.

                              Tschö,
                              Torsten.

                              --
                              Torsten Bronger, aquisgrana, europa vetus ICQ 264-296-646

                              Comment

                              Working...