【问题标题】:python: enforce that a class method is only called from within another class method?python:强制只从另一个类方法中调用一个类方法?
【发布时间】:2011-01-26 10:49:47
【问题描述】:

我有一个包含两个方法 A 和 B 的类。该类将被子类化。有没有一种优雅的方法来强制 B() 只在 A() 方法中对类的对象调用?

让我们限制它,说 A() 只在一个地方被调用,但子类实现 A() 并且可以选择在其中调用 B()。我想到的一种方法是通过设置一个全局变量来包装 A() 调用,该变量表示可以调用 B(),并且 B() 会在调用该变量时检查该变量。但这似乎并不优雅。

有什么建议吗?

【问题讨论】:

  • 只需通过添加前导下划线将B 设为私有,因此它是_B。这告诉人们这是一种私有方法。我认为在 Python 中没有一种简单甚至可靠的方式来做你想做的事情。
  • 听起来,从 OOP 设计的角度来看,您的基类对派生自它的类了解太多。
  • 在前面加一个下划线来表示“私人”,并假设使用 tnis 对象的人是聪明的,然后继续解决更重要的问题。

标签: python


【解决方案1】:

实际的私有方法是邪恶的。通过添加前导下划线将您的方法标记为内部方法。这告诉程序员除非他们知道自己在做什么,否则不要使用它。

【讨论】:

  • 您能详细说明一下吗?私有方法有什么问题?
  • @Makis:你阻止人们打电话给他们,如果他们需要打电话给他们,你只是无缘无故地让他们生活困难。对于更长的解释,我有这个答案:stackoverflow.com/questions/4683937/…
  • 为什么别人可以调用内部函数? C 中的静态函数也不好吗?
  • @Makis:调用内部函数的必要性在现实世界中经常出现,当您使用的库不能完全满足您的需求时。
  • 对我来说,这听起来更像是糟糕的设计。如果您认为 static 是一个完全无用的关键字,我仍然很想听听。但总的来说,我只是认为你鼓励糟糕的设计(“我不必为 API 考虑太多,我会公开所有内容”)。
【解决方案2】:

虽然我不推荐这种做法,但可以使用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()

输出:

== 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多