如何使导入的函数调用新函数?

时间:2012-10-31 22:00:55

标签: python function python-2.7 return

经过几天的搜索和尝试不同的代码后,我仍然无法弄清楚我的问题。因此,我在这里发布了这个问题。

对于这个问题,我使用的是Python 2.7.2 具体来说,我使用合成将一个类的函数导入另一个类。导入的类的功能包括基于raw_input的简单if语句。根据用户的输入,if语句应以某种方式调用或至少帮助调用与输入相对应的新函数。但是,此函数将位于要导入的类的一部分中,而不是导入的类。

我在这里使用两个.py文件,每个类一个,并且它们位于同一个文件夹中。

这是第一个文件(main.py),其中包含主类:

# importing class from file in same folder
from class_decision import Decision

class Main_Compositor(object):

    def __init__(self):
        # using composition to call the function of the imported class
        self.door_decision = Decision()

    def comp_door(self):
        self.door_decision.user_text()

        if door == "left":
            left_door()
        elif door == "right":
            right_door()
        else:
            print "incorrect input"

    def left_door(self):
        print "you're in the left room"

    def right_door(self):
        print "you're in the right room"


# instantiating
A_Compositor = Main_Compositor()

# calling A_Compositor's function comp_door()
A_Compositor.comp_door()

这是class_decision.py文件,其类正在导入:

class Decision(object):

    def user_text(self):
        print "which door do you open:"
        print "left or right?"

        door = raw_input("> ")

        if door == "left":
            print "you have chosen the left door"
            return door
        elif door == "right":
            print "you have chosen the right door"
            return door
        else:
            print "you must choose a door"
            self.user_text()

正如您所看到的,我尝试使用Return让主要类知道变量door。这可能是对Return的错误使用。我也尝试过getattr但没有成功。如果这个问题被问了很多,我道歉。与我的所有相似的问题似乎与数组有关,我无法通过他们的答案找出我的问题。谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

def user_text(self):
    print "which door do you open:"
    print "left or right?"

    door = raw_input("> ")

    if door == "left":
        print "you have chosen the left door"
        return door
    elif door == "right":
        print "you have chosen the right door"
        return door
    else:
        print "you must choose a door"
        return self.user_text()  # don't forget to return in the recursion case
def comp_door(self):
    choice = self.door_decision.user_text()  # actually use the returned result

    if choice == "left":
        self.left_door()
    elif choice == "right":
        self.right_door()
    else:
        print "incorrect input"

答案 1 :(得分:0)

在这里使用类是没有意义的,因为只有一个方法。

只需将Decision变为函数。

答案 2 :(得分:-1)

  

但是,此函数将位于要导入的类的一部分中,而不是导入的类中。

首先,这里有点混乱。你几乎总是在模块或脚本的顶层进行导入,而不是在类中进行导入 - 在相同的代码中肯定是这种情况 - 因此没有“正在导入的类”。至于“导入的类”,Python实际上是导入模块,而不是类。是的,你可以从模块中导入一个类......但是谈论导入类仍然很困惑。另外,正如Mark Amery指出的那样,你有一个名为class_decision的模块这一事实意味着你相信类和模块之间必须存在紧密耦合,这在其他语言中可能是正确的,但在Python中则不然。有一个像这样的名字的模块几乎没有充分的理由。

但我想我理解这个问题:在class_decision.Decision.user_text中,您希望动态调用main_compositor.Main_Compositor.left_door()main_compositor.Main_Compositor.right_door(),而无需导入main_compositor

事实上,您希望它与任何Compositor对象一起使用,无论它是否为Main_Compositor

这样做的一种方法 - 就像Eric的回答一样 - 是将“动作”从Decision方法移动到调用者。只需报告(通过return)应采取的操作,并让调用者采取该操作。

但是如果你想编写一个可以与几十个不同的合成器类中的任何一个一起使用的泛型Decision,你不希望在这些类的每一个中复制if choice == "left"…逻辑。

请记住,每当您尝试制作更通用或抽象的内容时,您就会更难以编写和思考。如果你实际上并不需要这种灵活性,请不要写它 - 使用Eric的答案,或者只将两个类合并为一个。

但是如果你需要Decision.user_text是通用的,并且对任何称为它的合成器采取行动,你是如何做到的?

嗯,在Python或其他大多数语言中都没有“叫我的对象”的概念。有人必须告诉方法要与之交谈的对象。调用方法将对self的引用传递给user_text,或者包含对象将对self的引用传递给Decision构造函数。这通常被称为“后退指针”(因为在较旧的语言中它实际上是一个指针,但在Python中则不相关)。

一旦你知道要与之交谈的对象,与它交谈是微不足道的。如果你习惯了像C ++或Java这样的静态语言,那就不是真的了 - 你必须做一些棘手的事情,比如定义一个所有合成器必须支持的接口,或者使用反射(如getattr)来按名称查找方法。但Python不是静态的;如果你有一个对象,那应该支持某种方法,你可以在它上面调用该方法。

实际上,您可以从方法调用语法中看到它的两面:something.right_door()。您需要something个对象,否则您无法调用该方法;一旦你拥有了它,没有什么比调用方法更能调用方法了。

那么,您如何决定是将合并器传递给Decision对象的构造函数,还是每次调用user_text?这是基本类设计的一部分:Decision的每个实例在其整个生命周期中是否都在单个合成器上工作?然后在构造函数中传递它。如果没有,请在方法调用中传递它。

以下是后者的样子:

class Main_Compositor(object):
    ...
    def comp_door(self):
        self.door_decision.user_text(self)

class Decision(object):

    def user_text(self, compositor):
        print "which door do you open:"
        print "left or right?"

        door = raw_input("> ")

        if door == "left":
            print "you have chosen the left door"
            compositor.left_door()
        elif door == "right":
            print "you have chosen the right door"
            compositor.right_door()
        else:
            print "you must choose a door"
            self.user_text()

如果要将后指针存储为Decision的一部分,则如下所示:

class Main_Compositor(object):

    def __init__(self):
        # using composition to call the function of the imported class
        self.door_decision = Decision(self)

    ...

class Decision(object):

    def __init__(self, compositor):

        self.compositor = compositor

    def user_text(self):
        print "which door do you open:"
        print "left or right?"

        door = raw_input("> ")

        if door == "left":
            print "you have chosen the left door"
            self.compositor.left_door()
        elif door == "right":
            print "you have chosen the right door"
            self.compositor.right_door()
        else:
            print "you must choose a door"
            self.user_text()

这里要记住的一件事是,它可能会混淆哪个对象是这里的所有者,以及哪个对象具有后向引用。除了混淆人类读者之外,你甚至可以混淆解释器,导致内存泄漏。 (您可能需要查看weakref ...)这是灵活性的代价之一。

值得注意的是,在您的示例中,实际上有一个可以使用的全局变量。但这通常不是一个好的设计。在这种特定的情况下,使用全局变量没有额外的灵活性 - 只能有一个合成器 - 所以你没有通过使Decision更复杂而获得任何东西。