Обтекание однородных объектов Python

Мы можем объединить две коллекции, используя sub-запрос mongoDB. Вот пример, Комментарии -

`db.commentss.insert([
  { uid:12345, pid:444, comment:"blah" },
  { uid:12345, pid:888, comment:"asdf" },
  { uid:99999, pid:444, comment:"qwer" }])`

Пользователи -

db.userss.insert([
  { uid:12345, name:"john" },
  { uid:99999, name:"mia"  }])

Суб-запрос MongoDB для JOIN -

`db.commentss.find().forEach(
    function (newComments) {
        newComments.userss = db.userss.find( { "uid": newComments.uid } ).toArray();
        db.newCommentUsers.insert(newComments);
    }
);`

Получить результат из недавно созданная коллекция -

db.newCommentUsers.find().pretty()

Результат -

`{
    "_id" : ObjectId("5511236e29709afa03f226ef"),
    "uid" : 12345,
    "pid" : 444,
    "comment" : "blah",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f0"),
    "uid" : 12345,
    "pid" : 888,
    "comment" : "asdf",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f1"),
    "uid" : 99999,
    "pid" : 444,
    "comment" : "qwer",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f3"),
            "uid" : 99999,
            "name" : "mia"
        }
    ]
}`

Надеюсь, что это поможет.

9
задан Peter Mortensen 17 March 2019 в 23:33
поделиться

2 ответа

Если вы только реализуете методы, то универсальный __getattr__ может сделать трюк

class Wrapper: 
    def __init__(self, x): 
        self.x = x 
    def __getattr__(self, name): 
        def f(*args, **kwargs): 
            for y in self.x: 
                getattr(y, name)(*args, **kwargs) 
        return f

Например, с x = Wrapper([[], [], []]) после вызова x.append(12) все три объекта списка будут иметь 12 как последний элемент.

Обратите внимание, что возвращаемое значение всегда будет None ... опция могла бы собирать возвращаемые значения и возвращать их в виде списка, но это, конечно, "сломало бы API".

0
ответ дан 6502 17 March 2019 в 23:33
поделиться

Я думаю, что у вас есть правильная идея здесь

wrapped_apis = [OriginalApi(), OriginalApi()]
for wrapped_api in wrapped_apis:
    wrapped_api.do_something(1, 2, True)

Вы можете определить свой класс-обертку, наследуя из list, а затем обрабатывать вызовы API для его элементов, как только он будет создан.

class WrapperClass(list):
    def __init__(self, api_type):
        self.api_type = api_type

        for func in dir(api_type):
            if callable(getattr(api_type, func)) and not func.startswith("__"):
                setattr(self, func, lambda *args, **kwargs: 
                    [getattr(o, func)(*args, **kwargs) for o in self])

w = WrapperClass(OriginalApi)
o1, o2 = [OriginalApi()]*2
w.append(o1)
w.append(o2)
print(w.do_something(1, 2, True))
# [None, None]
print(w[0].b)
# 12
print(w[1].b)
# 12
print(o1.b)
# 12

Здесь я перебираю каждый метод в вашем классе API и создаю метод в классе-обертке, который применяет свои аргументы ко всем своим элементам списка. Затем он возвращает понимание списка, состоящее из результатов.

Излишне говорить, что вам, вероятно, следует проверить тип нового объекта, добавляемого к этому WrapperClass, например,

def append(self, item):
    if not isinstance(item, self.api_type):
        raise TypeError('Wrong API type. Expected %s'.format(self.api_type))
    super(WrapperClass, self).append(item)
0
ответ дан darksky 17 March 2019 в 23:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: