2016-06-30 2 views
1

Это пример объекта python, с которым я работаю.Извлечение определенных полей из объекта python

class DataObj(object): 

    def __init__(self, cvid, cvname, address, get_info): 
     self.cvid = cvid 
     self.cvname = cvname 
     self.address = address 
     self.prof = PROF("Honda", "Jason Jones") 


class PROF(object): 

    def __init__(self, organization, manager_name): 
     self.organization = organization 
     self.manager_name = manager_name 
     self.project_list = [Proj("asd", "asd"), Proj("asdsd", "asdsd")] 
class Proj(object): 
    def __init__(self, projectname, projecttype): 
     self.projectname = projectname 
     self.projecttype = projecttype 

Мне нужно написать функцию, которая принимает список полей и извлечь все поля, как ключевой пары значений из DataObj. Фокус в том, что он должен также искать атрибуты объекта, составленного внутри DataObj класс. например, если список полей [ «CVID», «организация», «Projectname»], он должен вернуть что-то подобное в следующем формате

{'cvid' : 'value', 'organization' : 'Honda', Proj :[{'projectname' : 'asd'}, {'projectname' : 'asdsd'}] 

Где я должен написать эту функцию, так что мой код более модульная? Я думал о написании его внутри DataObj, но я не знал бы, какие атрибуты объекта состоят внутри DataObj. Как достичь того, что я пытаюсь сделать более объектно-ориентированным способом?

ответ

1

Между __getattr__ и operator.attrgetter, вы могли бы сделать эту работу довольно легко:

class DataObj(object): 

    def __init__(self, cvid, cvname, address, get_info): 
     self.cvid = cvid 
     self.cvname = cvname 
     self.address = address 
     self.prof = PROF("Honda", "Jason Jones") 

    def __getattr__(self, name): 
     # Called when an attribute is accessed which is not found on DataObj 
     # You can limit the loop to avoid checking some attributes, or 
     # remove the loop if only self.prof should be checked 
     for member in (self.cvid, self.cvname, self.address, self.prof): 
      try: 
       return getattr(member, name) 
      except AttributeError: 
       pass 
     raise AttributeError(name) 

     # If only self.prof should be checked, the function could simplify to: 
     # return getattr(self.prof, name) 

Затем вы можете сделать простую функцию полезности, которая работает против DataObj, чтобы получить произвольный набор пар ключ-значение из это:

from operator import attrgetter 

def extractdata(dataobj, *names): 
    return dict(zip(names, attrgetter(*names)(dataobj))) 

Или как член DataObj, просто назвать первый из параметров self в матч конвенция:

def extractdata(self, *names): 
    return dict(zip(names, attrgetter(*names)(self))) 

__getattr__ позволяет делегирование атрибутов поиска для содержащихся объектов и attrgetter позволяет получить набор произвольных атрибутов в простой форме.

+0

спасибо. Это решает мою проблему. –

+0

Можете ли вы объяснить мне эту часть attrgetter (* names) (self)? –

+0

@paris_serviola: 'attrgetter' выполняет функцию, которая извлекает предоставленные имена (имена) из того, что вызывается. Поэтому, если 'getname = attrgetter ('name')', то 'getname (foo)' эквивалентно 'foo.name'. С несколькими именами он возвращает 'tuple', поэтому' getfoobar = attrgetter ('foo', 'bar') 'делает объект таким, что' getfoobar (x) 'эквивалентен' (x.foo, x.bar) '. Таким образом, при распаковке звезды мы берем имена и создаем геттер для всех из них, а затем сразу же применяем геттер к объекту. При дальнейшем рассмотрении это не сработает, если «имена» - это только одно имя, поэтому вам понадобится специальный случай. – ShadowRanger

2

Все, что я сделал, это просто добавить __iter__, который в основном говорит эй, вы можете перебирать меня, если вы бросаете объект в контейнерный тип iterabale.

class Proj(object): 
    def __init__(self, projectname, projecttype): 
     self.projectname = projectname 
     self.projecttype = projecttype 

    def __iter__(self): 
     yield ("projectname", self.projectname) 


class PROF(object): 
    def __init__(self, organization, manager_name): 
     self.organization = organization 
     self.manager_name = manager_name 
     self.project_list = [Proj("asd", "asd"), Proj("asdsd", "asdsd")] 

    def __iter__(self): 
     for proj in self.project_list: 
      yield (dict(proj)) 


class DataObj(object): 
    def __init__(self, cvid, cvname, address): 
     self.cvid = cvid 
     self.cvname = cvname 
     self.address = address 
     self.prof = PROF("Honda", "Jason Jones") 

    def __iter__(self): 
     yield ('cvid', self.cvid) 
     yield ('organization', self.prof.organization) 
     yield ("Proj", list(self.prof)) 


do = DataObj("1", "heinst", "A Street, Somewhere, USA") 
print dict(do) 
Смежные вопросы