我制作了一个模块原型,目的是在python中构建复杂的计时器计划。类原型模拟Timer对象,每个对象具有等待时间,重复对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!"
答案 0 :(得分:5)
基于鸭子的打字方法很好。如果您希望能够检查某个给定的类是否应该在您的框架中运行,那么您可以使用Abstract Base Classes(需要Python 2.6)。 PEP 3119声明:
[...]有许多不同的方法来测试对象是否符合特定协议。例如,如果询问“这个对象是一个可变序列容器吗?”,可以查找“list”的基类,或者可以查找名为“ getitem ”的方法。但请注意,尽管这些测试看似显而易见,但它们都不正确,因为一个产生假阴性,另一个产生假阳性。[...]本PEP提出了一种特殊的策略来组织这些测试,称为抽象基类,或者ABC。 ABCs只是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):
...
重要的一点是,也可以将其他类(您可能无法控制,因为您没有编写它们)注册为runnables,并且isinstance
和issubclass
方法将反映:
>>> issubclass(SomeOtherClass, Runnable)
False
>>> Runnable.register(SomeOtherClass)
>>> issubclass(SomeOtherClass, Runnable)
True
答案 1 :(得分:3)
这称为duck typing,它一直在Python 中使用。
答案 2 :(得分:2)
它确实一直使用,非常好。如果您想要非常小心,可以使用hasattr
来确保您期望拥有run
方法的对象实际上很早就有了。这有助于确保异常尽可能接近错误点。
但除此之外,它很好并经常完成。