Topic: Ottimizzazione del codice  (Letto 183 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline biagiolicari7

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Ottimizzazione del codice
« il: Febbraio 13, 2019, 19:18 »
salve a tutti ! vorrei alcuni consigli per ottimizzare questo codice..magari per renderlo più pythonico ! grazie mille !
Questa parte di codice mi permette di gestire la classe compress e uncompress e di implementare gli script che ho scritto per eseguire il tutto da terminale.
il programma funziona in tutte le sue parti, ma non riesco a capire se è scritto in maniera adeguata o meno....aspetto i vostri consigli ! Grazie mille.

import os
from src.converter import convertinbits,number_from_bytestring
from pathlib import Path
from src.Compress import Compress,timer
from src.Uncompress import Uncompress,timer_uncompress
import shutil

#from Uncompress import Uncompress
BYTEDIM = 8
pattern = ['.z','.c','.cc','.xml','.html','.py','.htm','.cpp','.rtf','.json','.txt'] #pattern possibili da comprimere
pattern_compressed = ['*.Z', '*.z', '*.lzw']    #pattern lzw       

'''Funzione che legge all'interno di un determinato file compresso e ritorna la stringbit da dare in pasto al decompressore '''       
def read(filename) :
    z = ''
    try :
        f = open(os.path.abspath(filename),'rb')
        try :
            for byte in f.read() :
                z+=(convertinbits(byte,BYTEDIM))
        except (ImportError, EOFError) as ex :
            print('errore imprevisto : ' , ex)
               
    except IOError as ioerr:
        print('File not found :', ioerr)
       
    finally :
        f.close()
       
    return z

''' Funzione che scrive su file la stringa compressa'''
def write(stringbits, filename):
     with open(filename+'.z', "wb") as f:
         if len(stringbits)%BYTEDIM != 0:
             for _ in range(0, BYTEDIM-(len(stringbits)%BYTEDIM)):
                 stringbits += '0' #aggiungo il padding se serve
         numbytes = int(len(stringbits)/BYTEDIM)
         bytevalues = []
         for i in range(0,numbytes):
             bytevalues.append(number_from_bytestring(stringbits[BYTEDIM*i:BYTEDIM*(i+1)]))
         f.write(bytes(bytevalues))
         
'''funzione di ricerca file nel caso in cui is_file() è true, ritorna il codice del file compresso e la sua path abs'''         
def search(filename):
   
    path = Path(filename).resolve()
       
    bin_code = []
    abspath = []
   
    if path.is_file() : #se il path rappresenta un file eseguo i controlli per l'estensione     
        for _ in pattern_compressed : #se il file rientra nelle etensioni previste si esegue la decompressione
            if path.suffix == _[1:] :
                abspath.append(path)
                dec = read(path)
                bin_code.append(dec)
               
    if path.is_dir() : #se il path è un dir si decomprimono tutti i file all'interno
        return 0
       
    return bin_code,abspath

'''funziona che ricerca una dir e ritorna il codice decompresso di ogni file all'interno della dir specificata,in maniera ricorsiva, e relativo path abs '''
def search_dir(dirname) :
    #mposto la Path della directory da considerare, dove cercare i file lzw
    p = Path(dirname).resolve()
       
    abspath = []
    bin_code = []
    for _ in pattern_compressed :
        #Uso la funzione rglob che mi permette di socrrere ricorsivamente le sottocartelle della Path alla ricerca di eventuali file lzw
        for p in p.rglob(_) :#uso rglob per la ricerca ricorsiva
            abspath.append(p.resolve()) #aggiungo la path assoluta alla lista di ritorno
            dec = read(p.resolve()) #richiamo la funzione decompress_file per ogni elelemento lzw all'interno di una qualsiasi dir
            bin_code.append(dec) # aggiungo il testo decompresso ad una lista
       
    return bin_code,abspath

''' Funzione che comprime una intera cartella con annesse subdir presenti all'interno contenenti file compatibili col pattern specificato '''
def write_dir(dirname,dt,verbose) :
   
    p = Path(dirname).resolve()

    for p in p.rglob('*'): #ricerca ricorsiva all'interno del dir Path specificato di file compatili per essere compressi
        if p.suffix == '.z' :
            check_ext(p)
        else :
            if p.suffix in pattern :
                try :
                    size_b = file_size(p) #size prima della compressione per ogni file preso in considerazione
                    f = open(p,'r')
                           
                    if verbose == False:
                        cod_compressed,bin_compressed = Compress(f.read(),dt)
                    elif verbose == True:
                        compress_verbose = timer(Compress)
                        cod_compressed,bin_compressed = compress_verbose(f.read(),dt) #cod_compressed,bin_compressed = Compress(f.read(),dt) #richiamo la definizione di Compressione sul file specificato usando il dizionario o il trie
                        write(bin_compressed,os.path.join(p.parent,p.stem)) #richiamo la funzione che scrive il file compresso
                        f.close()
                        newpath = p.with_suffix('.z')
                        size_a = file_size(newpath)
                        if size_b < size_a:
                            if verbose == True :
                                print("Il file : ", newpath.name, " risulta maggiore dell'originale")
                                newpath.unlink()
                        else:
                            shutil.copymode(p,newpath)
                            p.unlink()
                except IOError :
                    print('errore in apertura di ', p)
               
                                             

'''funzione che comprime un determinato file inerente al pattern impostato'''
def write_file(filename, dict_or_trie,verbose,ric):
    path = Path(filename).resolve()
   
    if path.is_dir() and ric == True : #nel caso in cui la modalita ricorsiva sia attiva e il file passato è una dir, chiamo la funzione write_dir()
        b_size = directory_size(path)
        write_dir(path,dict_or_trie,verbose)
        a_size = directory_size(path)
        if verbose == True:
            percent = (b_size - a_size)/b_size * 100
            print("Compressione avvenuta del {} %".format(percent))           
     
    elif path.is_file() and ric == False  :
        if path.suffix == '.z' or path.suffix == '.Z' :
            check_ext(path) #controllo se file è stato già compresso e nel caso modifico estensione

        else :
            try :
                size_before = file_size(path) #calcolo dimensione prima della compressione
                f = open(path,'r')
               
                if verbose == False:
                    cod_compressed,bin_compressed = Compress(f.read(),dict_or_trie)
                if verbose == True: #se la modalita verbose è attiva applico il decoratore timer alla funzione compress
                    compress_verbose = timer(Compress)
                    cod_compressed,bin_compressed = compress_verbose(f.read(),dict_or_trie)
                   
                write(bin_compressed,os.path.join(path.parent,path.stem))#richiamo la funzione write
                f.close()
                newpath = path.with_suffix('.z')
                size_after = file_size(newpath) #calcolo la dimensione del file post_compressione
                if size_before < size_after:
                    newpath.unlink() #se la dimensione pre-compressione è superiore elimino il file compresso
                   
                else:
                    shutil.copymode(path,newpath)
                    path.unlink()
                   
                if verbose == True:
                    if not newpath.exists():
                        print("Il file : ", newpath.name, " risulta maggiore dell'originale")
                        return
                    percent = (size_before - size_after)/size_before * 100
                    print("Compressione avvenuta del {} %".format(percent))
                   
            except IOError as ex :
                print('Errore nel file : ', ex)
    else :
        print("Inserire correttamente le opzioni di ricerca " )
        return -1
           
    return 0

'''funzione che nel caso in cui il file sia gia compresso con estensione .z, ne modifica l'estensione'''
def check_ext (path): 
        base = os.path.splitext(path)[0]
        os.rename(path,base+".Z")
       
'''funzione che ritorna la dim in bytes del file passato come argomento'''
def file_size(fname):
    path = Path(fname)
    if path.is_file() :
        statinfo = os.stat(path)
        return statinfo.st_size
    elif path.is_dir() :
        dir_size = directory_size(path)
        return dir_size
   
'''funzione che ritorna la dimensione della dir passata come argomento, in bytes'''
def directory_size(path):
    total_size = 0
    seen = set()

    for dirpath, dirnames, filenames in os.walk(path): #ricerca ricorsiva all'interno della dir
        for f in filenames:
            fp = os.path.join(dirpath, f)

            try:
                stat = os.stat(fp)
            except OSError:
                continue

            if stat.st_ino in seen:
                continue

            seen.add(stat.st_ino)

            total_size += stat.st_size
        return total_size  # size in byte

           

'''Funzione che dato un path, una delle st_dati possibili e un argomento -r permettere di decomprimere un/a file/dir'''
def Uncompress_file(filename,dt,r,verbose):
    i = 0
   
    filename = Path(filename).resolve()
   
    if r == False and filename.is_file() :
        bin_cod,path = search(filename) #richiamo la funzione di ricerca file/dir
       
    elif r == True and filename.is_dir() :
        bin_cod,path = search_dir(filename)
    else :
        print("Inserire correttamente le opzioni di ricerca ")
        return -1

    for _ in bin_cod :
       
        if verbose == True:
            uncompress_verbose = timer_uncompress(Uncompress) #richiamo decoratore timer_uncompress nel caso in cui la modalita verbose sia attiva
            dec = uncompress_verbose(_,dt) #ottengo stringa decompressa
        elif verbose == False:
            dec = Uncompress(_,dt) #ottengo stringa decompressa
           
        name = Path(path[i]) #estraggo path del file decompresso
        f = open(os.path.join(name.parent,name.stem+'.txt'), 'w') #creazione nuovo file decompresso
        f.write(dec)
        f.close()
        shutil.copymode(name, os.path.join(name.parent,name.stem+'.txt'))
        name.unlink() #rimuovo il file compresso
        i += 1
       



« Ultima modifica: Febbraio 13, 2019, 19:20 da biagiolicari7 »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.859
  • Punti reputazione: 9
    • Mostra profilo
Re:Ottimizzazione del codice
« Risposta #1 il: Febbraio 13, 2019, 22:08 »
Avrei due suggerimenti.

Il primo è di rendere più ottimizzato e pythonico NON il tuo codice, ma per cominciare questo tuo post. "Mi permette di gestire la classe compress e uncompress e di implementare gli script" EEEHHH????? Scusa che cosa dovremmo sapere noi, che non ci stai dicendo? Tu dai per scontato che chi legge magia a colazione pane e src.converter, e beve acqua e src.Compress (con la lettera maiuscola... boh). Non so gli altri, ma io non ho la più pallida idea di che cosa si suppone che questo codice debba fare, con quali librerie deve lavorare, etc. Se non fornisci un (bel) po' di contesto, non è che abbiamo la sfera di cristallo.

Il secondo consiglio è questo: se vuoi ottimizzare e rendere più pythonico quel codice, aspetta sei mesi senza toccarlo, senza leggerlo, facendo altro. Altre cose, altro codice, altri pensieri, altri progetti. Poi, il 13 agosto sotto l'ombrellone prova a rileggerlo e vedi quello che riesci a capire. Lo shock di quello che scoprirai ti porterà sicuramente a ottimizzare il codice e renderlo più pythonico. A partire da un rispetto totale della Pep8, e da una documentazione ossessiva.

Offline biagiolicari7

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re:Ottimizzazione del codice
« Risposta #2 il: Febbraio 13, 2019, 23:10 »
Mi scuso se sono stato poco chiaro, ma ho dovuto scrivere di fretta. Metto qui l'intero codice. Il progetto è da consegnare per completare un'esame universitario e, nel caso in cui ci siano cose che non siano corrette, vorrei dei consigli su come migliorare per scrivere un buon codice da poter presentare.
Il progetto richiesto è la creazione di un Compressore/Decompressore LZW eseguibile da linea di comando con 'Compress  [-verbose] [-r] [file....]'

Compress.py implementa la compressione tramite dict o albero presenti in stdati.py


from src.stdati import trie, lzw_dict
from src.converter import convertinbits
import time

def timer(func):
    def inner(*args, **kwargs):
        t1 = time.time()
        f = func(*args, **kwargs)
        t2 = time.time()
        print('Compress Algorithm took {} seconds'.format(t2-t1))
        return f
    return inner


def Compress(input_File, char):
   
    stringa_compressa = []
    bitstring = ""
    if char == "D" or char == "d" :
        T = lzw_dict()
   
    elif char == "T" or char == "t" :
        T = trie()

    else :
        T = lzw_dict()       
       
    dim = len(input_File)
    counter = 0
    numbits = 9
    #ciclo che esamina ogni carattere   
    for C in input_File:
        #provo a cercare il prossimo carattere
        val = T.search(C)
        counter = counter + 1 #incremento il contatore dei caratteri
       
        if T.check() :
            stringa_compressa.append(val)
            if T.dim-1 == 2**numbits: #dim è ora il prossimo valore che verrà associato, il valore massimo attuale è T.dim-1:
                numbits = numbits + 1 #so di avere valori fino a T.dim-1
               
            bitstring = bitstring + convertinbits(val,numbits)
            val = T.search(C)
       
        #siamo arrivati alla fine e ci troviamo in un nodo intermedio, scriviamo il valore
        if counter == dim : #AND NOT CHECK???
            stringa_compressa.append(val) #non è necessario controllare T.dim
            bitstring = bitstring + convertinbits(val,numbits)
   
    stringa_compressa.append(256);
    bitstring = bitstring + convertinbits(256,numbits)

    return stringa_compressa, bitstring



    ''' Classe che rappresenta un trie. Utilizza le liste di adiacenza.
        La struttura consiste in una lista contenente coppie di valori.
        Il primo valore indica il nodo, il secondo è la sua lista di adiacenza
        contenente ulteriori coppie di valori (child, label)'''
   
    def __init__(self):
        self.__nodes = []
        self.__dim = 257 #END compreso
        #self.__root = -1
        self.__mynode = -1
        self.__nodes.append((-1,[]))
        for i in range(0,self.__dim):
            self.__nodes[0][1].append((i,chr(i)))
            self.__nodes.append((i,[]))
       
       
        super().__setattr__('nodes',self.__nodes)
        super().__setattr__('dim',self.__dim)
        super().__setattr__('mynode',self.__mynode)
   
    @property
    def nodes(self):
        return self.__nodes
   
    @nodes.setter
    def nodes(self, nodes_list):
        self.__node = nodes_list
   
    @property
    def dim(self):
        return self.__dim
   
    @dim.setter
    def dim(self, newdim):
        self.__dim = newdim
   
    @property
    def mynode(self):
        return self.__mynode
   
    @mynode.setter
    def mynode(self, newmynode):
        self.__mynode = newmynode
   
    '''Stampa la lista di adiacenza. Viene usata da print().'''
    def __str__(self):
        s = ""
        for i in range(0,len(self.__nodes)):
            s = s + self.__nodes[i][0].__str__() + " --> " + self.__nodes[i][1].__str__() + "\n"
        return s
   
    '''Funzione che aggiunge un nodo alla lista'''
    def addnode(self, node):
        self.__nodes.append((node,[]))
   
    '''Funzione che permette di creare un arco da node a child con una label'''
    #si sfrutta la sequenzialità dei nodi. Ogni valore del nodo sta al node+1 posto nella lista
    def addchildtonode(self, node, child, label):
        self.__nodes[node+1][1].append((child, label))
       
    '''Funzione che cerca il prossimo carattere a partire dal nodo attuale.
       Ritorna il valore del nodo figlio del nodo attuale che ha come label
       nell' arco il carattere se questo arco esiste, modificando il nodo
       attuale con il figlio, altrimenti torna il nodo, attuale e lo modifica
       con -1, tornando così alla radice.'''
    def search(self, char):
        #la lista dei figli non è vuota, cerco il valore con l'arco che ha label il carattere che cerco
        if self.__nodes[self.__mynode+1][1]:
            nodi_child = self.__nodes[self.__mynode+1][1] #ottengo la lista di adiacenza del node
            for i in range(0, len(nodi_child)):
                if nodi_child[i][1] == char:
                    self.__mynode = nodi_child[i][0]
                    return self.__mynode
        #se la lista di adiacenza del nodo attuale è vuota (il nodo attuale non ha figli)
        #o se non è stata trovata una label con il carattere cercato
        #aggiugo il figlio alla lista dei nodi, lo aggiungo come figlio del nodo attuale e
        #salvo il nodo attuale per il ritorno, modificando poi il nodo attuale con -1
        self.addnode(self.__dim)
        self.addchildtonode(self.__mynode, self.__dim, char)
        self.__dim = self.__dim + 1
        value = self.__mynode
        self.__mynode = -1
        return value
   
    '''Funzione che torna True se ancora non si è ricominciato da capo nel trie '''
    def check(self):
        #Il check è vero se siamo nella root, quindi se il valore di mynode = -1
        if self.__mynode == -1:
            return True
        else:
            return False
       
   
class lzw_dict() :
    '''Classe che implementa un dizionario, sfruttando la coppia <chiave,valore>, per implementare la compressione/decompressione di Lempel-Ziv-Welch'''

    def __init__(self) :
        self.__dim = 257 #END compreso
        self.__dict = {chr(i) : i for i in range(self.dim)} #costruisco il dizionario con coppia <chr(i),i)>
        self.__curr = ""
        self.__controllo = 0
        self.__value = 0
        self.__key = ""
       
       
        super().__setattr__('dict',self.__dict)
        super().__setattr__('dim',self.__dim)
        super().__setattr__('curr',self.__curr)
        super().__setattr__('controllo',self.__controllo)
        super().__setattr__('vaue',self.__value)
        super().__setattr__('key',self.__key)
       
       
    @property
    def controllo(self):
        return self.__controllo
   
    @controllo.setter
    def controllo(self, chk):
        self.__controllo = chk

    @property
    def value(self):
        return self.__value
   
    @value.setter
    def controllo(self, val):
        self.__value = val
   
    @property
    def key(self):
        return self.__key
   
    @key.setter
    def key(self, k):
        self.__key = k
   
    @property
    def dim(self):
        return self.__dim
   
    @dim.setter
    def dim(self, newdim):
        self.__dim = newdim
       
    @property
    def dict(self):
        return self.__dict
   
    @dict.setter
    def dict(self, newdict):
        self.__dict = newdict
 
   
    '''Funzione che stampa il dizionario'''
    def __str__(self) :
        return self.__dict


    def search(self, char) :
        self.__key = self.__curr + char
        '''se il valore di key è presente nel dizionario, ritorno col valore presente nel dizionario creato.'''
        if self.__key in self.__dict : #         
           self.__curr = self.__key
           self.__controllo= 0
           self.__value = self.__dict[self.__key]
        #altrimenti aggiungo tale valore al dizionario, andando ad impostare curr pari a "" per la prossima iterazione
        else :           
            self.__dict[self.__key] = self.__dim
            self.__dim += 1
            self.__curr = ""
            self.__controllo = -1

        return self.__value
       



    def check(self) :
        if self.__controllo == -1 :
            return True
        else :
            return False
           
'''Nella decompressione per ricostruire un path a partire da un valore è
importante conoscere il padre di un nodo, che è unico.
Il trie per la decompressione è un dizionario che associa a ogni nodo una
coppia (father,label)'''

class trie_uncompression:
   
    def __init__(self):
        self.__lastencoded = ""
        self.__lastnode = -1
        self.__dim = 257
        self.__dict_for_trie = {i : (-1, chr(i)) for i in range(self.dim)}
       
        super().__setattr__('lastencoded',self.__lastencoded)
        super().__setattr__('last',self.__lastnode)
        super().__setattr__('dim',self.__dim)
        super().__setattr__('dict_for_trie',self.__dict_for_trie)
       
    @property
    def lastencoded(self):
        return self.__lastencoded
   
    @lastencoded.setter
    def lastencoded(self, encoded):
        self.__lastencoded = encoded
   
    @property
    def last(self):
        return self.__lastnode
   
    @last.setter
    def last(self, node):
        self.__lastnode = node
   
    @property
    def dim(self):
        return self.__dim
   
    @dim.setter
    def dim(self, newdim):
        self.__dim = newdim
       
    @property
    def dict_for_trie(self):
        return self.__dict_for_trie
   
    @dict_for_trie.setter
    def dict_for_trie(self, newdict):
        self.__dict_for_trie = newdict


    def __str__(self):
        return self.__dict_for_trie.__str__()
   
    def find(self,value):
        #condizione di proiezione
        if value == self.__dim:
            string = self.__lastencoded + self.__lastencoded[0]
            self.__lastencoded = string
            self.__dict_for_trie[value] = (self.__lastnode, string[0])
            self.__lastnode = value
            self.__dim = self.__dim + 1
            return string
       
        edge = self.__dict_for_trie[value]
        string = edge[1] #prima label dell'arco
        while edge[0] != -1: #finche il padre dell'arco non è -1
            edge = self.__dict_for_trie[edge[0]] #guardo il nodo padre
            string = edge[1] + string
       
        self.__dict_for_trie[self.__dim] = (self.__lastnode, string[0])
        self.__dim = self.__dim + 1
        self.__lastencoded = string
        self.__lastnode = value
        return string
   
   
class Dict_uncompression:
    def __init__(self) :
        self.__dim = 257
        self.__dictionary = {i : chr(i) for i in range(self.dim)}
        self.__curr = ""
        self.__lastencoded = ""
           
        super().__setattr__('last') #ACCETTABILE???
        super().__setattr('dim',self.__dim)
        super().__setattr('dictionary',self.__dictionary)
        super().__setattr('curr',self.__curr)
        super().__setattr('lastencoded',self.__lastencoded)
       
    @property
    def last(self):
        return
   
    @last.setter
    def last(self, node):
        return
   
    @property
    def dim(self):
        return self.__dim
   
    @dim.setter
    def dim(self, newdim):
        self.__dim = newdim
       
    @property
    def curr(self,newcurr):
        self.__curr = newcurr
       
    @curr.setter
    def curr(self):
        return self.__curr
   
    @property
    def lastencoded(self):
        return self.__lastencoded
   
    @lastencoded.setter
    def lastencoded(self, encoded):
        self.__lastencoded = encoded
       
    @property
    def dictionary(self):
        return self.__dict_for_trie
   
    @dictionary.setter
    def dictionary(self, newdict):
        self.__dict_for_trie = newdict
       
    def find(self,v) :
        if v in self.__dictionary:
            self.__curr = self.__dictionary[v]
            self.__dictionary[self.__dim] = self.__lastencoded+self.__curr[0]
            self.__dim += 1
            self.__lastencoded = self.__curr
            return self.__lastencoded
        else: #proiezione
            self.__dictionary[self.dim] = self.__lastencoded + self.__lastencoded[0]
            self.__dim += 1
            self.__curr = self.__dictionary[v]
            self.__lastencoded = self.__curr
            return self.__lastencoded
           


uncompress.py implementa la decompressione tramite dizionario o albero

from src.stdati import trie_uncompression,Dict_uncompression
from src.converter import convertinint
import time

def timer_uncompress(func):
    def inner(*args, **kwargs):
        t1 = time.time()
        f = func(*args, **kwargs)
        t2 = time.time()
        print('Uncompress Algorithm took {} seconds'.format(t2-t1))
        return f
    return inner


def Uncompress(bitstring,td):
    #MANCA IL CASO PARTICOLARE
   
    if td == 't' or 'T' or 'trie' :
        T = trie_uncompression()
    elif td == 'd' or 'D' or 'dict' :
        T = Dict_uncompression()
    else:
        T = trie_uncompression()
       
    numbits = 9
    val = convertinint(bitstring[0:numbits],numbits)
    string = chr(val)

    T.lastencoded = string
    T.last = val #nel caso del trie salva l'ultimo nodo, nel dict non fa nulla
    indexiniziale = 0
    indexfinale = 9
   
    while val != 256:       
        if T.dim + 1 == 2**numbits:
            numbits = numbits+1     
        indexiniziale = indexfinale
        indexfinale = indexfinale + numbits
        valstring = bitstring[indexiniziale:indexfinale]
        val = convertinint(valstring, numbits)
 
        if val != 256:
            string = string + T.find(val)
   
    return string



BYTEDIM = 8
 
''' Funzione che converte un valore intero in una stringa "0/1" '''       
def convertinbits(value, numbits):
    B = ''
    for _ in range(0,numbits):
        B = str(int(value)%2) + B
        value = int(value)/2
    return B

''' Funzione che converte una stringa "0/1" in un valore intero '''   
def convertinint(bits, numbits):
    value = 0
    for i in range(0,numbits):
        bit = bits[numbits-1-i]
        value = value + (2**i) * int(bit)
    return value

''' Funzione che dato in ingresso una stringa rappresentante un byte, torna il valore numerico di quel byte '''
def number_from_bytestring(bitstring):
    v = 0
    power = [2**i for i in range(0,BYTEDIM)]
    for j in range(0,BYTEDIM):
        v = v + int(bitstring[j])*power[BYTEDIM-1-j]
    return v



script Compress
import argparse
import src.File_Manager, src.converter
from pathlib import Path


parser = argparse.ArgumentParser()  # Creiamo il nostro parser
parser.add_argument('file',help='lista file o dir da comprimere con lzw', nargs = '+', action = 'store') #aggiungo l'argomento di tipo lista da usare per la compressione/decompressione file/dir
gruppo_r = parser.add_argument_group() # Creiamo il gruppo necessario per le opzioni ricorsive
gruppo_stdati = parser.add_mutually_exclusive_group() #gruppo opzioni dict o trie
gruppo_v = parser.add_argument_group() #opzione verbose
gruppo_r.add_argument("-r", "--ricorsivo", action="store_true", help = 'opzione per la ricerca ricorsiva all interno di dir') #argomento -r che permette la ricerca ricorsiva se file = dir
gruppo_stdati.add_argument("-t","--trie", action="store_true", help = 'opzione per usare LZW tramite struttura Trie') #argomento st_dati trie
gruppo_stdati.add_argument("-d","--dict", action="store_true", help = 'opzione per usare LZW tramite struttura Dict')#argomento st_dati dict
parser.add_argument("-v","--verbose", action="store_true", help = 'opzione per visualizzare la verbose ')

arg = parser.parse_args() #parse degli argomenti passati

for _ in arg.file:
    if not Path(_).exists() :
        print(_,' Not Found !!')

    else :
       
        if arg.trie:
            src.File_Manager.write_file(_,'t',arg.verbose,arg.ricorsivo)
        elif arg.dict :
            src.File_Manager.write_file(_,'d',arg.verbose,arg.ricorsivo)
        else:
            src.File_Manager.write_file(_,'t',arg.verbose,arg.ricorsivo)

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.453
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re:Ottimizzazione del codice
« Risposta #3 il: Febbraio 16, 2019, 01:27 »
Allora, scusami sono brutale. Per "metterlo a posto" dal punto di vista *reale*, mi spiace, ma essenzialmente fai quasi prima a riscriverlo. Non mi sembra questa la dimensione in cui devi muoverti: e' solo un esame universitario.
Quindi cerchiamo di capire cosa si possa fare per renderlo un po' sensato. Essenzialmente faro' focus su roba semplice che puoi fare in fretta.

1. guardati come si fanno le docstring in python. apri un modulo qualunque della libreria standard, e fai la stessa cosa. costo minuscolo, eviti roba che davvero e' un pugno in un occhio.
2. Come gia' notato, la PEP8 non e' considerata opzionale nel mondo reale, ma in universita' dubito che ne siano a conoscenza
3. Nel mondo reale __ e' una cosa diversa da _ e tu usi __ per intendere _. Se il tuo docente non lo sa/non gli interessa, lascia perdere. Ma sappilo tu.
4. concatenare le stringhe a quel modo e' grossolano, inefficiente e grida inesperienza. questo dovresti davvero metterlo a posto.
5. La OOP non va, ma non credo sara' un problema
6. evita quegli obrobri con __setattr__. Se vuoi fare show off con un po' di metaprogrammazione, fallo a criterio. Questo e' gratuito.
7. __str__ e' un massacro
8. avresti potuto scrivere la meta' del codice evitando un sacco di roba inutile. ho il sospetto che sia lo stile che vi viene insegnato; non e' saggio per te avere questa discussione con il docente, fai quello che piace a lui.
9.