简体   繁体   English

如何使用zope.interface.direct提供内置类型实例(dict,string等)

[英]How to use zope.interface.directlyProvides with instances of build in types (dict, string, …)

I have a bunch of dictionaries, which I would like to annotate with type information, to be able to later get adapters for them. 我有一堆字典,我想用类型信息来注释,以便以后可以为它们获取适配器。 In the following example, the failing case is what I would like to do and the other case shows a working version. 在以下示例中,失败的情况是我要执行的操作,另一种情况显示了有效的版本。 Is it somehow possible to get the first version working without introducing the extra object? 是否可以在不引入额外对象的情况下使第一个版本正常工作? The code which creates the dicts would not be easy to change, so I'm looking for the most simple and non intrusive way to add some type infos. 创建字典的代码很难更改,因此我正在寻找添加一些类型信息的最简单且非侵入性的方法。

from zope.interface import Interface, implements, directlyProvides               
from zope.interface.registry import Components                                   

registry = Components()                                                          

class IA(Interface):                                                             
    pass                                                                         

#   this one fails                                                               

data = {}                                                                        
directlyProvides(data, IA)                                                       

#   this way it works                                                            

class X(dict):                                                                   
    pass                                                                         

data = X()                                                                       
directlyProvides(data, IA)

zope.interface relies on the ability to set some magic attributes on various objects and classes. zope.interface依赖于在各种对象和类上设置一些魔术属性的能力。 This is what happens 这是怎么回事

>>> class Dict(dict):
...     pass
...
>>> getattr(Dict, '__provides__', None)

Nothing. 没有。 Now try to do what you did. 现在尝试做你所做的。

>>> from zope.interface import Interface, implements, directlyProvides
>>> class IA(Interface):
...     pass
... 
>>> data = Dict()
>>> directlyProvides(data, IA)

Try to grab that __provides__ again 尝试再次抓住__provides__

>>> getattr(Dict, '__provides__', None)
<zope.interface.declarations.ClassProvides object at 0x7f133cab48d0>

Reason this fails on the builtin types is because you can't actually set attributes on any of them (through standard means). 内建类型失败的原因是,您实际上无法(通过标准方式)对任何内置属性设置属性。

>>> setattr(dict, '__provides__', None)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'dict'

Hence if you want to assign some marker interface on some instances of standard types, it will fail. 因此,如果您想在某些标准类型的实例上分配一些标记器接口,它将失败。 Just subclass them as is, or create real objects which is more what the Zope Component Architecture was more designed to be used for. 只需按原样对它们进行子类化,或创建实际对象,这比Zope组件体系结构设计用于的对象更多。

You cannot annotate Python built-in types with interface information; 您不能使用接口信息来注释Python内置类型。 you simply cannot add the required attributes. 您根本无法添加所需的属性。

You can register adapters for the type (so no interfaces implemented): 可以为该类型注册适配器(这样就不会实现接口):

>>> from zope.interface.registry import Components                                   
>>> from zope.interface import Interface
>>> registry = Components()                                                          
>>> class IA(Interface):                                                             
...     pass                                                                         
... 
>>> data = {}
>>> registry.registerAdapter(lambda o: 'adapter from dict to IA', [dict], IA)
>>> registry.queryAdapter(data, IA)
'adapter from dict to IA'

You cannot do this for instances, unfortunately: 不幸的是,您不能在某些情况下执行此操作:

>>> registry.registerAdapter(lambda o: 'adapter from data to IA', [data], IA)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/zope/interface/registry.py", line 186, in registerAdapter
    required = _getAdapterRequired(factory, required)
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/zope/interface/registry.py", line 432, in _getAdapterRequired
    raise TypeError("Required specification must be a "
TypeError: Required specification must be a specification or class.

This means that if you really must adapt specific dictionaries, then your options are limited. 这意味着,如果您确实必须改编特定的词典,那么您的选择将受到限制。 Using a subclass of dict is one work-around. 使用dict的子类是一种解决方法。

However, you must really ask if adapting dictionaries is the best approach for your problem here. 但是,您必须真正询问适应词典是否是解决问题的最佳方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM