#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)]
Комментариев нет:
Отправить комментарий