1

I want to monkey patch a function which private and part of a class but I also want to call the patched function.

Example:

class SomeClass:
    def __some_function(self, foo):
        return do_something()

Now I want to write something like

def new_function(self, foo)
    if foo == 'bar':
        return True
    return super(self).__some_function(foo)

SomeClass.__some_function = new_function

I tried to overwrite this with a decorator but I had problems to call the old function because it wasn't accessible. Also I checked the mock library but didn't understand how to something like this with calling the old function with the parameters.


The decorator I tried:

def patch_something(method):
    def new_function(self, foo):
        if foo == 'bar':
            return True
        return method(self, foo)
    return new_function

SomeClass.__some_function = patch_something(SomeClass.__some_function)

I getting this error (the class is in another file - is this a problem?).

AttributeError: type object 'SomeClass' has no attribute '__some_function'
4
  • Can you show us the code that didn't work? If you want to call the overwritten method you should store it somewhere. Commented Jun 21, 2016 at 11:32
  • 1
    Attributes with __ are name mangled i.e. see here docs.python.org/2/tutorial/… . You should be able to acess it by SomeClass._someclass__some_function. Commented Jun 21, 2016 at 11:54
  • Thanks for the help, it works :D :D. This was the desired answer (but should be SomeClass._SomeClass__some_function). Commented Jun 21, 2016 at 12:05
  • what happens when __some_function is out of a class in a file called A.py Commented Aug 16, 2017 at 13:50

1 Answer 1

3

Attributes with double underscore __ are name mangled and need to be accessed by the mangled name as described in the documentation:

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.