Python 工厂动态实例化
Python factory dynamic instantiation
我是一名 C# 程序员,我正在寻找一个简单的工厂。观察appempt:
class ShapeFactory:
_registry: Dict[ShapeType, Shape] = {
ShapeType.Shape: lambda: Shape(),
ShapeType.Circle: lambda: Circle(),
ShapeType.Square: lambda: Square()
}
def Create(self, key: ShapeType) -> Shape:
if key in self._registry:
return self._registry.get(key)
raise KeyError(key)
def Register(self, key: ShapeType, value: Shape) -> None:
if key not in self._registry:
self._registry[key] = value
raise KeyError(type)
问题是 Create
总是 return 同一个实例,比如说 Circle
。如何在允许 OCP 的情况下实现动态实例化对象的方法?
编辑:
进一步扩展我的观点;在 C# 中,我会将我的字典声明为:
Dictionary<ShapeType, Func<Shape>> _registry = new Dictionary{
[ShapeType.Shape] = () => new Shape(),
[ShapeType.Circle] = () => new Circle(),
[ShapeType.Square] = () => new Square()
}
这将始终return 为字典的每个值创建一个新实例化的对象。这是我希望在 python.
中重现的效果
动态创建对象的一种简单的 pythonic 方式是:
class C:
def __init__(self):
self.name = "C"
class D:
def __init__(self):
self.name = "D"
dic = {"C": C, "D": D}
x1 = dic["C"]()
x2 = dic["C"]()
print(x1 is x2) #prints False
您在此设计中遇到了一些较大的问题。
首先,如果你在 class 中有一个可变属性,你应该在 class 的 __init__
方法中定义 _registry
(与实例隔离) .
接下来,_registry
的类型属性是错误的。您有 dict
个 lambda
个实例,而不是 Shape
个实例。你需要 Dict[ShapeType, Callable[[], Shape]]
。 Register
方法也有类似的问题。
您还应遵循 PEP 8 命名规则。试试这个:
class ShapeFactory:
def __init__(self) -> None:
self._registry: Dict[ShapeType, Callable[[], Shape]] = {
ShapeType.Shape: lambda: Shape(),
ShapeType.Circle: lambda: Circle(),
ShapeType.Square: lambda: Square()
}
def create(self, key: ShapeType) -> Shape:
if key in self._registry:
return self._registry[key]()
else:
raise KeyError(key)
def register(self, key: ShapeType, value: Callable[[], Shape]) -> None:
if key not in self._registry:
self._registry[key] = value
else:
raise KeyError(key)
我是一名 C# 程序员,我正在寻找一个简单的工厂。观察appempt:
class ShapeFactory:
_registry: Dict[ShapeType, Shape] = {
ShapeType.Shape: lambda: Shape(),
ShapeType.Circle: lambda: Circle(),
ShapeType.Square: lambda: Square()
}
def Create(self, key: ShapeType) -> Shape:
if key in self._registry:
return self._registry.get(key)
raise KeyError(key)
def Register(self, key: ShapeType, value: Shape) -> None:
if key not in self._registry:
self._registry[key] = value
raise KeyError(type)
问题是 Create
总是 return 同一个实例,比如说 Circle
。如何在允许 OCP 的情况下实现动态实例化对象的方法?
编辑: 进一步扩展我的观点;在 C# 中,我会将我的字典声明为:
Dictionary<ShapeType, Func<Shape>> _registry = new Dictionary{
[ShapeType.Shape] = () => new Shape(),
[ShapeType.Circle] = () => new Circle(),
[ShapeType.Square] = () => new Square()
}
这将始终return 为字典的每个值创建一个新实例化的对象。这是我希望在 python.
中重现的效果动态创建对象的一种简单的 pythonic 方式是:
class C:
def __init__(self):
self.name = "C"
class D:
def __init__(self):
self.name = "D"
dic = {"C": C, "D": D}
x1 = dic["C"]()
x2 = dic["C"]()
print(x1 is x2) #prints False
您在此设计中遇到了一些较大的问题。
首先,如果你在 class 中有一个可变属性,你应该在 class 的 __init__
方法中定义 _registry
(与实例隔离) .
接下来,_registry
的类型属性是错误的。您有 dict
个 lambda
个实例,而不是 Shape
个实例。你需要 Dict[ShapeType, Callable[[], Shape]]
。 Register
方法也有类似的问题。
您还应遵循 PEP 8 命名规则。试试这个:
class ShapeFactory:
def __init__(self) -> None:
self._registry: Dict[ShapeType, Callable[[], Shape]] = {
ShapeType.Shape: lambda: Shape(),
ShapeType.Circle: lambda: Circle(),
ShapeType.Square: lambda: Square()
}
def create(self, key: ShapeType) -> Shape:
if key in self._registry:
return self._registry[key]()
else:
raise KeyError(key)
def register(self, key: ShapeType, value: Callable[[], Shape]) -> None:
if key not in self._registry:
self._registry[key] = value
else:
raise KeyError(key)