0

I have sort of an interesting request here. Let's say I have a class called Object, which has two methods, func1() and func2(). The second method calls func1(), though I would like to be able to alter the function definition of func1() be able to differentiate between being called from within func2() from being called as a standalone method of my Object class, like so:

obj = Object()
obj.func1()

I could simply create two versions of the function (one private method, for func2() to use, and one public method for the user to be able to access; yes I know that in python there really is no such thing as private, but following I think the normal naming conventions, I can make it clear that it is meant to be an internal function only). But that would require a fair amount of redundancy, and is something I would like to try to avoid if at all possible. Is there any mechanism or strategy anybody can recommend for doing this type of thing?

I know, for example, that if I wanted my entire script object.py to execute a certain set of code if ran only as a standalone script (i.e. - it's not being imported at the top of another script), I would do:

if __name__ == "__main__":
    ...
    code to run if standalone
    ...

I was wondering if there is a similar strategy for methods of a class.

6
  • 1
    This isn't possible in a non-hacky way. Why do you feel you need to do this? In addition to creating separate methods, another possibility is to add an argument to the function that func2 can use when calling it to indicate "internal" use. Commented Mar 6, 2014 at 17:57
  • 1
    The trick is to factor the redundant code into a separate "common" function that both can use. Commented Mar 6, 2014 at 17:59
  • I feel I need to do this because called in a certain way, I would like to produce terminal output, whereas if this function is called internally, I would like it to forego printing to the terminal. Commented Mar 6, 2014 at 17:59
  • Set a debug attribute on the class. with self.debug = True, then print to the terminal, otherwise don't print. Commented Mar 6, 2014 at 18:01
  • @mgilson That sounds like a good strategy, actually. What about decorators? Could I use that in some way? I think refactoring is good, but it would take a bit of time to do that. Commented Mar 6, 2014 at 18:01

3 Answers 3

2

You can also use inspect like this:

import inspect

def func2():
    if inspect.stack()[1][3] == "func1":
        #...do something...
    else:
        #...do something else...

def func1():
    return func2()

See the official documentation for details:

http://docs.python.org/2/library/inspect.html

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

Comments

1

You could use sys._getframe() and depending on the caller decide what to do. f_code.co_name returns the function

import sys

class MyClass(object):
    def func1(self):
        frame = sys._getframe(1)
        if frame.f_code.co_name == 'func2':
            print "called from func2"
        else:
            print "called from elsewhere"
    def func2(self):
        self.func1()

c = MyClass()
c.func1()
c.func2()

4 Comments

Would you be willing to make a barebones example class with 2 functions which implements this?
@astromax see example added to my answer
Great, this is exactly what I needed! Thanks! Since you answered first I think I have to give you the checkmark.
Please note that _getFrame should be used for internal and specialized purposes only. It is not guaranteed to exist in all implementations of Python.
1

By reading your comments, it seems that your actual problem is this: you have a method that prints some output. If the user calls the code, then you want that output to be printed to the terminal. If the code is called internally by another method, you don't want the output to be printed.

The debug arg as suggested by @mgilson is a good option, but you'd prefer that the user not know about this option, for whatever reason.

And alternative is to make a function wrapper to redirect stdout during the function call, then restore it afterwards. Something like this:

import os
import sys

def suppress_print(f, *args, **kwargs):
    """Call the function f, but print to the null device 
    instead of the screen."""
    old_stdout = sys.stdout
    sys.stdout = open(os.devnull, 'w')

    result = f(*args, **kwargs)

    sys.stdout = old_stdout

    return result

class Foo:

    def bar(self):
        print "This is a test."
        return 42

    def baz(self):
        return suppress_print(self.bar)


foo = Foo()

# this should print to the terminal
foo.bar()

# this shouldn't
foo.baz()

Then, whenever you call the function internally, you wrap it with suppress_print, and the output will be squashed. Note that this is actually a nice place to use a context manager, but I'll leave that as a further exercise...

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.