0

I have a class with two methods A and B. The class will be subclassed. Is there an elegant way to enforce that B() is only ever called on an object of the class from within the A() method?

Let's constrain it and say that A() is only called in one place but subclasses implement A() and can optionally call B() within that. One way I thought of doing this was to wrap the A() call with setting a global variable that says it's ok to call B(), and B() would check this variable when it's invoked. This doesn't seem elegant though.

Any suggestions?

3
  • 1
    Just make B private by adding a leading underscore so it's _B. That tells people it's a private method. I don't think there's an easy or even reliable way to do what you want in Python. Commented Jan 26, 2011 at 11:07
  • 1
    It also sounds like, from an OOP design point-of-view, like your base class knows too much about the class(es) that will be derived from it. Commented Jan 26, 2011 at 13:13
  • 1
    Prepend an underscore to signify "private", and assume people who use tnis object are intelligent, then move on to more important problems. Commented Jan 26, 2011 at 13:33

2 Answers 2

5

Actual private methods is an evil. Mark your method as internal by adding a leading underscore. This tells programmers not to use it unless they know what they are doing.

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

14 Comments

Could you elaborate on this? What's wrong with private methods?
@Makis: You are preventing people from calling them, and if they then need to call them, you are just making life difficult for them for no reason. For a longer explanation, I have this answer: stackoverflow.com/questions/4683937/…
Why should others be able to call internal functions? Are static functions in C bad as well?
@Makis: The necessity to call internal functions pop up quite often in the real world, when a library you are using isn't doing just exactly what you want.
To me that sounds like poor design more than anything. I'm still interested to hear if you think static is a completely useless keyword. But in general I just think you encourage poor design ("I don't have to think too hard about the API, I'll just make everything public").
|
2

Although I don't recommend the practice, here's a way it could be done using sys._getframe():

import sys

class Base(object):
    def A(self):
        print '  in method A() of a {} instance'.format(self.__class__.__name__)

    def B(self):
        print '  in method B() of a {} instance'.format(self.__class__.__name__)
        if sys._getframe(1).f_code.co_name != 'A':
            print '    caller is not A(), aborting'
            return
        print '    called from A(), continuing execution...'

class Derived(Base):
    def A(self):
        print "  in method A() of a {} instance".format(self.__class__.__name__)
        print '    calling self.B() from A()'
        self.B()

print '== running tests =='
base = Base()
print 'calling base.A()'
base.A()
print 'calling base.B()'
base.B()
derived = Derived()
print 'calling derived.A()'
derived.A()
print 'calling derived.B()'
derived.B()

The output:

== running tests ==
calling base.A()
  in method A() of a Base instance
calling base.B()
  in method B() of a Base instance
    caller is not A(), aborting
calling derived.A()
  in method A() of a Derived instance
    calling self.B() from A()
  in method B() of a Derived instance
    called from A(), continuing execution...
calling derived.B()
  in method B() of a Derived instance
    caller is not A(), aborting

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.