associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Você não tem permissão para executar esta ação.

Excluir mensagem

InterpolatedValuesMapping

Mapeamento com valroes interopolados

por JoaoBueno

Uma coisa bem simples de se fazer em Python é criar novos tipos de dados que usem os métodos especiais definidos no data model para prover funcionalidades novas ( e consistentes).

Por exemplo, se queremos fazer uma interpolação de valores a partir de um conjunto finito de pontos, podemos criar uma classe que carregue um conjutno inicial de pontos, e escreva o método "getitem" (e somente esse método é necessário), de forma que se for solicitado um valor intermediário da tabela carregada originalmente, ele possa usa-la para calcular esse valor em tempo real e retorna-lo ao requisitante de forma completamente transparente.

Para a parte da aplicação que fizer uso desse objeto, será como se ele fosse um "dicionário com todos os vlaores intermediários possíveis".

É claro que se pode sofisticar bastante a coisa - trago um exemplo bem fatorado e expandido apartir de uma necessidade exposta na lista python-brasil hoje (18-06-2009) pelo Helberg - a classe faz exatamente o que descrevo para uma tabela de data-hora e temperaturas:

   1 # -*- coding: utf-8 -*-
   2 from datetime import datetime
   3 import time
   4 
   5 class InterpolatedTimeTable(object):
   6     def __init__(self, time_temperature_list=[]):
   7         """
   8             time_temperature_list should be a sequence of strings like:
   9 
  10              ("2009-06-03 15:00:00  18.40",
  11               "2009-06-03 18:00:00  21.00",
  12               "2009-06-01 18:00:00  24.70")
  13              Where the last parameter is a temperature measurement,
  14              from which it will be able to return a linearly interpolated 
  15              temperature coputed from the given values for anuy datetime
  16              object inside the given range
  17         """
  18         self.table = {}
  19         for line in time_temperature_list:
  20             self.add_line(line, reindex = False)
  21         self.reindex()
  22          
  23     def add_line(self, line, reindex = True):
  24         date_time_str, temp = line.rsplit(None, 1)
  25         date_time_obj = self.str_to_datetime(date_time_str.strip())
  26         self.table[date_time_obj] = float(temp)
  27         if reindex:
  28             self.reindex()
  29              
  30     def reindex(self):
  31         self.table_indexes = sorted(self.table.keys())
  32              
  33 
  34     def str_to_datetime(self, date_time_str):
  35         time_struct = time.strptime(date_time_str, "%Y-%m-%d %H:%M:%S")
  36         return datetime(*(time_struct[:6]))
  37 
  38     def __getitem__(self, date_time_obj):
  39         if isinstance(date_time_obj, str):
  40             date_time_obj = self.str_to_datetime(date_time_obj)
  41         if date_time_obj in self.table:
  42             return self.table[date_time_obj]
  43         prev_dt = self.find_previous_dt(date_time_obj)
  44         next_dt = self.find_next_dt(date_time_obj)
  45         
  46         table_time_delta = float((next_dt - prev_dt).seconds)
  47         requested_item_time_delta = (date_time_obj - prev_dt).seconds
  48         value = self.table[prev_dt] + (requested_item_time_delta * 
  49                     (self.table[next_dt] - self.table[prev_dt]) /
  50                  table_time_delta
  51                 )
  52         return value
  53     
  54     def find_previous_dt(self, target_dt):
  55         return self._find_dt(target_dt, True)
  56         
  57     def find_next_dt(self, target_dt):
  58         return self._find_dt(target_dt, False)
  59     
  60     def _find_dt(self, target_dt, previous):
  61         for i, dt in enumerate(self.table_indexes):
  62             if dt > target_dt:
  63                 if previous:
  64                     if i >= 1:
  65                         return self.table_indexes[i - 1]
  66                     else:
  67                         raise IndexError("datetime out of range for interpolation %s" %target_dt)
  68                 else: #finding_next_dt
  69                     return dt
  70         else:
  71             raise IndexError("datetime out of range for interpolation %s" %target_dt)
  72         
  73 if __name__ == "__main__":
  74     #teste:
  75     sample_data = """\
  76 | 2009-06-03 15:00:00 | 18.40 |
  77 | 2009-06-03 18:00:00 | 21.00 |
  78 | 2009-06-01 18:00:00 | 24.70 |
  79 | 2009-05-25 01:00:00 | 18.70 \
  80 """
  81     sample_data = sample_data.replace("|", "").split("\n")
  82     table = InterpolatedTimeTable(sample_data)
  83     test_pattern = ("2009-06-03 15:00:00",
  84                     "2009-06-03 16:00:00",
  85                     "2009-06-03 17:00:00",
  86                     "2009-06-03 17:30:00",
  87                     "2009-06-03 17:55:00",
  88                     "2009-06-03 18:00:00",
  89                     # "2005-07-13 00:00:00" #value out of range. uncomment for testing
  90                     )
  91     for dt in test_pattern:
  92         print "%s - %.2f" % (dt, table[dt])
  93     

Voltar ao CookBook