2

I have come across a python project that commonly calls external functions from class methods and passes the class instance and some other parameters to the external function.

The method used is shown in method_one below and I have never come across this implementation before. Using locals to get both the local method parameters and the self class instance seems strange to say the least. The code then relies upon the dictionary keys being named correctly i.e. the same as the parameters of the external function (some_function).

To me, the obvious, simpler direct alternative is method_two but even over that I would prefer either

  1. making some_function a method of ExampleClass1 so it has direct access to self, or
  2. passing only the required attributes of the ExampleClass1 instance to some_function.

Example code:

class ExampleClass1(object):
    def __init__(self, something):
        self.something = something

    def method_one(self, param_1, param_2):
        all_params = locals()
        all_params['example_self'] = all_params.pop('self')
        some_function(**all_params)

    def method_two(self, param_1, param_2):
        some_function(self, param_1, param_2)


def some_function(example_self, param_1, param_2):
    print(example_self.something, param_1, param_2)


e = ExampleClass1("do")
e.method_one(1, "a")
e.method_two(2, "b")

So,

  1. Is there any reason to be using method_one that I'm not aware of?
  2. How would you offer advice on the best practice for this situation?
1
  • 1
    I'd say example one is just really bad practice. Don't do that and be careful with the code where you found it. In Python, we have a saying that explicit is better than implicit, example one breaks that principle, severly. Commented Jun 14, 2018 at 21:47

1 Answer 1

1

Passing self as a parameter to external functions is a totally standard practice. I'm a little unclear why the call to locals() is used and why keys are being shuffled around, but that's a separate matter. In general, I find that if you're using locals(), then 9 times out of 10 the code you're writing can be simpler. Notable exception being metaprogramming, which is another topic.

One example that I use this for is when you want to separate out code into several modules rather than have one large class with a bunch of methods. There's a lot of ways to organize code, but one approach that I use is to segregate functions to other modules based on their domain, and then pass self to those functions for their use.

Concrete example: a server object accepting requests can have the routes handling those requests live elsewhere, and then delegate the actual business logic to the external route functions. If those routes need the server object, though, then you may want to pass self (being the server) to them. You could make an argument they should just be methods then, but that's a matter of code style and depends a lot on exact use case.

In general, passing self around isn't a bad practice when used appropriately.

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

2 Comments

Yes, totally agree about passing self being normal practice. I was just wondering if there was something special about using the locals() method - doesn't appear so! Thanks
Yeah, I'd rank using locals() and globals() up there with exec(): to be avoided 99.9% of the time, and the .1% of the time has to be really really justified. Anything having to do with looking at "the state of the program execution" from a meta level is generally ill-advised because it's not explicit at all what you're doing.

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.