Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 29, 2019 15:59:48

Babay82
Зарегистрирован: 2019-02-19
Сообщения: 39
Репутация: +  0  -
Профиль   Отправить e-mail  

Требуется оценка.

Изучаю язык(да и в принципе программирование) по книге М.Доусона. Дошли до ООП. В частности на данный момент изучил главу о создании классов. Как обычно в конце главы задания. Вот авторский код (программа “Виртуальный питомец”):

 class Critter(object):
    """Питомец"""
        
    def __init__(self, name, hanger = 0, boredom = 0):
        self.name = name
        self.hanger = hanger
        self.boredom = boredom
        
    def __pass_time(self):
        self.hanger += 3
        self.boredom += 3
        
    @property
    def mood(self):
        unhappiness = self.hanger + self.boredom
        if unhappiness < 5:
            m = "Зашибись"
        elif 5 <= unhappiness <= 10:
            m = "Норм"
        elif 11 <= unhappiness <= 15:
            m = "Не очень"
        elif 16 <= unhappiness <= 20:
            m = "Хреново"
        return m
    
    def talk(self):
        print("Привет, я",self.name, ",сейчас я чувствую себя ", self.mood, "\n")
        self.__pass_time()
        
    def eat(self, food = 4):
        food = acquaintance("Сколько корма вы хотите дать питомцу?")
        print("Мрр...Спасибо!:)")       
        self.hanger -= food
        if self.hanger < 0:
            self.hanger = 0
        self.__pass_time()
        
    def play(self, fun = 4):
        fun = acquaintance("Сколько времени вы потратите на игру с питомцем?")
        print("Wowww!!!")       
        self.boredom -= fun
        if self.boredom < 0:
            self.boredom = 0
        self.__pass_time()
def main():
    crit_name = input("Дайте имя вашему питомцу:")
    crit = Critter(crit_name)
    choice = None
    while choice != "0":
        print("""
                Тамагочи                
                0 - Выйти
                1 - Поговорить с питомцами
                2 - Покормить питомцев
                3 - Поиграть с питомцами
                """)
        choice = input("Ваш выбор:")
        print()
        if choice == "0":
            print("До свидания")
        elif choice == "1":
            crit.talk()
        elif choice == "2":
            crit.eat()
        elif choice == "3":
            crit.play()
        else:
            print("Такого пункта в меню нет")                            
main()
input("Push Enter for Exit")
По заданию нужно дать возможность пользователю решать сколько давать еды или тратить время на игру, создать чит чтобы пользователь мог выводить числовые атрибуты питомца, и расширить программу до зоофермы , т.е. создать несколько питомцев, чтобы пользователь мог с помощью пункта в меню выбирать действие которое можно делать со всеми питомцами сразу (покормить, поиграть, поговорить). И чтобы при инстанцировании у питомцев уровни голода и уныния назначались в рандомном порядке.
От себя добавил возможность узнать количество, продать, и произвести действия с каждым питомцем по отдельности. У автора правильность выполнения задания узнать не могу по известным причинам, спрашиваю вас.
Вот, собственно, код:
 import random
class Critter(object):
    """Питомец"""
    pets = []
    total = 0
    pets_names = []
    @staticmethod
    def status():
        print("Всего питомцев сейчас", Critter.total)
    @staticmethod
    def all_eat():
        for i in Critter.pets:
            i.eat()
    @staticmethod
    def all_play():
        for i in Critter.pets:
            i.play()
    @staticmethod
    def all_talk():
        for i in Critter.pets:
            i.talk()
        
    def __init__(self, name, hanger = random.randrange(1, 15), boredom = random.randrange(1, 15)):
        self.name = name
        self.hanger = hanger
        self.boredom = boredom
        Critter.pets.append(self)
        Critter.total += 1
        Critter.pets_names.append(name)
        self.talk()
        
    def __str__(self):
        rep = "Объект класса Critter\n"
        rep += "имя:" + self.name +"\n"
        rep += "голод:" + str(self.hanger) +"\n"
        rep += "печаль:" + str(self.boredom) +"\n"        
        return rep
    
    def sale(self):        
        print("Ваш питомец", self.name, "продан")
        Critter.pets.remove(self)
        Critter.pets_names.remove(self.name)
        Critter.total -= 1
        
    def __pass_time(self):
        self.hanger += 3
        self.boredom += 3
        
    @property
    def mood(self):
        unhappiness = self.hanger + self.boredom
        if unhappiness < 5:
            m = "Зашибись"
        elif 5 <= unhappiness <= 10:
            m = "Норм"
        elif 11 <= unhappiness <= 15:
            m = "Не очень"
        elif 16 <= unhappiness <= 20:
            m = "Хреново"
        return m
    
    def talk(self):
        print("Привет, я",self.name, ",сейчас я чувствую себя ", self.mood, "\n")
        self.__pass_time()
        
    def eat(self, food = 4):
        food = acquaintance("Сколько корма вы хотите дать питомцу?")
        print("Мрр...Спасибо!:)")       
        self.hanger -= food
        if self.hanger < 0:
            self.hanger = 0
        self.__pass_time()
        
    def play(self, fun = 4):
        fun = acquaintance("Сколько времени вы потратите на игру с питомцем?")
        print("Wowww!!!")       
        self.boredom -= fun
        if self.boredom < 0:
            self.boredom = 0
        self.__pass_time()
