Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何创建通过items()返回重复值的类似dict的对象 框架_Python - Fatal编程技术网

Python 如何创建通过items()返回重复值的类似dict的对象 框架

Python 如何创建通过items()返回重复值的类似dict的对象 框架,python,Python,我正在使用该框架生成HTTP/2流量。在生成请求和响应时,我当前使用和分别发送HTTP/2请求和响应 我的要求 我需要能够发送带有重复字段的HTTP/2请求和响应。例如,这里是YAML指定的请求,它包含两个x-test-duplicate字段: headers: fields: - [ :method, GET, equal ] - [ :scheme, https, equal ] - [ :authority, example.data.com, equa

我正在使用该框架生成HTTP/2流量。在生成请求和响应时,我当前使用和分别发送HTTP/2请求和响应

我的要求 我需要能够发送带有重复字段的HTTP/2请求和响应。例如,这里是YAML指定的请求,它包含两个
x-test-duplicate
字段:

  headers:
    fields:
    - [ :method, GET, equal ]
    - [ :scheme, https, equal ]
    - [ :authority, example.data.com, equal ]
    - [ :path, '/a/path?q=3', equal ]
    - [ Accept, '*/*' ]
    - [ Accept-Language, en-us ]
    - [ Accept-Encoding, gzip ]
    - [ x-test-duplicate, first ]
    - [ x-test-duplicate, second ]
    - [ Content-Length, "0" ]
注意,根据HTTP/2规范,这是明确允许的。例如,见:

动态表可以包含重复的条目(即带有 相同的名称和值)。因此,不得重复条目 被解码器视为错误

我的问题 问题是,虽然正确处理可能包含重复字段(例如,
(“name1”、“value1”)、(“name2”、“value2”)、(“name1”、“另一个值”)
)的元组表,但需要一个字典,当然,它不是为重复键设计的。文档中没有明确说明
标题的类型要求,但在源代码中,
items()
被取消。如果我传递一个元组的iterable,我会得到
AttributeError:“tuple”对象没有属性“items”
。请注意,这是多么可悲:超框架强制用户传入一个不允许重复的字典,然后通过
items()
,立即将该字典转换为元组的一个iterable,后者允许重复字段。如果只需要一组元组,比如h2的接口,我就不会有这个问题

我的问题
我在hyper-github项目中提出了关于此限制的问题。同时,我希望我能解决这个问题。我有一个表示HTTP/2头的元组表,其中包含重复的字段。我是否可以将其包装在一个对象中,以便在对其调用
items()
时,它只返回元组的iterable?

由于Python支持Duck类型,因此具有
items
方法的类就足够了:

class Wrapper:
    __slots__ = ["pairs"]  # Minor optimization
    def __init__(self, pairs: Iterable[Tuple[str, str]]):
        self.pairs = pairs

    def items(self) -> Iterable[Tuple[str, str]]:
        return self.pairs
然后:


这方面的主要问题是它完全依赖于
请求的实现细节。如果他们将来选择使用
标题
用于其他类似dict的目的,这将很容易中断。

Python通常使用
电子邮件实例来实现这一点()

EmailMessage
类似字典的接口由标题名称索引,标题名称必须是ASCII值。字典的值是带有一些额外方法的字符串。标头以保留大小写的形式存储和返回,但字段名不区分大小写进行匹配。与真正的dict不同,对键有一个顺序,并且可以有重复的键。提供了用于处理具有重复键的标题的其他方法

在基本用法中,您可以使用设置项并使用检索项。您可以将有效负载留空

>>> headers = EmailMessage()
>>> headers.add_header("x-test-duplicate", "first")
>>> headers.add_header("x-test-duplicate", "second")
>>> headers.items()
[('x-test-duplicate', 'first'), ('x-test-duplicate', 'second')]
这是一场经过自身考验的战斗,这是一种挑战

与滚动自己的multidict或使用简单的对列表相比,其优点是可以获得标题的正确行为(RFC 5322和RFC 6532样式字段名和值),例如不区分大小写:

>>> headers.add_header("aBc", "val1")
>>> headers.add_header("AbC", "val2")
>>> headers.get_all("ABC")
['val1', 'val2']

是的,很好。为了明确起见,我已经验证了这确实满足hyper.HTTP20Connection.request(),并导致发送重复的字段。非常感谢。
>>> headers.add_header("aBc", "val1")
>>> headers.add_header("AbC", "val2")
>>> headers.get_all("ABC")
['val1', 'val2']