Topic: Non capisco un pezzo di codice in micropython  (Letto 173 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline giannican

  • python unicellularis
  • *
  • Post: 2
  • Punti reputazione: 0
    • Mostra profilo
Non capisco un pezzo di codice in micropython
« il: Giugno 09, 2020, 18:37 »
Salve a tutti, ho un pezzo di codice che non riesco a capire, scritto in micropython. Uso il linguaggio blockly su ide UIFlow. Devo fare un progetto con M5StickC. Ciò che mi risulta abbastanza ostico, è il ciclo, e soprattutto come fa il codice a settare "valore" per ogni variabile che gli arriva. Uso l'esp now e riceve in ingresso come "dato" 3 variabili (Get_x, Get_y, Pos) in loop. Purtroppo sono alle prime armi con python e non ho tempo per ora di approfondire, quindi ve ne sarei lieto se mi spiegaste meglio come funziona e in che modo legge le stringhe.
Le variabili che userò sono quelle 3 che ho scritto prima e l'unico modo per usarle è convertirle in un int.
link al blockly: https://ibb.co/QjYRRmM
grazie mille a tutti

def upRange(start, stop, step):
  while start <= stop:
    yield start
    start += abs(step)

def downRange(start, stop, step):
  while start >= stop:
    yield start
    start -= abs(step)


def recv_cb(_):
  global mac,dato,cmd,Tempo,valor,Get_x,Get_y,Pos,j
  mac, _, dato = espnow.recv_data(encoder='str')
  cmd = dato[0]
  valor = ''
  j_end = float(len(dato))
  for j in (2 <= j_end) and upRange(2, j_end, 1) or downRange(2, j_end, 1):
    valor = (str(valor) + str(dato[int(j - 1)]))
  if cmd == 'X':
    Get_x = valor
    label0.setText(str((str('X') + str(Get_x))))
  elif cmd == 'Y':
    Get_y = valor
    label1.setText(str((str('Y') + str(Get_y))))
  elif cmd == 'P':
    Pos = valor
    label2.setText(str((str('P') + str(Pos))))

  pass
espnow.recv_cb(recv_cb)
« Ultima modifica: Giugno 09, 2020, 18:48 da giannican »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.151
  • Punti reputazione: 9
    • Mostra profilo
Re:Non capisco un pezzo di codice in micropython
« Risposta #1 il: Giugno 09, 2020, 23:03 »
Uhm... sì d'accordo ma capisci che tutta la premessa di quello che scrivi è... un po' bizzarra, diciamo (eufemismo).
Butti là uno stack di tecnologie lungo un chilometro (micropython... blockly... uiflow... m5stickc... nient'altro?) e poi il tuo problema è che non ti è chiaro come funziona un ciclo python... capisco, per carità... ma è come se tu dicessi che vuoi cucinare una boeuf bourguignon e l'unica cosa che non ti è ben chiara è come far bollire l'acqua.

Poi io capisco che uno possa aver "bisogno" di cucinare una boeuf bourguignon in poco tempo, ma... che posso dire... anche io avrei bisogno di un miliardo di euro in poco tempo.

In tutto questo la cosa che davvero non mi è chiara è *perché* hai bisogno di capire come funziona il ciclo... voglio dire, tu stai generando codice Python con blockly... se per qualche ragione quello che hai fatto non ti funziona, non è che puoi metterti a modificare il codice generato... devi modificare qualcosa in blockly... se ti metti a modificare il codice generato da blockly, tanto vale che lasci perdere blockly, ti metti a studiare python e ti scrivi il codice a mano (cosa che ti consiglio, peraltro).

Detto questo, mah... nessun problema a spiegarti quel pezzo di codice... ma la cosa che devi metterti in testa prima di tutto è questa Verità Assoluta Fondamentale: blockly genera codice Python di qualità strepitosamente pessima. Quindi non devi assolutamente pensare che il codice python generato da blockly sia neanche lontanamente indicativo di "come si fanno le cose in python"... anzi è esattamente l'opposto: blockly ti dice come le cose NON si fanno in python.

Per cominciare, le due funzioni upRange e downRange non fanno altro che re-inventare daccapo la funzione predefinita Python "range"... e perché blockly dovrebbe re-inventare "range"? Semplicemente perché blockly non "sa" che in python esiste "range"... blockly è fatto per generare indifferentemente codice python, javascript, php... e non tutti questi linguaggi hanno qualcosa come "range" nella loro cassetta degli attrezzi... quindi blockly preferisce andare sul sicuro e la re-inventa daccapo. In sostanza, upRange produce sequenze numeriche crescenti del tipo [3, 4, 5, 6], e downRange produce sequenze decrescenti del tipo [12, 11, 10, 9].

Capito questo, capito questo, la riga 18 del tuo codice è un po' difficile da leggere... si tratta di un idioma assolutamente estraneo a Python, ma invece molto comune nei linguaggi che non dispongono di un "immediate if" (a dire il vero era usato anche in Python, prima che Python disponesse appunto di un costrutto "immediate if"). In pratica quella riga decide se usare "upRange" o "downRange" a seconda della lunghezza di "dato" (calcolata alla riga precedente). Ovvero, se contare in modo crescente o decrescente.

Tutto questo in Python si esprimerebbe meglio dicendo qualcosa come:

j_end = len(dato) # la riga 17
step = 1 if j_end >= 2 else -1 # "immediate if" Python
for j in range(2, j_end, step):  # "range" Python
    # etc etc


Risolto questo pasticcio... boh, il resto è semplice. La variabile "valor" (bel nome, eh) inizialmente è impostata alla stringa vuota (riga 16). A ogni passaggio del ciclo, viene "aumentata" del successivo elemento di "dato" (riga 19). E siccome nella riga 18 tu hai previsto che in ogni caso, sia upRange sia downRange finiscano la loro sequenza con "j_end", in pratica *non ha importanza* se tu alla riga 18 hai scelto upRange o downRange. In entrambi i casi l'ultimo valore assegnato a "j" sarà "j_end", ovvero la lunghezza di "dato". E di conseguenza in ogni caso alla fine del ciclo "valor" sarà incrementata di *tutti* gli elementi di "dato" a eccezione del primo (che resta fuori dal ciclo).

Quindi in pratica alla fine "valor" sarà uguale a "dato", tranne il primo elemento. Puoi facilmente verificarlo provando il codice in una shell di Python (se sei capace ad aprire una shell di Pyhton).

>>> def upRange(start, stop, step):
        while start <= stop:
            yield start
        start += abs(step)

>>> def downRange(start, stop, step):
        while start >= stop:
            yield start
        start -= abs(step)

>>> def test(dato):
        j_end = float(len(dato))
        valor = ''
        for j in (2 <= j_end) and upRange(2, j_end, 1) or downRange(2, j_end, 1):
            valor = valor + str(dato[int(j-1)])
        return valor

>>> test('ciao')
'iao'
>>> test('una stringa lunghiiiiiiissima')
'na stringa lunghiiiiiiissima'
>>> test('ab')
'b'


Tutto questo ovviamente in Python si esprimerebbe dicendo

valor = dato[1:]

e fine della storia.

Ora, non ho la più pallida idea se questo sia un comportamento atteso, voluto, ricercato, oppure sia banalmente un garbuglio di codice combinato da te e/o da blockly... e non ho idea, in questo caso, di che cosa tu e blockly aveste in mente di fare... ma in ogni caso, quel ciclo funziona così.

Offline giannican

  • python unicellularis
  • *
  • Post: 2
  • Punti reputazione: 0
    • Mostra profilo
Re:Non capisco un pezzo di codice in micropython
« Risposta #2 il: Giugno 10, 2020, 12:07 »
La premessa l'ho inserita per presentare quello che uso e far capire qual è il mio scopo diciamo.. passami la similitudine, ma non si può cucinare una boeuf bourguignon senza sapere cos'è ahhahah.. scherzi a parte, ho dimenticato di dire che il progetto che devo fare è per il tirocinio e non ho tempo perchè dovrei laurearmi, ecco tutto.
Detto questo mi serviva capire come funzionava il ciclo perchè l'ho visto usare su un altro codice (ecco perchè la variabile si chiamava valor, bel nome ahahahha) e l'ho adattato a quello che mi serviva, ma non mi era ben chiaro come funzionasse precisamente. Python sarà oggetto di studio in un futuro molto vicino e per ora mi serviva solo questo.
Ovviamente ti ringrazio infinitamente per come mi hai spiegato tutto, davvero zelante e molto preciso, grazie mille.