2014-02-19 1 views
4

Мне нужно проверить, являются ли объекты, считанные из файла (и eval ed) с ConfigParser, являются сопоставлениями.Как проверить, является ли объект сопоставлением (поддерживает использование ** O)

Не совсем уверен в терминологии здесь, но позвольте мне объяснить. Учитывая, что мой объект называется O он должен поддерживать используется следующим образом:

def tester(**kwargs): 
    print kwargs 

tester(**O) 

Если O не поддерживая ** это привело бы в TypeError, например, TypeError: test() argument after ** must be a mapping, not tuple.

Это очень простой сценарий, но мне нужно знать, что O будет работать, прежде чем использовать его, и я должен быть абсолютно уверен, что он не подведет. Если бы я испытывал O за то, что итератор, я хотел бы использовать что-то вроде:

try: 
    iter(O) 
except: 
    O = tuple() 

Как обсуждалось в In Python, how do I determine if an object is iterable?

Я не могу найти параллель отображений. Как обсуждалось в том же ответе выше, использование isinstance и collections не является хорошим решением.

Так что я должен сделать мой тестер-функцию выше (без печати) в качестве собственного отображения-тест при загрузке объектов, как

try: 
    tester(**O) 
except TypeError: 
    O = {} 

или же питон имеет встроенный способ проверить это, как есть ли итераторы? Кажется, должно быть одно.

Редактировать

На самом деле связанный ответ выше никогда не выступал против метода isinstance, следует читать его лучше ...

ответ

6

Используйте collections.Mapping ABC:

from collections import Mapping 

if isinstance(O, Mapping): 
    # O is a mapping 

Это поддерживает любые объект, который реализует правильные методы считается картографическим, включая dict.

Демо:

>>> from collections import Mapping 
>>> isinstance({}, Mapping) 
True 
>>> isinstance((), Mapping) 
False 
+0

Но это должно быть получено из Mapping или что-то, что является сопоставлением, так это то же самое, что и поддержка **? – deinonychusaur

+0

@deinonychusaur: Нет, 'Mapping' - это ABC, абстрактный базовый класс, и любой объект, поддерживающий * методы *, считается экземпляром. На самом деле это не нужно наследовать от «Mapping», реализация функциональности достаточно. –

+0

OK спасибо за быстрый ответ, я был только смущен, похоже, но концепция отображения python кажется не такой, как здесь, на SO, надеюсь, это поможет кому-то еще. – deinonychusaur

2

Некоторые объекты не могут быть экземплярами collections.Mapping и все же могут быть распакованы с использованием двойной звезды синтаксис (**):

import collections 
def tester(**kwargs): 
    print kwargs 

class D: 
    "http://stackoverflow.com/a/8601389/190597 (Raymond Hettinger)" 
    def keys(self): 
     return ['a', 'b'] 
    def __getitem__(self, key): 
     return key.upper() 

obj = D() 
tester(**obj) 
# {'a': 'A', 'b': 'B'} 

print(isinstance(obj, collections.Mapping)) 
# False 

Минимальный интерфейс, который obj должен поставить на keys и __getitem__:

print(all(hasattr(obj, attr) for attr in ('keys', '__getitem__'))) 
# True 
+0

Итак, вы говорите, что единственный истинный способ познания - это тестирование или потенциально использование 'dir' (хотя это будет более низкая степень уверенности)? – deinonychusaur

+1

Нет, я говорю, когда 'all (hasattr (obj, attr) для attr in ('keys', '__getitem __'))' is 'True', тогда' tester (** obj) 'работает. – unutbu

Смежные вопросы