python's OOP question

Discussion in 'Python' started by neoedmund, Oct 16, 2006.

  1. neoedmund

    neoedmund Guest

    There's a program, it's result is "unexpected aaa", i want it to be
    "expected aaa". how to make it work?

    Code (Text):


    class C1(object):
        def v(self, o):
            return "expected "+o

    class C2(object):
        def v(self, o):
            return "unexpected "+o
        def m(self):
            print self.v("aaa")

    class C3(object):
        def nothing(self):
            pass

    def test1():
        o = C3()
        setattr(o,"m",C2().m)
        setattr(o,"v",C1().v)
        o.m()

    test1()

     
     
    neoedmund, Oct 16, 2006
    #1
    1. Advertisements

  2. neoedmund

    Kay Schluehr Guest

    class C3(C1, C2):pass
    [/QUOTE]
    expected aaa
     
    Kay Schluehr, Oct 16, 2006
    #2
    1. Advertisements

  3. neoedmund

    Ben Finney Guest

     
    Ben Finney, Oct 16, 2006
    #3
  4. neoedmund

    neoedmund Guest

    thank you, Kay.

    But i need a "dynamic" way. Say i have a existing class, and add some
    method from other class into it.


    expected aaa[/QUOTE]
     
    neoedmund, Oct 16, 2006
    #4
  5. neoedmund

    neoedmund Guest

    I'm trying to achieve a higher level of "reusability". Maybe it cannot
    be done in python? Can anybody help me?


     
    neoedmund, Oct 16, 2006
    #5
  6. neoedmund

    Ben Finney Guest

    [Please don't top-post above the text to which you're replying.]

    What, specifically, are you trying to achieve? What problem needs
    solving?
     
    Ben Finney, Oct 16, 2006
    #6
  7. neoedmund

    neoedmund Guest

    python use multiple inheritance.
    but "inheritance" means you must inherite all methods from super type.
    now i just need "some" methods from one type and "some" methods from
    other types,
    to build the new type.
    Do you think this way is more flexible than tranditional inheritance?


     
    neoedmund, Oct 16, 2006
    #7
  8. Probably your problem is better solved with delegation instead of
    inheritance.
     
    Gregor Horvath, Oct 16, 2006
    #8
  9. The following does the trick:

    from types import MethodType

    def addMethod(meth, obj):
    f = meth.im_func
    setattr(obj, f.__name__, MethodType(f,obj))

    def test1():
    addMethod(C2.m, C3)
    addMethod(C1.v, C3)
    o = C3()
    o.m()

    The same works as is on modifying individual instances, rather than
    their class:

    def test2():
    o = C3()
    addMethod(C2.m, o)
    addMethod(C1.v, o)
    o.m()
    # raises AttributeError
    # C3().m()


    George
     
    George Sakkis, Oct 16, 2006
    #9
  10. neoedmund

    neoedmund Guest

    I found a dynamic way to inherite classes:

    def MixIn(pyClass, mixInClass):
    if mixInClass not in pyClass.__bases__:
    pyClass.__bases__ += (mixInClass,)

    def test1():
    o = C3()
    MixIn(C3,C1)
    MixIn(C3,C2)
    o.m()

    "expected aaa"
     
    neoedmund, Oct 16, 2006
    #10
  11. neoedmund

    neoedmund Guest

    Oh, How great is the solution! ( though i don't know how it works. )
    Thank you George.
     
    neoedmund, Oct 16, 2006
    #11
  12. neoedmund wrote:
    (*PLEASE* stop top-posting - corrected)
    While dynamically adding attributes (and methods - which are attributes
    too) is not a problem, I'd second Gregor's anwser : it might be better
    to use composition/delegation here.
     
    Bruno Desthuilliers, Oct 16, 2006
    #12
  13. neoedmund

    neoedmund Guest

    Could you show some code to help me know how composition/delegation can
    be done here? Thanks.
     
    neoedmund, Oct 16, 2006
    #13
  14. neoedmund

    Kay Schluehr Guest

    Starting with your example C2 might just derive from C1 and perform a
    supercall:

    class C1(object):
    def v(self, o):
    return "expected "+o


    class C2(C1):
    def v(self, o):
    return "unexpected "+o
    def m(self):
    print super(C2,self).v("aaa")
    expected aaa

    But in general there is no single pattern to deal with object
    composition.
     
    Kay Schluehr, Oct 16, 2006
    #14
  15. About composition/delegation, there's no "one-size-fits-all" answer, but
    the main idea is to use the magic '__getattr__(self, name)' method.

    Now back to your specific case : after a better reading of your original
    question, straight composition/delegation wouldn't work here - at least
    not without modifications to both C1 and C2 (sorry, should have read
    better the first time).

    Given the context (ie : "create a new type with methods from type X and
    methods from type Y"), a very simple solution could be:

    class C3(object):
    m = C2.m.im_func
    v = C1.v.im_func

    FWIW, if you have full control over C1, C2 and C3, you could also just
    'externalize' the functions definitions:

    def v1(self, o):
    return "expected "+o

    def v2(self, o):
    return "unexpected "+o

    def m2(self):
    """ requires that 'self' has a v(self, somestring) method """
    print self.v("aaa")

    class C1(object):
    v = v1

    class C2(object):
    v = v2
    m = m2

    class C3(object):
    v = v1
    m = m2


    The problem (with the whole approach, whatever the choosen technical
    solution) is that if one of theses methods depends on another one (or on
    any other attribute) that is not defined in your new class, you're in
    trouble. This is not such a big deal in the above example, but might
    become much more brittle in real life.

    Now we can look at the problem from a different perspective. You wrote:
    """
    but "inheritance" means you must inherite all methods from super type.
    now i just need "some" methods from one type and "some" methods from
    other types, to build the new type.
    """

    What is your problem with having the other extra methods too ?
     
    Bruno Desthuilliers, Oct 16, 2006
    #15
  16. neoedmund

    neoedmund Guest

    Bruno , your 2 great and clear samples revealed what method is in
    python, which is also I really want to ask. thank you.
    So I can reuse a method freely only if it's worth reusing.
    For the word "inheritance", in some aspect, meanings reuse the super
    class, with the condition: must reuse everything from super class.
    It's lack of a option to select which methods are to be reused.
    this is something should be improved for general OOP i think.
    So to answer " What is your problem with having the other extra methods
    too ?",
    in real life, a class is not defined so well that any method is needed
    by sub-class. so contains a method never to be used is meaningless and
    i think something should forbidden.
    also, any handy methods in a class can be grabbed out for our reuse. so
    we can forgotting the bundering inheritance tree and order.
     
    neoedmund, Oct 17, 2006
    #16
  17. neoedmund wrote:
    (snip)
    Not really. In fact, inheritance *is* a special case of
    composition/delegation. A 'child' class is a class that has references
    to other classes - it's 'parents' -, and then attributes that are not
    found in the instance or child class are looked up in the parents
    (according to mro rules in case of multiple inheritance). And that's all
    there is.
    Methods not redefined in the 'child' class or it's instance are
    'reusable'. Now they are only effectively 'reused' if and when called by
    client code. So the 'option to select which methods are to be reused' is
    mostly up to both the 'child' class and code using it.
    Then perhaps is it time to refactor. A class should be a highly cohesive
    unit. If you find yourself needing only a specific subset of a class, it
    may be time to extract this subset in it's own class. Given Python's
    support for both multiple inheritance and composition/delegation, it's
    usually a trivial task (unless you already mixed up too many orthogonal
    concerns in your base class...).
     
    Bruno Desthuilliers, Oct 17, 2006
    #17
  18. neoedmund

    neoedmund Guest

    ivestgating the web, i found something similiar with my approch:
    http://en.wikipedia.org/wiki/Duck_typing
    "Duck-typing avoids tests using type() or isinstance(). Instead, it
    typically employs hasattr() tests"
     
    neoedmund, Oct 18, 2006
    #18
  19. neoedmund

    neoedmund Guest

    I donnot agree with your "it's time to refactory" very much, man has
    probly never has time to do such things. suppose a system is working
    soundly, you maybe has no time or motivation to do refactory instead of
    having a vocation to a island. it's easy to say, at lease myself has
    not the experience to do such things, :)
     
    neoedmund, Oct 18, 2006
    #19
  20. that's not entirely correct, though: in Python, duck-typing typically
    uses "Easier to Ask Forgiveness than Permission" (EAFP), aka "Just Do
    It", rather than "Look Before You Leap" (LBYL).

    </F>
     
    Fredrik Lundh, Oct 18, 2006
    #20
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.