Классы, методы и полиморфизм в Python - PullRequest
3 голосов
/ 25 января 2010

Я сделал прототип модуля с целью построения сложных расписаний таймеров в python. Прототипы класса эмулируют объекты Timer, каждый со своим временем ожидания, объектами Repeat, которые группируют Timer и другие объекты Repeat, и класс Schedule, только для хранения всей конструкции или экземпляров Timers и Repeat. Конструкция может быть настолько сложной, насколько это необходимо, и должна быть гибкой.

Каждый из этих трех классов имеет метод .run(), позволяющий пройти весь график. Независимо от класса, метод .run() запускает таймер, группу повторов для определенного числа итераций или расписание.

Этот подход, ориентированный на полиморфизм, звучит или глупо? Какие еще подходящие подходы я должен рассмотреть, чтобы создать такую ​​универсальную утилиту, которая позволила бы объединить все строительные блоки настолько сложным способом, насколько это необходимо с простотой?

Спасибо!

Вот код модуля:

#####################
## Importing modules

from time import time, sleep


#####################
## Class definitions

class Timer:
    """
    Timer object with duration.

    """
    def __init__(self, duration):
        self.duration = duration
    def run(self):
        print "Waiting for %i seconds" % self.duration
        wait(self.duration)
        chime()

class Repeat:
    """
    Repeat grouped objects for a certain number of repetitions.

    """
    def __init__(self, objects=[], rep=1):
        self.rep = rep
        self.objects = objects
    def run(self):
        print "Repeating group for %i times" % self.rep
        for i in xrange(self.rep):
            for group in self.objects:
                group.run()

class Schedule:
    """
    Groups of timers and repetitions. Maybe redundant with class Repeat.

    """
    def __init__(self, schedule=[]):
        self.schedule = schedule
    def run(self):
        for group in self.schedule:
            group.run()

########################
## Function definitions

def wait(duration):
    """
    Wait a certain number of seconds.

    """
    time_end = time() + float(duration) #uncoment for minutes# * 60
    time_diff = time_end - time()
    while time_diff > 0:
        sleep(1)
        time_diff = time_end - time()

def chime():
    print "Ding!"

Ответы [ 3 ]

5 голосов
/ 25 января 2010

Подход, основанный на типизировании утки, хорош. Если вы хотите проверить, должен ли данный класс работать в вашей среде, вы можете использовать Абстрактные базовые классы (требуется Python 2.6). PEP 3119 гласит:

[...] есть много разных способов проверить, соответствует ли объект определенному протоколу или нет. Например, если спрашивать «Является ли этот объект контейнером изменяемой последовательности?», Можно искать базовый класс «list» или метод « getitem ». Но обратите внимание, что хотя эти тесты могут показаться очевидными, ни один из них не является правильным, так как один генерирует ложные отрицания, а другие ложные положительные. [...] В этом PEP предлагается конкретная стратегия организации этих тестов, известная как абстрактные базовые классы, или ABC. ABC - это просто классы Python, которые добавляются в дерево наследования объекта, чтобы сообщать об определенных функциях этого объекта внешнему инспектору. Тесты выполняются с использованием isinstance (), и наличие определенного ABC означает, что тест пройден.

Вы можете реализовать ABC и использовать isinstance или issubclass, чтобы проверить, написаны ли классы или экземпляры для вашей платформы:

from abc import ABCMeta, abstractmethod

class Runnable(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def run(self):
        raise NotImplementedError

 class Schedule(Runnable):
     ...

Важным моментом является то, что можно также зарегистрировать другие классы (над которыми у вас может не быть контроля, потому что вы их не написали) в качестве исполняемых файлов, а методы isinstance и issubclass будут отражать, что:

  >>> issubclass(SomeOtherClass, Runnable)
  False
  >>> Runnable.register(SomeOtherClass)
  >>> issubclass(SomeOtherClass, Runnable)
  True
3 голосов
/ 25 января 2010

Это называется утка, печатающая , и она используется в Python все время .

2 голосов
/ 25 января 2010

Это действительно используется все время и прекрасно. Если вы хотите быть очень осторожным, вы можете использовать hasattr, чтобы убедиться, что объект, который вы ожидаете получить с помощью метода run, действительно имеет его довольно рано. Это помогает убедиться, что исключения генерируются как можно ближе к точке ошибки.

Но в остальном все нормально и часто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...