Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Изменение поля одного класса из метода другого

#python #ооп #инспекция_кода


Вот, помалу радую себя питоном. Бэкграунда 0, если что. 

Хочу понять, правильно ли я сделал. Есть два класса: веревка и нож. Есть один обьект
каждого класса. Веревка имеет длину, нож умеет отрезать веревку. 
Правильно ли я понял суть использования метода одного класса, изменяющего атрибут
другого? или это кривой детский код? благодарствую за советы, аноны

class Rope:
    length = 30
    def get_info(self):
        print("\n", "---"*8, "\n", "class Rope, get_info(): ", "\n",
        "Rope's length is %s meters" % self.length,
        "\n", "---"*8, "\n"
    )

class Knife:
    def cut_rope(self, length, a):
        print("Now we will cut %s meters off" % length)
        a.length -= length


rope = Rope()
knife = Knife()

rope.get_info()
knife.cut_rope(12, rope)
rope.get_info()


C:\Users\олег\Python34\classes>ex2.py

 ------------------------
 class Rope, get_info():
 Rope's length is 30 meters
------------------------

Now we will cut 12 meters off

------------------------
class Rope, get_info():
Rope's length is 18 meters

    


Ответы

Ответ 1



Как уже писал в комментарии, предлагаю делать верёвку иммутабельным объектом. А ещё максимально использовать встроенные методы. # coding=utf-8 class Rope: # зачем хардкодить длину верёвки? Лучше будем задавать её в конструкторе. def __init__(self, length): if length <= 0: raise ValueError('length should be > 0') self._length = length # сработает с методом len() def __len__(self): return self._length # а это сработает с str(), соответственно и с print def __str__(self): return "This rope's length is {0!s} meters".format(self._length) class Knife: # Полиморфизм! Ножу всё равно, что резать. На выходе должно быть два того же. # Если нарезаемое нельзя инициировать только по длине, задаваемой числом, будет ошибка. def cut(self, object, length): _class = object.__class__ # по-хорошему, тут ещё должны быть проверки, что length не None и что число # и, конечно, что object не None if len(object) < length: raise ValueError('cut length exceeds available length') elif len(object) == length: # даже для одного объекта мы возвращаем список, чтобы всегда был перечислимый (iterable) результат return [_class(len(object))] else: return [_class(len(object) - length), _class(length)] rope = Rope(30) knife = Knife() print rope for r in knife.cut(rope, 20): print r Вывод: This rope's length is 30 meters This rope's length is 10 meters This rope's length is 20 meters

Ответ 2



# -*- coding: UTF-8 -*- class Rope(str): def __init__(self, s: str): self.len = len(self) print("%s rope's length is %s meters" % (self, self.len)) def __getitem__(self, item: slice): return self.__class__(super().__getitem__(item)) class Knife: @staticmethod def cut(string: str, length: int): rope = Rope(string) yield from (rope, rope[:length], rope[length:]) print('{s} cut {}[{}] pos'.format(rope.len, length, s=rope)) if __name__ == '__main__': rope = '-qwertyuiop-' print([(r, r.len) for r in Knife.cut(rope, 5)]) out: -qwertyuiop- rope's length is 12 meters -qwer rope's length is 5 meters tyuiop- rope's length is 7 meters -qwertyuiop- cut 12[5] pos [('-qwertyuiop-', 12), ('-qwer', 5), ('tyuiop-', 7)]

Комментариев нет:

Отправить комментарий