在Python请求中使用super()从多个会话继承

在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

为了以干燥的方式编写许多HTTP请求,我想定义会话的几个子类,并根据需要从它们继承。我尝试了以下方法:

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,如果你想证明