我应该如何在这个 class 中的函数之间传递变量?

How should I pass variables between functions in this class?

我正在尝试做的事情: 执行脚本,我将不得不输入两个数字,它会比较它们。 我总共要被问 3 次。 第一次输入 10 和 5,第二次输入 5 和 10,第三次输入 10 和 10 以获得所有三个可能的答案。

第一个代码的问题是:getnumbers()Checknumbers() 内部被调用。 我想创建函数和循环并严格只在专用循环内执行函数,而不是在另一个函数内执行。

我希望一切都干净利落,不要在另一个函数中引用任何函数,我也不想使用任何全局变量。

我用 class 解决了这个问题,但我不确定我是在贬低语言还是这是常见的做法。我还必须在 checknumbers() 函数中引用 class。

第一个解决方案:

def getnumbers():
    x = input("Enter the X number: ")
    y = input("Enter the Y number: ")
    return x, y

def checknumbers():
    x, y=getnumbers()
    if   x > y:
        print(f'x is larger then y: x is {x} and y is {y}')
    elif y > x:
        print(f"y is larger then x: x is {x} and y is {y}")
    elif y == x:
        print(f"x is equal to y: x is {x} and y is {y}")     
    else:
        print("Dont know mate")


n = 0
while(n < 3):
    checknumbers()
    n += 1

这是 class 的变体:

class ui:
    x = input("Enter the X number: ")
    y = input("Enter the Y number: ")


def checknumbers():
    if   ui.x > ui.y:    
        print(f'x is larger then y: x is {ui.x} and y is {ui.y}')
    elif ui.y > ui.x:
        print(f"y is larger then x: x is {ui.x} and y is {ui.y}")
    elif ui.y == ui.x:
        print(f"x is equal to y: x is {ui.x} and y is {ui.y}")     
    else:
        print("Dont know mate")

n = 0
while(n < 3):
    checknumbers()
    n += 1

理想的解决方案,所以函数 getnumbers()checknumbers 都是完全独立的,并且它们在 while 循环内被调用,问题是 [= 中的 x 和 y checknumbers.

不知道 14=] 函数

要求是:我不能在我的函数中引用任何其他函数,我如何在不引用它们的情况下传递 x 和 y?:

def getnumbers():
    x = input("Enter the X number: ")
    y = input("Enter the Y number: ")
    return x, y

def checknumbers():
    if   x > y:
        print(f'x is larger then y: x is {x} and y is {y}')
    elif y > x:
        print(f"y is larger then x: x is {x} and y is {y}")
    elif y == x:
        print(f"x is equal to y: x is {x} and y is {y}")     
    else:
        print("Dont know mate")


n = 0
while(n < 3):
    getnumbers()
    checknumbers()
    n += 1
  • 我没有发现第一个解决方案有任何问题(除了 getumbers returns 字符串在 Python 3 中)。 类 并不是所有问题的解决方案

  • I cant have any reference of any other function inside my functions, how do I pass x and y without referencing them?

    不可能在不引用的情况下传递某些内容。即使 xy 是全局变量(这比您当前的设计差很多),using 函数也需要引用它们。

我不明白为什么你觉得在另一个函数中调用一个函数是不好的或错误的设计。

如果您不想在 checknumbers() 内调用 getnumbers(),唯一可行的方法是将数字作为参数传递给 checknumbers()

def getnumbers():
    x = int(input("Enter the X number: "))
    y = int(input("Enter the Y number: "))
    return x,y

def checknumbers(x, y):
    if x > y:
        # etc.

...

for _ in range(3):
    x,y = getnumbers()
    checknumbers(x,y)

那至少有更好的关注点分离。

  • 您混淆了 class 实体和实例,以及 class 属性和 实例属性 。 (阅读例如 this
    • 存储状态变量(如 x、y)以便您不必在函数(/方法)调用之间传递它们的 OO 方法是使它们成为 实例属性. (不是 class 属性,正如你所做的那样。别担心,我第一次学习 Python 时也是这样做的)。
    • 所以我们声明一个classUI;我们将在其方法中以 self.x, self.y 的形式访问其实例属性。
    • 不要尝试直接在 class UI 上做事。您必须首先实例化它:ui = UI()。您应该遵循 Python 约定,即 class 名称为 Uppercase/CamelCase: UI,实例名称为小写,例如ui, ui1, ui2...
    • 您试图将代码直接放入 UI 的 class 定义中,而不是定义方法并将代码放入其中,而您的 UI class 没有甚至没有 __init__()
    • 方法是 class 中的函数,它们总是有第一个参数 self。如果他们不这样做,该方法将无法访问 class(!)
    • 的其余部分
  • 现在我们已经清楚了,有几种方法可以分解方法来做你想做的事:
    1. 有一个空的 __init__()(你可以让它的主体做 pass)。让 get_numbers()check_numbers() 成为单独的方法,您可以按顺序手动调用它们。这是我在下面显示的内容,最接近您所说的内容 ("I want no reference to any function inside another function"),但分解效果不佳 - 如果客户在 get_numbers()?它会在 TypeError 上爆炸,因为 __init__() 使用 None.
    2. 初始化 x,y
    3. 更好的方法是让 __init__() 在后台调用方法 get_numbers() 以保证实例得到正确初始化。 (如果我们想输入新数字,我们总是可以稍后再次调用 get_numbers())。这个很容易改,就交给你了。
    4. 在方法 1. 中,我们必须将实例成员初始化为 something(否则尝试在 check_numbers() 中访问它们将会失败)。所以我们初始化为None,比较的话会故意抛出异常。这并不重要,这只是糟糕的分解,没有 __init__() 正确初始化实例(并调用完成该操作所需的任何方法)。这就是方法 2. 更好的原因。一般来说,你应该总是有一个 __init__() 将 class 初始化为已知状态,以便可以安全地调用任何其他方法。

代码:

class UI:
    def __init__(self, x=None, y=None):
        self.x = x
        self.y = y
    def get_numbers(self):
        self.x = input("Enter the X number: ")
        self.y = input("Enter the Y number: ")
    def check_numbers(self):
        """This is bad decomposition because if the client calls check_numbers() before get_numbers(), the NoneType will throw a TypeError"""
        if   self.x > self.y:    
            print(f'x is larger then y: x is {self.x} and y is {self.y}')
        elif self.y > self.x:
            print(f'y is larger then x: x is {self.x} and y is {self.y}')
        elif self.y == self.x:
            print(f'x is equal to y: x is {self.x} and y is {self.y}')     
        else:
            print("Don't know mate")

# Declare an instance and reuse it three times    
ui = UI()
for n in range(3):
    ui.get_numbers()
    ui.check_numbers()

此外,还有一些小的文体要点:

  • 对于简单的计数器,您不需要 while 循环:n = 0while(n < 3) ... n += 1。 for 循环是单行代码:for n in range(3):
  • good Python 风格(见PEP-8)是给方法命名lower_case_with_underscores,因此get_numbers(), check_numbers()
  • 设计 class 的一种自上而下的好方法是 首先编写其方法签名,考虑您需要哪些方法和属性以及它们如何协同工作。示例:“get_numbers() 将获取用户输入,因此我们需要属性 self.x,y 来存储数字,以便 check_numbers() 可以访问它们”。这样一来,您就可以在编写大量代码之前解决 class 设计方面的任何问题。