2013-09-03 3 views
0

Как создать класс словаря D, который хранит экземпляры некоторого класса «A» и наследует завернутые версии методов «A»?python dict объектов класса, который наследует атрибуты из объектов класса

Например, предположим, что a = A() и a.first() - это функция, которая что-то делает с «a» и возвращает некоторый объект. Тогда я хочу, чтобы d = D ({'k0': a0, 'k1': a1}) имел атрибут d.first(), который возвращает {'k0': a0.first(), 'k1': a1.first()} и изменяет базовые данные в a0 и a1, как и вызовы first().

Кроме того, я хочу только разоблачать методы (и, возможно, атрибуты), которые уже не существуют в классе Dict (не топает) И я хочу, чтобы это сделать динамически (без жесткого кодирования методов A, I уже знают, как набирать все методы вручную). Возможно, рассмотрим только методы, которые не начинаются с «_», если это проще.

Кроме того, я хотел бы, чтобы «D» выполнял обработку выходов из вызовов в зависимости от типов возврата (постобработка, упаковка вообще).

Кажется, что это может быть плохой идеей, но я просто хочу понять, какие подходы есть. Из моего чтения до сих пор, похоже, я мог использовать множественное наследование и написать свою собственную функцию __new__ или сделать что-то еще с метаклассированием. Но знание состоит в том, что вы, как правило, не обходитесь с __new__, если вы не гуру, поэтому меня заставляют колебаться. Есть ли какой-нибудь декораторский трюк для этого? Я думаю, что я мог бы также использовать модуль проверки для прохождения класса «А», но это похоже на взлом.

Обновление: В качестве особого примера. Представьте себе, что у меня есть словарь pandas.DataFrames и что я хочу, чтобы коллекция появлялась и вела себя как можно больше, как один DataFrame с четным завершением табуляции методов, работающих в iPython (и я не использую pandas.Panel). Для простоты рассмотрим только поведение только для чтения (индексирование и выбор), такие вещи, как d.ix [0:10] и d.mean(), должны возвращать что-то от применения функции ко всем кадрам в словаре, в то время как d ['k0 '] должен вернуть значение в словаре, соответствующее ключу' k0 '. Комбинация жесткого кодирования и getattr делает то, что я хочу, но я изучаю, как это можно сделать с менее жестким кодированием.

Я думаю, что это общая проблема проектирования, в которой вы хотите динамически генерировать итерацию, которая ведет себя как объекты, которые она содержит.

+0

Вы смотрели на '__getattr__'? – BrenBarn

+0

@BrenBarn Вы имеете в виду просто обрабатывать наследование самостоятельно, проверяя __getattr__ на dict, а затем на 'A'? Полагаю, это более простое решение. – mathtick

ответ

0

Это немного странный вопрос, но это очень зависит от того, что «D» структурно. Если D это просто структура данных, то это вполне допустимо, чтобы упаковать словарь с объектами, subcript и вызов функции следующим образом:

class A(object): 
    def __init__(self,x): 
     self.x = x 
    def first(self): 
     return self.x 

a = A(7) 
b = A(3) 
d = {'X':a,'Y':b} 
print d['X'].first() 

Наряду с этим, если вы хотите, чтобы все «первые», то вы можете сделать что-то вроде этого:

firsts = {} 
for i,j in d: 
    firsts[i]=j.first() 

Однако, кажется, что ваш вызов является немного более сложным, а также небезопасно: что если objecy в словаре есть метод keys()? Что имеет преимущество, и если его словари, как мне получить доступ к методу содержимого keys()?

Что я предлагаю - это перерисовать или заново задавать вопрос с некоторыми особенностями. Во-первых, что представляют собой объекты в словаре? И что еще важнее, что представляет собой словарь?

+0

Дик имеет преимущество. Если вы хотите получить доступ к ключам объектов, тогда вы просто сделаете это d ['k0']. Keys() (функция удобства не указана). Вариант использования - в основном iPython. Подумайте о наборе таблиц (или DataFrames), в которых вы хотите хранить их отдельно (в основном, непересекающиеся столбцы), но хотите выполнять операции над ними, как если бы они были одной таблицей. – mathtick

1

Каждая из этих работ в ограниченном тестировании:

#! /usr/bin/python3 
class D(dict): 
    def __getattr__(self, name): 
     return lambda *args, **kw: { 
      k:getattr(v,name)(*args, **kw) for k,v in self.items() } 

class D(dict): 
    def __getattr__(self, name): 
     def proxy(*args, **kw): 
      d2 = {k:getattr(v,name)(*args, **kw) for k,v in self.items()} 
      # Post-process if required 
      return d2 
     return proxy 

d = D() 

d['k1']='a1' 
d['k2']='a2' 
d['k3']='33' 

print(d.capitalize()) # No-arg form passed to str, not dict 
print(d.replace('a', 'Hello')) # Arguments 
print(d.get('k1')) # .get() satisified by dict, not str 
+0

__getattr__, похоже, работает для функций, но не для таких атрибутов, как d.ix [0:10], которые в основном имеют метод __getitem__. Думаю, это можно было бы проверить вручную. – mathtick

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