0

In python 3.4 I have a member object through composition.

I would like to override one of it's member functions.

def class Foo:
    def __init__(self, value):
        self.value = value
    def member_obj.baz(baz_self, arg):
        print("my new actions on {}".format(arg))
        Foo.member_obj.baz(arg) #the original function

foo_inst = Foo(2)
bar = Bar(*bar_parameters) #from a third party module
setattr(foo_inst, "member_obj", bar) #it did not "stick" when I did foo_inst.member_obj = bar

foo_inst.member_obj.baz("some argument")

It does not make sense to inherit from the Bar class. I also only want this different behaviour to occur if the object is inside Foo. I use Bar in many other places and would like to retain the same way of calling the method. I.e. I would like to avoid wrapping it in Foo.baz.

Is it even possible to do something like the def member_obj.baz and is it a good idea?

It would be similar to this: https://softwareengineering.stackexchange.com/questions/150973/what-are-the-alternatives-to-overriding-a-method-when-using-composition-instea

Community
  • 1
  • 1
mvbentes
  • 1,022
  • 12
  • 24
  • `def member_obj.baz` is decidedly not valid. You'll have to subclass `Bar` and use that for `foo_inst.member_obj`. – chepner Aug 24 '15 at 17:24
  • I put it there to illustrate what I am trying to achieve. The `Bar` in question is `sqlalchemy.Session`. I would like to avoid subclassing it because it comes from a `sessionmaker` function, so I would have to change that too and there would also probably be other ties I am not aware of that might also break. I would like to add some routine before `session.expunge` for a mixin I am doing, so I would have no control over the time when It would get called. I think my best option would be to override it in the mixin if possible. – mvbentes Aug 24 '15 at 17:37

1 Answers1

1

Are you trying to do something like this?

class B():
    def __init__(self):
        self.x = None
    def fun(self):
        print("Assigning value to attribute of object of class B.\n")
        self.x = "Value of B object's attribute"
class A():
    def __init__(self):
        self.value = B()
    def fun(self):
        print("Screw this, I'll do something else this time!\n")
        self.value.x = 13
    def override(self):
        # Edit: you can assign any identifier (that is not reserved) to
        # any type of object or method AND the "fun" ("really self.fun") 
        # above is visible from here, since we passed "self" as an
        # argument
        self.value.fun = self.fun

myObj = B()
myOtherObj = A()
myOtherObj.override()

myObj.fun()
myOtherObj.value.fun()
Larry
  • 427
  • 2
  • 10
  • Sorry, but no. I would like to call `myOtherObj.value.fun` and have it rerouted to do something other than `B.fun`. The important part is to retain this way of calling: `myOtherObj.value.fun`. As I pointed in the question, I could wrap it in a `A.B_fun_wrapper` but I am trying to avoyd this course of action. – mvbentes Aug 24 '15 at 18:16
  • Ah, I see! In that case, you can do self.value.fun = self.fun in the __init() of the A class, since methods are visible everywhere inside a class, even "before" being def-fed, such as inside the __init__() – Larry Aug 24 '15 at 18:20
  • I edited my answer now to point this out. Also, I wrote "value = B()" instead of "self.value = B()" first, I apologize. – Larry Aug 24 '15 at 18:26
  • I will try this as soon as I can. There are some complications, though: `value` can not be in my init, because it would be later included by a Mixin as in my sample code. So I think I would not be able to do the assignment before having the member object. I will try to assign just after I include the object. – mvbentes Aug 24 '15 at 18:26
  • You can also reassign the identifier of the member object after you've created the containing one. You could do this manually outside of the class, but it is not really practical. Instead, you can write a method "ovverride(self)" to do just that, which you can call after you create the containing object. – Larry Aug 24 '15 at 18:31
  • I changed the answer again. I hope there are no mistakes this time. – Larry Aug 24 '15 at 18:41