def pet_instanse():
    crit_name = None
    while not crit_name:
        crit_name = input("Дайте имя вашему питомцу"). title(). strip()
    crit = Critter(crit_name)
    return crit
def acquaintance(question):
    response = None
    while response not in range(10):
        print("Введите значение от 0 до 9")
        try:
            response = int(input(question))
        except (TypeError, ValueError):
            print("Недопустимый ввод")
                    
    return response
def main():
    
    choice = None
    while choice != "0":
        print("""
                Тамагочи
                
                999 - Завести питомца
                0 - Выйти
                000 - Количество питомцев
                111 - Поговорить с питомцами
                222 - Покормить питомцев
                333 - Поиграть с питомцами
                555 - Выбрать питомца
                """)
        choice = input("Ваш выбор:")
        print()
        if choice == "0":
            print("До свидания")
        elif choice == "999":
            new_pets = pet_instanse()
        elif choice == "123":        
            for i in Critter.pets:
                print(i)
        elif choice == "000":
            Critter.status()
        elif choice == "111":
            Critter.all_talk()
        elif choice == "222":
            Critter.all_eat()
        elif choice == "333":
            Critter.all_play()
        elif choice == "555":
            new_pets = input("Введите имя питомца").title() .strip()
            if new_pets not in Critter.pets_names:
                print("Такого питомца у вас нет!")
            else:    
                for i in Critter.pets:
                    if new_pets == i.name:
                        print("""
                            1 - Узнать самочувствие
                            2 - Покормить питомца
                            3 - Поиграть с питомцем
                            4 - Продать питомца
                            """)
                        choice = input("Ваш выбор:")
                        if choice == "1":
                            i.talk()
                        elif choice == "2":
                            i.eat()
                        elif choice == "3":
                            i.play()
                        elif choice == "4":   
                            i.sale()
                            Critter.status()
                        else:
                            print("Такого пункта в меню нет")
                               
        else:
            print("Такого пункта в меню нет")
        
main()
input("Push Enter for Exit")
И сразу вопрос, почему в конструкторе, при инстанцировании каждого питомца уровни голода и уныния выбираютя случайно, но у всех одинаковые. т.е. при каждом запуски программы они разные, но одинаковые при создании у всех питомцев, пробовал и randint и randrange , результат тот-же, так и не понял в чем причина?

Офлайн

#2 Апрель 29, 2019 17:00:31

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

Требуется оценка.

Babay82
И сразу вопрос, почему в конструкторе, при инстанцировании каждого питомца уровни голода и уныния выбираютя случайно, но у всех одинаковые. т.е. при каждом запуски программы они разные, но одинаковые при создании у всех питомцев, пробовал и randint и randrange , результат тот-же, так и не понял в чем причина?
Как я понимаю, при обработке def __init__ сразу подставляются конкретные результаты вызова указанных функций и помещаются в поле __defaults__ соответствующего объекта (ссылающегося на метод). Набросал для проверки такой код:
 s = "abc"
def get_str():
    return s
def change_str(new_s=get_str()):
    global s
    print("new_s =", new_s)
    s = "123"
if __name__ == "__main__":
    change_str()
    print("s =", get_str())
    change_str()
    print("s =", get_str())
    print(change_str.__defaults__)
На скрине - результат работы, т.е. новое значение при повторном вызове уже не подставляется - используется уже заданное __defaults__

Прикреплённый файлы:
attachment pycharm64_2019-04-29_16-59-44.jpg (176,3 KБ)

Офлайн

#3 Апрель 30, 2019 02:23:21

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10024
Репутация: +  857  -
Профиль   Отправить e-mail  

Требуется оценка.

