在继承httplib.HTTP(s)Connection时处理SSL与非SSL连接
我有一个类,它是从httplib.HTTPSConnection这个类继承来的。
class MyConnection(httplib.HTTPSConnection):
def __init__(self, *args, **kw):
httplib.HTTPSConnection.__init__(self,*args, **kw)
...
我想知道在创建这个类的时候,是否可以关闭SSL层,这样我就可以用它和不安全的服务器进行通信了?
在我的情况下,在初始化之前就已经知道是否需要使用SSL,所以另一种解决方案是尝试把继承关系从httplib.HTTPSConnection改成httplib.HTTPConnection,但我也不太确定怎么才能合理地做到这一点?
3 个回答
看起来你想用 MyConnection 来连接多个不同的主机。如果是这样的话,你就不应该从 HTTP(S)Connection 这个类去继承,因为这个类并不适合用来处理多个连接。相反,你可以让 MyConnection 拥有 一个 HTTP(S)Connection。
根据你最后一段的内容,在Python中,你可以使用类似工厂模式的东西:
class Foo:
def doit(self):
print "I'm a foo"
class Bar:
def doit(self):
print "I'm a bar"
def MakeClass(isSecure):
if isSecure:
base = Foo
else:
base = Bar
class Quux(base):
def __init__(self):
print "I am derived from", base
return Quux()
MakeClass(True).doit()
MakeClass(False).doit()
输出结果:
I am derived from __main__.Foo
I'm a foo
I am derived from __main__.Bar
I'm a bar
根据我对@Mark回答的评论,我喜欢他提倡的工厂方法。不过,我不会完全按照他的方式来做,因为他每次都新建一个类。相反,这里可以很好地使用混入(mixin)和super
,如下所示:
class MyConnectionPlugin(object):
def __init__(self, *args, **kw):
super(MyConnectionPlugin, self).__init__(*args, **kw)
# etc etc -- rest of initiatizations, other methods
class SecureConnection(MyConnectionPlugin,
httplib.HTTPSConnection, object):
pass
class PlainConnection(MyConnectionPlugin,
httplib.HTTPConnection, object):
pass
def ConnectionClass(secure):
if secure:
return SecureConnection
else:
return PlainConnection
conn = ConnectionClass(whatever_expression())()
等等。
当然,还有其他选择,因为在Python中,一个对象可以改变自己的__class__
,等等。不过,就像用犀牛步枪打苍蝇一样,使用过于强大的(非常复杂、深奥,几乎像魔法一样的语言特性)来解决那些可以用合理的方法轻松解决的问题(就像用苍蝇拍一样),并不是一个好主意;-)。
编辑:在基类中额外注入object
只是为了弥补一个不太好的事实,那就是在Python 2.*中,HTTPConnection类是旧式的,因此与其他类不太兼容——可以看看...:
>>> import httplib
>>> class Z(object): pass
...
>>> class Y(Z, httplib.HTTPConnection): pass
...
>>> Y.mro()
[<class '__main__.Y'>, <class '__main__.Z'>, <type 'object'>, <class httplib.HTTPConnection at 0x264ae0>]
>>> class X(Z, httplib.HTTPConnection, object): pass
...
>>> X.mro()
[<class '__main__.X'>, <class '__main__.Z'>, <class httplib.HTTPConnection at 0x264ae0>, <type 'object'>]
>>>
在类Y中,方法解析顺序(也叫MRO)在没有额外注入object
基类的情况下,会先找到来自httplib的类(所以super
无法正确工作),但额外的注入会调整MRO以进行补偿。可惜的是,在处理旧式类时,Python 2.*需要这样小心;幸运的是,在Python 3中,旧式风格已经消失,每个类都能“和谐相处”,这才是应该的!-)