在Python请求中使用super()从多个会话继承
为了以干燥的方式编写许多HTTP请求,我想定义会话的几个子类,并根据需要从它们继承。我尝试了以下方法:在Python请求中使用super()从多个会话继承,python,multiple-inheritance,Python,Multiple Inheritance,为了以干燥的方式编写许多HTTP请求,我想定义会话的几个子类,并根据需要从它们继承。我尝试了以下方法: import requests, time requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours auth_token = 'asdlfjkwoieur182932385' # Fake authorization to
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
>>> x=10
>>> def foo(x):
... return x + 1
...
>>> foo()
TypeError: foo() missing 1 required positional argument: 'x'
然而,如果我尝试运行它(在Python3中),我会得到
[9]中的:exec(open('requestbin\u test\u python3.py').read())
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 exec(open('requestbin\u test\u python3.py').read())
在()
TypeError:\uuuu init\uuuu()缺少1个必需的位置参数:“auth\u令牌”
我希望应用于AuthorizedJSONDebugSession
的super()。\uuuuu init\uuuu
将“足够聪明”地理解auth_令牌
用于初始化AuthorizedSession
和验证
以初始化DebugSession
。(一个仅使用AuthorizedSession
和JSONSession
的类似示例确实有效)
然而,情况似乎并非如此。如何修改此代码以使其正常工作?我非常怀疑这种方法在一般情况下是否有效,但您可以尝试显式调用必需的
\uuuu init\uu
方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
AuthorizedSession.__init__(self, auth_token)
JSONSessions.__init__(self)
DebugSession.__init__(self, verify=verify)
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
我非常怀疑这种方法在一般情况下是否有效,但您可以尝试显式调用必需的
\uuuu init\uuu
方法:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
AuthorizedSession.__init__(self, auth_token)
JSONSessions.__init__(self)
DebugSession.__init__(self, verify=verify)
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
看看这个
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
您的问题是AuthorizedJSONDebugSession()的没有提供任何参数,但init方法需要1个auth令牌参数def\uuuu init\uuuu(self,auth\u token,verify=False)
这与尝试执行以下操作基本相同:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
>>> x=10
>>> def foo(x):
... return x + 1
...
>>> foo()
TypeError: foo() missing 1 required positional argument: 'x'
在功能范围内,x
与全局x
要解决此问题,请执行以下操作:
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
或者,您可以更改init方法来实现这一点,但我不推荐这样做
def\uuuu init\uuuu(self,auth\u token=auth\u token,verify=False)
您还应该注意如何使用super()
传递参数。在这方面,您的代码还有一些其他问题。您必须确保MRO中的每个类都配合您想要做的事情,并将参数传递给超类
您还应该熟悉Python的super
的工作原理,这与其他语言不同。看看这个
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
您的问题是AuthorizedJSONDebugSession()的没有提供任何参数,但init方法需要1个auth令牌参数def\uuuu init\uuuu(self,auth\u token,verify=False)
这与尝试执行以下操作基本相同:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, auth_token):
super().__init__()
self.auth_token = auth_token
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self):
super().__init__()
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, verify=False):
super().__init__()
self.verify = verify
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, auth_token, verify=False):
super().__init__(auth_token, verify=verify)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
>>> x=10
>>> def foo(x):
... return x + 1
...
>>> foo()
TypeError: foo() missing 1 required positional argument: 'x'
在功能范围内,x
与全局x
要解决此问题,请执行以下操作:
with AuthorizedJSONDebugSession(auth_token) as s:
response = s.post(requestbin_URL, data={"key" : "value"})
或者,您可以更改init方法来实现这一点,但我不推荐这样做
def\uuuu init\uuuu(self,auth\u token=auth\u token,verify=False)
您还应该注意如何使用super()
传递参数。在这方面,您的代码还有一些其他问题。您必须确保MRO中的每个类都配合您想要做的事情,并将参数传递给超类
您还应该熟悉Python的super与其他语言不同的工作原理。处理这一问题的标准方法是只允许关键字参数,并使所有类都接受**kwargs
:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, **kwargs):
try:
self.auth_token = kwargs.pop('auth_token')
except KeyError:
raise TypeError('Missing auth_token parameter!')
super().__init__(**kwargs)
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, **kwargs):
self.verify = kwargs.pop('verify', False)
super().__init__(**kwargs)
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, **kwargs):
super().__init__(**kwargs)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
dict.pop
方法查找给定的键并将其从字典中删除。第二个参数是要使用的默认值,如果未提供,则会引发KeyError
请注意,无论何时在子类中定义\uuuuu init\uuuu
,都必须调用super()。\uuuuu init\uugs(**kwargs)
,即使您认为在这种情况下不需要它。因为将子类添加到具有多个祖先的类的层次结构中可能会更改mro,如果不执行此调用,则可能会导致初始化中断。处理此问题的标准方法是只允许关键字参数,并使所有类都接受**kwargs
:
import requests, time
requestbin_URL = 'http://requestb.in/1nsaz9y1' # For testing only; remains usable for 48 hours
auth_token = 'asdlfjkwoieur182932385' # Fake authorization token
class AuthorizedSession(requests.Session):
def __init__(self, **kwargs):
try:
self.auth_token = kwargs.pop('auth_token')
except KeyError:
raise TypeError('Missing auth_token parameter!')
super().__init__(**kwargs)
self.headers.update({'Authorization': 'token=' + self.auth_token})
class JSONSession(requests.Session):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.headers.update({'content-type': 'application/json'})
class DebugSession(requests.Session):
def __init__(self, **kwargs):
self.verify = kwargs.pop('verify', False)
super().__init__(**kwargs)
class AuthorizedJSONDebugSession(AuthorizedSession, JSONSession, DebugSession):
def __init__(self, **kwargs):
super().__init__(**kwargs)
with AuthorizedJSONDebugSession() as s:
response = s.post(requestbin_URL, data={"key" : "value"})
dict.pop
方法查找给定的键并将其从字典中删除。第二个参数是要使用的默认值,如果未提供,则会引发KeyError
请注意,无论何时在子类中定义\uuuuu init\uuuu
,都必须调用super()。\uuuuu init\uugs(**kwargs)
,即使您认为在这种情况下不需要它。因为将子类添加到具有多个祖先的类的层次结构中可能会更改mro,如果不执行此调用,则可能会导致初始化中断。您可以在任何地方使用kwargs为每个超类提供它实际需要的参数,但我将一起消除多重继承。它通常会变成一个令人讨厌的bug源。多重继承充其量是很棘手的,最好只限于“一个基类+两个混合类”的使用。你可以在任何地方使用kwargs来为每个超类提供它实际需要的参数,但我会一起去掉多重继承。它通常会变成一个令人讨厌的bug源。多重继承充其量是很棘手的,最好只限于“一个基类+几个混合类”的使用。这不是一个好主意。如果你不能让super
在多重继承中工作,那通常是一种强烈的设计气味。@Brunodesshuilliers同意这不是一个好主意。如果你不能使super
在多重继承中工作,这通常是一种强烈的设计气味。@Brunodesshuilliers同意避免缺少auth\u令牌参数
类型错误,我不得不将AuthorizedJSONDebugSession
初始化为AuthorizedJSONDebugSession(auth\u令牌=auth\u令牌)
@KurtPeek,如果你想证明