Babay82
Изучаю язык(да и в принципе программирование) по книге М.Доусона. Дошли до ООП.
Это не ООП.

Babay82
Требуется оценка.
Детский лепет. (Простые функции неправильно пишешь.)

ООП - это очень сложная парадигма. Суть в том, что ты строишь модель, которая состоит из объектов, пересылающих друг другу сообщения. Все сообщения они пересылают друг другу одновременно. Множества объектов собираются в классы объектов и у классов относительно друг друга выстраивается иерархия в соответствии с разными, хорошо отделёнными друг от друга уровнями абстракции. Естественно, для этого надо понимать “а как понять, что сложная система правильно поделена на уровни?”. Если система неправильно поделена, то это будет такое болото или каша из объектов, которые, естественно, невозможно будет объединить в модель. Это я тебе вкратце рассказал, чтобы ты понимал, что ты вообще не в ООП. А там ещё и про каждый элемент этой парадигмы есть куча нюансов, которые надо знать и видеть.

Так вот, до парадигмы ООП надо освоить парадигму СП - структурное программирование. То есть ты должен понимать, как вообще выстраивать структуру модулей: что такое модуль; как писать функции; как писать функции, вызывающие другие функции, вызывающие другие функции. Там тоже немало всякой теории, естественно, не бесполезной, а применяемой постоянно.

Просто когда ты пишешь метод у класса, он пишется-то по правилам СП. Какие аргументы ему сделать, сколько их и должны ли у них быть значения по умолчанию, - это всё понятия из СП. ООП к этому никаким боком, оно только занимается полиморфизмом самой функции (по аргументам принимается решение, какой вариант функции вызвать из нескольких). Мало того, есть ООП (объектно-ориентированное программирование), а есть ОП (объектное программирование) и они различаются наличием иерархии у классов. Естественно, в зависимости от этого и пишется там по-разному всё. Есть ещё программирование с абстрактными типами данных, там тоже пишется слово class, но это вообще не объекты, а просто типы, чуть более сложные, чем простые встроенные. Соответственно, сделать из них общающиеся между собой объекты не получится - не та парадигма.

Так что ты пытаешься взять высоту в пять метров с шестом, когда даже без шеста перепрыгнуть метровую перекладину не можешь.



Отредактировано py.user.next (Апрель 30, 2019 02:32:23)

Офлайн

#4 Апрель 30, 2019 11:27:18

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2849
Репутация: +  186  -
Профиль   Отправить e-mail  

Требуется оценка.

py.user.next Не пугай ребёнка!



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#5 Май 1, 2019 04:11:06

Babay82
Зарегистрирован: 2019-02-19
Сообщения: 39
Репутация: +  0  -
Профиль   Отправить e-mail  

Требуется оценка.

py.user.next
Это не ООП.
Естественно! К самому ООП ещё и не приступали. Прошёл только главу которая была посвящена созданию классов. После неё задание. По нему собственно и был вопрос.
py.user.next
Детский лепет. (Простые функции неправильно пишешь.)
Ахрененный ответ. Спасибо, я сразу многое понял. Вы так подробно всё обьяснили!!!

Офлайн

#6 Май 1, 2019 06:11:57

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10024
Репутация: +  857  -
Профиль   Отправить e-mail  

Требуется оценка.

Babay82
я сразу многое понял
Ты ничего не понял. Хочешь подробностей - ну ладно. Твой код не то что в ООП плох, он даже в простейших вещах плох. Почему он плох в простейших вещах - потому что ты не знаешь азов программирования.

Функции не чистые, с побочными эффектами.
Функции не общего вида, а привязанные к фиксированным значениям.
Магические числа, разбросанные внутри функций.
Функции называются не императивно.

Вот с чего вдруг у тебя play() и eat() связаны максимальным количеством единиц? Допустим, я хочу покормить его не более 20-ю единицами еды, а поиграть с ним не более 10-и единиц по времени. Да, вот хочу иметь и такую возможность, и такую возможность одновременно. Мы видим, что проблема в функции acquaintance() - она просто держит ограничения, изначально взятые с потолка (писалась она явно не для этого применения). И как мы это можем исправить, чтобы получить разные возможности в кормёжке и игре? Значит, мы должны написать вторую функцию, чтобы рассоединить эти диапазоны или же использовать какую-то одну общую функцию, подавая в неё просто разные аргументы границ при вызове.
  
food = acquaintance("Сколько корма вы хотите дать питомцу?", 0, 20)
  
