【问题标题】:python function calling within a classpython函数在类中调用
【发布时间】:2014-03-06 17:54:29
【问题描述】:

我在这里有一个有趣的请求。假设我有一个名为 Object 的类,它有两个方法,func1() 和 func2()。第二种方法调用 func1(),尽管我希望能够更改 func1() 的函数定义,能够区分从 func2() 内部调用和作为我的 Object 类的独立方法调用,就像这样:

obj = Object()
obj.func1()

我可以简单地创建函数的两个版本(一个私有方法,供 func2() 使用,一个公共方法供用户访问;是的,我知道在 python 中确实没有这样的东西私有的,但按照我认为正常的命名约定,我可以明确表示它只是一个内部函数)。但这需要相当多的冗余,这是我想尽可能避免的事情。有没有人可以推荐做这种事情的机制或策略?

我知道,例如,如果我希望我的整个脚本 object.py 仅作为独立脚本运行(即 - 它不会在另一个脚本的顶部导入)来执行某组代码,我会做:

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

我想知道类的方法是否有类似的策略。

【问题讨论】:

  • 这是不可能的。为什么你觉得你需要这样做?除了创建单独的方法之外,另一种可能性是在函数中添加一个参数,func2 在调用它时可以使用它来指示“内部”使用。
  • 诀窍是将冗余代码分解为一个单独的“通用”函数,两者都可以使用。
  • 我觉得我需要这样做,因为以某种方式调用,我想产生终端输出,而如果这个函数在内部调用,我希望它放弃打印到终端。
  • 在类上设置debug 属性。用self.debug = True,然后打印到终端,否则不打印。
  • @mgilson 实际上,这听起来是个不错的策略。装饰师呢?我可以以某种方式使用它吗?我认为重构是好的,但是这样做需要一些时间。

标签: python function oop methods


【解决方案1】:

你也可以像这样使用inspect

import inspect

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

def func1():
    return func2()

详见官方文档:

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

【讨论】:

  • 太好了,这正是我想要的!谢谢!
【解决方案2】:

您可以使用sys._getframe() 并根据调用者决定做什么。 f_code.co_name 返回函数

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()

【讨论】:

  • 您愿意制作一个具有 2 个实现此功能的准系统示例类吗?
  • @astromax 查看添加到我的答案中的示例
  • 太好了,这正是我需要的!谢谢!既然你先回答了,我想我必须给你打勾。
  • 请注意,_getFrame 只能用于内部和专门用途。它不保证在 Python 的所有实现中都存在。
【解决方案3】:

通过阅读您的 cmets,您的实际问题似乎是:您有一个打印一些输出的方法。如果用户调用代码,那么您希望将该输出打印到终端。如果代码在内部被其他方法调用,你不希望输出被打印出来。

@mgilson 建议的 debug 参数是一个不错的选择,但您希望用户不知道此选项,无论出于何种原因。

另一种方法是在函数调用期间制作一个函数包装器来重定向stdout,然后再恢复它。像这样的:

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()

然后,每当您在内部调用该函数时,都将其包装为suppress_print,并且输出将被压缩。请注意,这实际上是使用上下文管理器的好地方,但我将把它留作进一步的练习......

【讨论】:

    猜你喜欢
    • 2019-04-24
    • 2019-07-27
    • 1970-01-01
    • 2017-01-26
    • 2022-01-06
    • 1970-01-01
    • 2018-02-27
    • 2017-06-22
    • 2021-03-27
    相关资源
    最近更新 更多