I'm using python to do some research tasks. I have a class hierarchy for "tools", where each object is an instance of a particular tool. They all share some functionality and have many similarities in their states.

Some of these tools can use one of several methods based on the tool object's current state. The specific tool I'm going to ask about actually calls functions from external modules instead of methods written in the class directly. The underlying reason for this is to break up the code into multiple files, i.e. not have any huge monster file that has all the various methods and helper functions those methods use, when all it needs at any given time is a particular very-targeted subset. I.e. when the mode of the tool is "clean_house", I would only functions like "wash_windows", "vacuum_carpet", and "ask_girlfriend_for_help", while when the mode is "do_work", I use functions like "write_code", "debug_code", and "ask_SO_question". The subsets don't intersect in any way, i.e. "write_code" would never call "ask_girlfriend_for_help", etc.

Instead of calling these functions from module scope within the class methods, it seems to me that it's a better idea to monkeypatch them to the tool's class, since there are instance methods they need to call that go further up the class hierarchy and modify some (protected) part object's state that is used later in the destructor.

I know monkeypatching is often considered poor design or last-resort practice when hot-fixes are in order (Programmer's SE post here), but is it justified in this case? Any alternative code design suggestions?

  • 1
    Monkeypatching is the act of using Python's dynamic nature to change third-party code. What you are doing is using that same dynamic nature to build your class. That is not the same thing, per se. – Martijn Pieters Aug 9 '13 at 12:58
  • That makes sense. But is writing an "extension method" like this in a different module (for lack of a better way to describe it) a good idea at all? – Greg Kramida Aug 9 '13 at 13:06

You are not really monkey patching. Monkey patching is the act of using Python's dynamic nature to change third-party code. What you are doing is using that same dynamic nature to build your class. That is not the same thing, per se.

It sounds like you are delegating functionality to other modules. That sounds like a perfectly fine practice. But I don't quite see why you'd need to alter your tool to do so; your tool can pass on method calls to an underlying object that is responsible for the actual implementation, based on the current state.

Those responsible objects can still modify the state of the tool, as nothing in Python is private, really.

  • I understand the idea, I think it's good in many ways. However, I don't think you are entirely correct when you say "nothing in Python is private." Python does make provisions for encapsulation: "private" and "protected" are there (The destructor being the former). Besides, if I have code written in class A that holds class B as a field and uses it, instance of B would need a reference to its encapsulating instance of A, and even then it would be only able to call its public methods and access its public variables. – Greg Kramida Aug 9 '13 at 13:18
  • __del__ is not a destructor, nor is it private. The __ convention only applies to names that start with the double underscore, and that mechanism is intended to provide instance attributes with a namespace (subclasses using the same __name attributes or methods do not override the parent), not privacy. You can still access those attributes. Using _ for 'private' attributes is merely a convention. – Martijn Pieters Aug 9 '13 at 13:20
  • You are right that B would need a reference to A, but it can reach in and access anything A can, short of local variables in functions. – Martijn Pieters Aug 9 '13 at 13:21
  • What you're saying is certainly correct where it's dealing with fact. I think the misunderstanding hinges on the word "private" here, and it all depends on how you define it. The python documentation uses the word "private" to describe the things python achieves with name-mangling. Even if it doesn't fully prevent accessing those methods, it is clear they are not intended to be accessed from outside. Storing something in A_instance._A__private_state I think is a little more hacky and counter-intuitive then the "extension methods." – Greg Kramida Aug 9 '13 at 13:30
  • Then don't use double-underscore names for such state, or provide methods for B to access and influence the state of A. It is still your choice as to what the internal interactions are. – Martijn Pieters Aug 9 '13 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.