fun = acquaintance("Сколько времени вы потратите на игру с питомцем?", 0, 10)
И что нужно сделать для этого? Надо написать функцию acquaintance() в общем виде - где через аргументы можно ставить границы. То есть нужно сделать то, что описано во всех классических учебниках. Так она ещё и названа неправильно: она называется “знакомство”, а ты используешь её для ввода количества еды, количества времени и ещё хрен знает для чего (в будущем тебя ещё что-нибудь может осенить точно так же). Лучше бы она называлась ask_for_number() - “запросить число” и благодаря этому имени подходила бы ко всем ситуациям, так ещё бы и было понятно по её названию, что именно она делает (какой результат будет возвращён из неё).

Откуда у тебя эти пробелы? Ну вот оттуда. Ты не изучал это всё. То есть ты не изучал то, что нужно тебе уже сейчас.



Отредактировано py.user.next (Май 1, 2019 06:24:05)

Офлайн

#7 Май 4, 2019 12:17:02

Babay82
Зарегистрирован: 2019-02-19
Сообщения: 39
Репутация: +  0  -
Профиль   Отправить e-mail  

Требуется оценка.

py.user.next
Вот с чего вдруг у тебя play() и eat() связаны максимальным количеством единиц?
Да потому что они изначально связаны связаны параметром unhappynes и методом __pass_time(self), это изначальная задумка игры, есть разброс 9 ед, хочешь 1 дай хочешь 9. Таковы правила.
py.user.next
Функции не чистые, с побочными эффектами.
Функции не общего вида, а привязанные к фиксированным значениям.
Магические числа, разбросанные внутри функций.
Функции называются не императивно.
Функция написанная мной здесь всего одна, и да, с названием я тут действительно прое…ся, т.к. эта функция взята из другого кода, и исправлена для этого.
Так что в ней не так, какой побочный эффект, какие магические числа?
Я для этого на форум и обратился , потому что в реале мне спросить не кого, а книга , учебник мне не ответит. Или ты на форуме для новичков чтобы ядом поплеваться, типа “хуйня переделывай”. Так я это и без тебя знаю , что хуйня!

Офлайн

#8 Май 4, 2019 12:31:02

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Требуется оценка.

Babay82
Так что в ней не так, какой побочный эффект, какие магические числа?
Babay82, вы так далеко то не уедете. Вам дали подсказки - вперед гуглить, вы не в школе, “учить” вас никто не будет.

Вот смотрите
Вторая ссылка в гугле

Первая ссылка в гугле



Офлайн

#9 Май 4, 2019 13:44:33

Babay82
Зарегистрирован: 2019-02-19
Сообщения: 39
Репутация: +  0  -
Профиль   Отправить e-mail  

Требуется оценка.

FishHook
Спасибо.
Так в том то и дело, чисел в ней никаких нет вообще, и функция служит для того , что бы обработать правильность ввода пользователя, чем она не чистая? Она не вносит каких либо изменений в программу, принимая значение одно и то же значение от пользователя она всегда возвратит один и тот же результат, она не зависит ни от каких внешних данных. Побочный эффект? То что она взаимодействует с консолью? Так она для этого и предназначена. Вроде в Python(да и не только) не всегда есть возможность писать только чистые функции? Так что с ней конкретно так ужасно, кроме названия(которое как я уже объяснял осталось от прежней программы, да тут затупил, просмотрел)?

Офлайн

#10 Май 4, 2019 14:30:41

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Требуется оценка.

Babay82

Babay82
Так в том то и дело, чисел в ней никаких нет вообще
Ну во-первых, вы видимо как-то не очень внимательно прочитали данные вам ссылки, иначе вы бы понимали, что “числа” в данном случае понятие условное, так же как “звездное небо” не состоит исключительно из звезд в астрономическом понимании. Во-вторых, именно магические числа у вас таки есть.
     def __pass_time(self):
        self.hanger += 3
        self.boredom += 3
Что это за тройка? Можно ли это понять, не изучая подробно алгоритм? Будет ли логической ошибкой первую тройку изменить на четверку, а вторую нет? А если ваш код будет тысяч на пять строк, можно ли разобраться, что тройка в сотой строке и тройка в трехтысячной - это одна и та же константа и их нужно изменять одновременно? Могут ли эти числа быть нецелыми? А отрицательными? Ваш код это никак не документирует, поэтому числа “магические”. Их нужно сделать именованными константами.

Где py.user.next увидел побочки я не нашел, на мой взгляд вы зря затеяли возню со статическими методами. Это в данном случае чужеродно выглядит. Сделайте отдельный класс для набора питомцев и оперируйте объектом этого класса.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version