当您希望创建派生的单例时,使用Python模块的替代方案
在Python项目中,我需要为用户提供各种概念的单个实例,让我们称它们为“狗”、“猫”和“鹦鹉”。它们有一些共同的功能,比如sleep()、eat()和is_dead(),为了代码重用的目的,我想把它们放在“pet”的概念中。可以有多只宠物,但每种类型只有一只宠物 我相信Python模块不可能从另一个模块继承,因此如果我只想使用模块,我就必须抛弃“宠物”概念,在每个“狗”、“猫”和“鹦鹉”模块中重复代码(睡眠、进食等)。或者创建一个“宠物”模块,然后在其他每个模块中使用“从宠物导入*”,据我所知,这被认为是不好的做法 或者,我可以创建一个“pet”类(从实现基类的单例派生),然后从中派生“dog”、“cat”和“parrot”类。然而,我看到大多数关于Python中单例模式的讨论都暗示该模式不是一个好主意 因此,我想避免我印象中的三个方面是不好的做法:当您希望创建派生的单例时,使用Python模块的替代方案,python,design-patterns,inheritance,singleton,Python,Design Patterns,Inheritance,Singleton,在Python项目中,我需要为用户提供各种概念的单个实例,让我们称它们为“狗”、“猫”和“鹦鹉”。它们有一些共同的功能,比如sleep()、eat()和is_dead(),为了代码重用的目的,我想把它们放在“pet”的概念中。可以有多只宠物,但每种类型只有一只宠物 我相信Python模块不可能从另一个模块继承,因此如果我只想使用模块,我就必须抛弃“宠物”概念,在每个“狗”、“猫”和“鹦鹉”模块中重复代码(睡眠、进食等)。或者创建一个“宠物”模块,然后在其他每个模块中使用“从宠物导入*”,据我所知
- 不同源文件之间的代码复制
- “from x import*”的使用
- 单例设计模式的使用
class Pet():
def __init__(self):
self._type = "Generic pet"
def sleep(self):
print self.type, "is sleeping"
文件dog.py
import pet
class Dog(pet.Pet):
number_of_dogs = 0
def __init__(self):
if (Dog.number_of_dogs != 0):
raise Exception("Grrrr...")
pet.Pet.__init__(self) # assuming no diamond inheritance of animals
self.type = "The Dog"
Dog.number_of_dogs = 1
def Bark(self):
print "Woof"
提示符>python
>>> import pet
>>> import dog
>>> c = dog.Dog()
>>> d = dog.Dog()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "dog.py", line 8, in __init__
raise Exception("Grrrr...")
Exception: Grrrr...
>>> c.sleep()
The Dog is sleeping
>>> c.Bark()
Woof
>>>
>>导入宠物
>>>进口狗
>>>c=狗。狗()
>>>d=狗。狗()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“dog.py”,第8行,在init中__
引发异常(“Grrrr…”)
例外:Grrrr。。。
>>>c.睡眠()
狗在睡觉
>>>c.树皮()
汪汪
>>>
我将遵循一些编写良好的教程,并结合有必要摆脱将类实例视为生成可与之交互的继承结构的唯一方法的想法:可以使用类方法(而不仅仅是实例方法)创建类
因此,可以根据需要创建继承结构,其中狗
、猫
和鹦鹉
继承自宠物
。然后,通过使用classmethods而不是实例方法,可以在不实例化的情况下与这些类进行交互,因此不需要任何单例模式。如果需要任何状态,则可以使用类属性在类级别保持该状态
classmethods的使用有很好的文档记录
例如:
class Pet(object):
@classmethod
def is_dead(cls):
return False
class Dog(Pet):
@classmethod
def bark(cls):
print "woof"
if __name__ == "__main__":
if not Dog.is_dead():
Dog.bark()
用你的例子来说有点难,但是这些是否真的需要是单独的实例呢?它们可能是共享动物超类上的类方法吗?为什么不创建共享类的实例呢
dog=Pet(…)
则是模块中的全局变量。您总是可以将附加功能附加到该实例。虽然建议不要使用宠物导入的*
,但宠物导入的狗、猫、鹦鹉的则不是。根据我的经验,大多数人接触单身人士都是过度设计了他们的问题。在Python中,如果有人通过创建多个单例类实例来攻击自己,这不是您的问题。只需创建Pet
、Cat
、Dog
和Parrot
类,分别创建后三个类的一个实例,并使用这些实例记录API。如果必须在创建实例后立即使用del Cat、Dog、Parrot
,以防止轻松导入,通常只需使用即可。是的,或者从Pet生成子类,只使用类而不是实例@那么classmethod就是你的朋友了。