Overriding internal method function in python

This is kind of a best practice question.

I have a class structure with certain methods. In some cases, I want to override a specific part of the method. At first I thought it was splitting my method into more atomic elements and redefining related parts like below.

class myTest(object):
    def __init__(self):
        pass

    def myfunc(self):
        self._do_atomic_job()
        ...
        ...

    def _do_atomic_job(self):
        print "Hello"

      

This is a practical way to solve the problem. But since I have too many parameters to pass and return from _do_atomic_job()

, I don't want to pass and retrieve many parameters. Another parameter sets these parameters as class variables with self.param_var

etc., but these parameters are used in a small piece of code and using is self

not my preferred way of solving this question.

The last option I thought uses internal functions. (I know I'm going to have problems with variable scopes, but as I said, this is best practice and they just ignore them and think that scope and all things about internal functions work as expected).

class MyTest2(object):
    mytext = ""

    def myfunc(self):
        def _do_atomic_job():
            mytext = "Hello"
        _do_atomic_job()
        print mytext

      

Let's assume it works as expected. What I want to do is override the inner function_do_atomic_job()

class MyTest3(MyTest2):
    def __init__(self):
        super(MyTest3, self).__init__()
        self.myfunc._do_atomic_job = self._alt_do_atomic_job  # Of course this do not work!

    def _alt_do_atomic_job(self):
        mytext = "Hollla!"

      

Doing what I want to achieve is to override the internal function of the inherited class method _do_atomic_job

Is it possible?

+3


source to share


2 answers


Either factoring it _do_atomic_job()

into the correct method, or perhaps factoring it into your class seems to be the best approach. Overriding an internal function cannot work because you will not have access to the local variable containing the method.

You say you _do_atomic_job()

take many parameters, return many values. Perhaps you are grouping some of these parameters into sane objects:

_do_atomic_job(start_x, start_y, end_x, end_y) # Separate coordinates
_do_atomic_job(start, end)                     # Better: start/end points
_do_atomic_job(rect)                           # Even better: rectangle

      

If you cannot do this and _do_atomic_job()

is self-contained enough, you can create helper classes AtomicJobParams

and AtomicJobResult

. Example using namedtuples

instead of classes:

AtomicJobParams = namedtuple('AtomicJobParams', ['a', 'b', 'c', 'd'])

jobparams = AtomicJobParams(a, b, c, d)
_do_atomic_job(jobparams)                # Returns AtomicJobResult

      



Finally, if the atomic assignment is self-contained, you might even put your own class at risk AtomicJob

.

class AtomicJob:
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self._do_atomic_job()

    def _do_atomic_job(self):
        ...
        self.result_1 = 42
        self.result_2 = 23
        self.result_3 = 443

      

Overall, it looks more like a code factorization problem. Aim for classes that delegate work to helpers where needed. Follow the principle of single responsibility . If the values ​​belong together, combine them into a value class.

As David Miller (a renowned Linux kernel developer) recently said :

If you write interfaces with more than 4 or 5 function arguments, it is possible that you and I may not be friends.

+3


source


Internal variables are related to where they are defined, not where they run. This prints "hello".

class MyTest2(object):
    def __init__(self):
        localvariable = "hello"
        def do_atomic_job():
            print localvariable
        self.do_atomic_job = do_atomic_job

    def myfunc(self):
        localvariable = "hollla!"
        self.do_atomic_job()


MyTest2().myfunc()

      



So I see no way to use local variables without passing them in, which is probably the best way to do it.

Note. Passing locals()

will bring you a variable of variables, however this is considered pretty bad.

0


source







All Articles