Как я должен передавать переменные между функциями в этом классе? - PullRequest
0 голосов
/ 29 ноября 2018

Что я пытаюсь сделать: выполняя скрипт, мне нужно будет набрать два числа, и он сравнит их.Я хочу, чтобы меня спросили всего 3 раза.В первый раз я наберу 10 и 5, второй раз 5 и 10, а в третий раз я наберу 10 и 10, чтобы получить все три возможных ответа.

Моя проблема с первым кодом: getnumbers() вызывается внутри Checknumbers().Я хочу создавать функции и цикл и строго выполнять ТОЛЬКО функции внутри выделенного цикла, а не внутри другой функции.

Я хочу, чтобы все было чисто вырезано и никаких ссылок на какие-либо функции внутри другой функции, я не хочуиспользовать любые глобальные переменные либо.

Я решил это с помощью класса, но я не совсем уверен, убиваю ли я язык или это обычная практика.Также я должен ссылаться на класс внутри функции checknumbers().

Первое решение:

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 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 из функции getnumbers() неизвестны для checknumbers.

Требование: у меня не может быть никаких ссылок на любые другие функции внутри моих функций, как я могу передать 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

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Если вы не хотите вызывать getnumbers() в пределах checknumbers(), единственная альтернатива, которая имеет смысл, состоит в том, чтобы передать числа в качестве параметров 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)

По крайней мере, имеетлучшее разделение интересов.

0 голосов
/ 29 ноября 2018
  • Вы путаетесь между классами и экземплярами, а также между атрибутами класса и атрибутами экземпляра .(Прочтите, например, this )
    • OO способ хранить переменные состояния (например, x, y), чтобы вам не приходилось передавать их между вызовами функций (/ методов), это сделатьих атрибуты экземпляра .(Не атрибуты класса, как вы делали. Не волнуйтесь, я тоже так делал, когда впервые изучал Python).
    • Итак, мы объявляем класс UI;мы получим доступ к его атрибутам экземпляра как self.x, self.y внутри его методов.
    • Не пытайтесь напрямую что-то делать с интерфейсом класса.Сначала вы должны создать его экземпляр: ui = UI().Вы должны следовать соглашению Python, что имена классов - это Uppercase / CamelCase: UI, имена экземпляров строчные, например ui, ui1, ui2...
    • Вы пытались поместить код непосредственно в определение класса UI, а не определять методы ипоместите код в него, и ваш класс пользовательского интерфейса даже не имеет __init__()
    • Методы являются функциями внутри класса, они всегда имеют первый аргумент self.Если бы они этого не сделали, метод не смог бы получить доступ к остальной части класса (!)
  • Теперь, когда мы это выяснили, есть несколько способов разложитьметоды, чтобы сделать то, что вы хотите сделать:
    1. иметь пустой __init__() (вы можете просто заставить его тело делать pass).Пусть get_numbers() и check_numbers() будут отдельными методами, которые вы вызываете по очереди вручную.Это то, что я покажу ниже, и оно наиболее близко к тому, что вы сказали, что хотите ( «Я не хочу ссылаться на какую-либо функцию внутри другой функции» * ), но это плохая декомпозиция - что если клиент вызывал check_numbers() раньшеget_numbers()?Это вызовет ошибку TypeError, поскольку __init__() инициализирует x, y с помощью None.
    2. Лучше было бы __init__() вызвать метод get_numbers() под капотом, чтобы гарантировать, что экземпляр будет правильно инициализирован.(Мы всегда можем позвонить get_numbers() еще раз позже, если мы хотим ввести новые номера).Это легко изменить, я оставляю это вам.
    3. В подходе 1. мы должны были инициализировать элементы экземпляра для что-то (в противном случае попытка доступа к ним в check_numbers() взорвется).Таким образом, мы инициализируем None, что намеренно выдает исключение, если мы сравним.На самом деле это не имеет значения, это просто плохая декомпозиция, чтобы не __init__() правильно инициализировать экземпляр (и вызывать любые методы, которые ему нужны, чтобы это сделать).Вот почему подход 2. лучше.Обычно у вас всегда должен быть __init__(), который инициализирует класс в известное состояние, чтобы можно было безопасно вызывать любой другой метод.

Код:

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 = 0, while(n < 3) ... n += 1.Цикл for является однострочным: for n in range(3):
  • Хороший стиль Python (см. PEP-8) должен называть методы lower_case_with_underscores, таким образом get_numbers(), check_numbers()
  • отличный нисходящийЧтобы спроектировать класс, сначала наберите сигнатуры его методов, подумайте, какие методы и атрибуты вам понадобятся и как они будут работать вместе .Пример: «get_numbers() получит пользовательский ввод, поэтому нам понадобятся атрибуты self.x,y для хранения номеров, чтобы check_numbers() мог получить к ним доступ».И таким образом вы должны столкнуться с любыми проблемами в дизайне классов, прежде чем писать стену кода.
0 голосов
/ 29 ноября 2018
  • Я не вижу ничего плохого в первом решении (за исключением того факта, что getumbers возвращает строки в Python 3).Классы не являются решением для каждой проблемы

  • У меня не может быть ссылок на любые другие функции внутри моих функций, как я могу передать x и y без ссылки на них?

    Невозможно передать что-то без ссылки на это.Даже если бы x и y были глобальными переменными (что намного хуже, чем ваш текущий дизайн), функция using должна была бы ссылаться на них.

Я не понимаю, почему у вас сложилось впечатление, что вызов функции внутри другой функции плохой или неправильный дизайн.

...