Woo*_*193 5 python duck-typing
假设我有一个A类:
class A:
def __init__(self, x, y):
self.x = x
self.y = y
def sum(self):
return self.x + self.y
Run Code Online (Sandbox Code Playgroud)
我定义了一个名为的工厂方法factory:
def factory(x, y):
class B: pass
b = B()
setattr(b, 'x', x)
setattr(b, 'y', y)
B.__name__ = 'A'
return b
Run Code Online (Sandbox Code Playgroud)
现在,如果我这样做print(type(A(1, 2))),print(type(factory(1, 2)))他们会证明这些是不同的类型.如果我尝试做,factory(1, 2).sum()我会得到一个例外.但是,type(A).__name__并且type(factory(1, 2)).__name__是相同的,如果我这样做,A.sum(factory(1, 2))我会得到3,好像我用它来调用它A.所以,我的问题是:
如果factory(1, 2).sum()不在sumB上定义或继承,我需要做什么才能完成工作?
我认为你从根本上误解了工厂模式,并且可能对 Python 中接口的工作方式感到困惑。要么是这样,要么我从根本上对这个问题感到困惑。不管怎样,我们需要做一些整理。
我需要在这里做什么才能使 factory(1, 2).sum() 工作而不在 B 上定义 sum 或进行继承?
只需返回一个A而不是其他类型:
def factory(x, y):
return A(x, y)
Run Code Online (Sandbox Code Playgroud)
然后
print(factory(1,2).sum())
Run Code Online (Sandbox Code Playgroud)
3将按预期输出。但这是一个无用的工厂……可以用A(x, y)它来完成!
一些注意事项:
当您拥有易于构建的“可命名”类型时,通常会使用“工厂”(或工厂模式)。考虑一下当您使用scipy.interpolate.interp1d(请参阅此处)时,有一个选项kind,它基本上是您可能用于进行插值的所有不同策略的枚举。这本质上是一个工厂(但隐藏在函数内部以方便使用)。您可以想象这可能是独立的,因此您可以调用您的“策略”工厂,然后将其传递给调用interp1d。然而,内联执行是 Python 中的常见模式。观察:这些策略很容易“命名”,但一般来说构建起来有些困难(您可以想象,必须传递一个执行线性插值的函数而不是仅仅执行 会很烦人kind='linear')。这就是工厂模式有用的原因......
如果您不知道A前面是什么,那么它绝对不是您想要应用的工厂模式。此外,如果您不知道要序列化/反序列化的内容,则无法调用或使用它。你必须知道这一点,或者有某种方式来推断它。
Python 中的接口不像Java/C++ 等其他语言那样强制执行。这就是鸭子打字的精神。如果一个接口执行类似 call 的操作x.sum(),那么实际上是什么类型并不重要x,它只需要有一个名为 的方法即可sum()。如果它的行为像“sum”鸭子,叫起来像“sum”鸭子,那么从Python的角度来看,它就是“sum”鸭子。无论x是numpy数组还是A,它都可以正常工作。在 Java/C++ 中,除非编译器绝对确定已定义该方法,否则此类内容不会编译。幸运的是,Python 不是这样的,所以您甚至可以动态定义它(也许您正在尝试使用)。不管怎样,Python 中的接口概念与其他主流语言中的接口概念有很大不同。xsumB
聚苯乙烯
但是 和
type(A).__name__是type(factory(1, 2)).__name__等价的
当然是,当你说 时,你明确地这样做了B.__name__ = 'A'。所以我不确定你想达到什么目的......
哈!
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |