English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Aggiunta dinamica di attributi e creazione di oggetti in una classe Python

Questo articolo risolverà passo dopo passo da diversi aspetti

      1、La funzione principale del programma

      2、Procedura di implementazione

      3、Definizione della classe

      4、Aggiornamento dinamico di ogni oggetto e restituzione dell'oggetto utilizzando generatori

      5、Utilizzo di strip per rimuovere caratteri inutili

      6、Matching di stringhe con rematch

      7、Utilizzo di timestrptime per convertire una stringa in un oggetto di tempo

      8、Codice completo

La funzione principale del programma

Adesso c'è un documento simile a una tabella per memorizzare informazioni degli utenti: la prima riga sono le proprietà, le proprietà sono separate da virgola (,), a partire dalla seconda riga, ogni riga rappresenta il valore di ogni proprietà, ogni riga rappresenta un utente. Come implementare la lettura di questo documento, per riga esportare un oggetto utente?
Inoltre ci sono altre 4 richieste specifiche:

Ogni documento è molto grande, se si memorizza tutti gli oggetti generati da tutte le righe in una lista in una volta, la memoria si romperà. Nel programma, ogni volta si può memorizzare solo un oggetto generato da una riga.

Ogni stringa separata da virgola, che può avere virgolette doppi (”) o singole ('), ad esempio ”张三”, deve rimuovere le virgolette; se è un numero, come +000000001.24, deve rimuovere il + e gli 0 iniziali e estrarre 1.24

Il documento contiene l'ora, che può essere nel formato 2013-10-29 o 2013/10/29 2:23:56. È necessario convertire queste stringhe in tipo data.

Ci sono molti documenti di questo tipo, ciascuno con attributi diversi, ad esempio questo è l'informazione dell'utente, quello è la cronologia delle chiamate. Pertanto, gli attributi specifici della classe devono essere generati dinamicamente in base alla prima riga del documento.

Procedura di implementazione

1. Definizione della classe

Poiché gli attributi vengono aggiunti dinamicamente, anche le coppie attributo-valore vengono aggiunte dinamicamente. Nella classe devono essere presenti due funzioni membri updateAttributes() e updatePairs(), oltre a utilizzare la lista attributes per memorizzare gli attributi e il dizionario attrilist per memorizzare le mappature. La funzione init() è il costruttore. I variabili di tipo __attributes hanno un trattino sottile davanti, indicando variabili private che non possono essere chiamate direttamente dall'esterno. L'istanziazione richiede solo a=a=UserInfo() senza alcun parametro.

class UserInfo(object):
 'Classe per ripristinare le informazioni dell'utente'
 def __init__ (self):
  self.attrilist={}
  self.__attributes=[]
 def updateAttributes(self,attributes):
  self.__attributes=attributes
 def updatePairs(self,values):
  for i in range(len(values)):
   self.attrilist[self.__attributes[i]]=values[i]

2. Aggiornare dinamicamente ogni oggetto con il generatore (generator) e restituire l'oggetto

Un generatore è una funzione che deve essere inizializzata una volta sola e può essere eseguita automaticamente più volte, restituendo un risultato ogni ciclo. Tuttavia, la funzione restituisce i risultati con return, mentre il generatore li restituisce con yield. Ogni volta che viene eseguito, si ferma alla yield e la prossima volta inizia dopo la yield. Ad esempio, possiamo implementare la serie di Fibonacci utilizzando sia una funzione che un generatore:

def fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  print(b)
  a, b = b, a + b
  n = n + 1
 return 'done'

Calcoliamo i primi 6 numeri della serie:

>>> fib(6)
1
1
2
3
5
8
'done'

Se si utilizza un generatore, è sufficiente sostituire print con yield. Esempio:

def fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  yield b
  a, b = b, a + b
  n = n + 1

Modo d'uso:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
>>> for i in f:
...  print(i)
... 
1
1
2
3
5
8
>>> 

Si può vedere che il generatore fib è un oggetto, ogni volta che si arriva a yield si interrompe e restituisce un risultato, poi continua a eseguire la riga di codice successiva a yield. Il generatore può anche essere eseguito con generator.next().

Nel mio codice del generatore, è così:

def ObjectGenerator(maxlinenum):
 filename='/home/thinkit/Documents/usr_info/USER.csv'
 attributes=[]
 linenum=1
 a=UserInfo()
 file=open(filename)
 while linenum < maxlinenum:
  values=[]
  line=str.decode(file.readline(),'gb2312')#linecache.getline(filename, linenum,'gb2312')
  if line=='':
   print'reading fail! Please check filename!'
   break
  str_list=line.split(',')
  for item in str_list:
   item=item.strip()
   item=item.strip('\"')
   item=item.strip('\'')
   item=item.strip('+0*')
   item=catchTime(item)
   if linenum==1:
    attributes.append(item)
   else:
    values.append(item)
  if linenum==1:
   a.updateAttributes(attributes)
  else:
   a.updatePairs(values)
   yield a.attrilist #Change to ' a ' to use
  linenum = linenum +1

In questo caso, a=UserInfo() è un'istanza della classe UserInfo. Poiché il documento è codificato in gb2312, è stato utilizzato il metodo di decodifica corrispondente. Poiché la prima riga è un attributo, c'è una funzione che inserisce la lista degli attributi in UserInfo, ossia updateAttributes(); Le righe successive devono leggere il pair attributo-valore e inserirlo in un dizionario per memorizzarlo. p.s. Il dizionario in Python è equivalente a una mappatura (map).

3. Rimuovere i caratteri inutili utilizzando strip

Dalla codice sopra, si può vedere che utilizzare str.strip(somechar) è sufficiente per rimuovere i caratteri somechar all'inizio e alla fine di str. somechar può essere un simbolo, può anche essere un'espressione regolare, come sopra:

item=item.strip()#Rimuovere tutti i caratteri di escape all'inizio e alla fine della stringa, come \t, \n, ecc.
item=item.strip('\"')#Rimuovere i caratteri " all'inizio e alla fine
item=item.strip('\'')
item=item.strip('+0*')#Rimuovere i caratteri +00...00 all'inizio e alla fine, * indica che il numero di 0 può essere qualsiasi numero, può anche non esserci

4. Match della stringa con re.match

Sintassi della funzione:

re.match(pattern, string, flags=0)

Descrizione dei parametri della funzione:

parametro         Descrizione

pattern       Espressione regolare da matchare

string         Stringa da matchare.

flags          Indice di segno, utilizzato per controllare il modo di match della espressione regolare, come: se distinguere tra maiuscole e minuscole, match multi-linea, ecc.

Se il match è successo, il metodo re.match restituisce un oggetto di match, altrimenti restituisce None.

>>> s='2015-09-18'
>>> matchObj=re.match(r'\d{4}-\d{2}-\d{2}',s, flags= 0)
>>> print matchObj
<_sre.SRE_Match oggetto at 0x7f3525480f38>
1
2
3
4
5

5. Estrarre una stringa in un oggetto di tempo utilizzando time.strptime

Nel modulo time, time.strptime(str, format) può trasformare str secondo il formato format in un oggetto di tempo, i formati comuni di format sono:

     L'anno in formato a due cifre (%y) (00-99)

     L'anno in formato a quattro cifre (%Y) (000-9999)

     Il mese (%m) (01-12)

     Il giorno del mese (%d) (0-31)

     L'ora in formato 24 ore (%H) (0-23)

     %I ora in formato 12 ore (01-12)

     %M minuti (00-59)

     %S secondi (00-59)

Inoltre, è necessario utilizzare il modulo re, utilizzando espressioni regolari, per abbinare le stringhe e vedere se è nel formato di tempo standard, come YYYY/MM/DD H:M:S, YYYY-MM-DD ecc.

Nel codice sopra, la funzione catchTime determina se item è un oggetto di tempo, se lo è, lo converte in un oggetto di tempo.

Il codice è il seguente:

import time
import re
def catchTime(item):
 # check if it's time
 matchObj=re.match(r'\d{4}-\d{2}-\d{2}',item, flags= 0)
 if matchObj!= None :
  item = time.strptime(item,'%Y-%m-%d')
  #print "returned time: %s " %item
  return item
 else:
  matchObj=re.match(r'\d{4}/\d{2}/\d{2}\s\d+:\d+:\d+',item,flags=0 )
  if matchObj!= None :
   item = time.strptime(item,'%Y/%m/%d %H:%M:%S')
   #print "returned time: %s " %item
  return item

Codice completo:

import collections
import time
import re
class UserInfo(object):
 'Classe per ripristinare le informazioni dell'utente'
 def __init__ (self):
  self.attrilist=collections.OrderedDict()# ordered
  self.__attributes=[]
 def updateAttributes(self,attributes):
  self.__attributes=attributes
 def updatePairs(self,values):
  for i in range(len(values)):
   self.attrilist[self.__attributes[i]]=values[i]
def catchTime(item):
 # check if it's time
 matchObj=re.match(r'\d{4}-\d{2}-\d{2}',item, flags= 0)
 if matchObj!= None :
  item = time.strptime(item,'%Y-%m-%d')
  #print "returned time: %s " %item
  return item
 else:
  matchObj=re.match(r'\d{4}/\d{2}/\d{2}\s\d+:\d+:\d+',item,flags=0 )
  if matchObj!= None :
   item = time.strptime(item,'%Y/%m/%d %H:%M:%S')
   #print "returned time: %s " %item
  return item
def ObjectGenerator(maxlinenum):
 filename='/home/thinkit/Documents/usr_info/USER.csv'
 attributes=[]
 linenum=1
 a=UserInfo()
 file=open(filename)
 while linenum < maxlinenum:
  values=[]
  line=str.decode(file.readline(),'gb2312')#linecache.getline(filename, linenum,'gb2312')
  if line=='':
   print'reading fail! Please check filename!'
   break
  str_list=line.split(',')
  for item in str_list:
   item=item.strip()
   item=item.strip('\"')
   item=item.strip('\'')
   item=item.strip('+0*')
   item=catchTime(item)
   if linenum==1:
    attributes.append(item)
   else:
    values.append(item)
  if linenum==1:
   a.updateAttributes(attributes)
  else:
   a.updatePairs(values)
   yield a.attrilist #Change to ' a ' to use
  linenum = linenum +1
if __name__ == '__main__':
 for n in ObjectGenerator(10):
  print n  # Visualizza il dizionario, controlla se è corretto

Sommario

Questo è tutto il contenuto dell'articolo, spero che possa essere di aiuto per la vostra apprendimento o lavoro. Se avete domande, potete lasciare un commento per discuterle, grazie per il supporto al tutorial urla.

Ti potrebbe interessare