[Risolto][Python] Nuovo oggetto dopo concatenazione o sezionamento

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

[Risolto][Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da gila75 »

Buon giorno a tutti, sto affrontando il capitolo sul sezionamento e la concatenazione di stringhe e liste.
Alla risoluzione di un esercizio, il mio manuale dice che viene sempre creato un nuovo oggetto, ma a me non risulta.
O meglio con gli oggetti immutabile (es. stringhe) si, ma con i mutabili dipende:

Qui per esempio non cambia:

Codice: Seleziona tutto

l=[1,2,3,4]
>>> id(l)
139920980686536
>>> l+=[6,7,8]
>>> l
[1, 2, 3, 4, 6, 7, 8]
>>> id(l)
139920980686536
>>>


qui si:

Codice: Seleziona tutto

>>> l=[1,2,3,4,5]
>>> id(l)
139920983095432
>>> l=l+[5,6,7]
>>> l
[1, 2, 3, 4, 5, 5, 6, 7]
>>> id(l)
139920983096392
>>> 

Il perchè è abbastanza ovvio : l=l+1 diverso da l+=1. Allora perchè il manuale mi dice così?
Impapare Python è il mio libro, non l'ultima ciofeca da 10 euro.
Accodo seconda domanda (mi pare sciocco aprire un 3d apposta) :
Non trovo la spiegazione a questo:
Cosi' è lecito:

Codice: Seleziona tutto

>>> l=[1,2,3,]
>>> l+='concateno str'
>>> l
[1, 2, 3, 'c', 'o', 'n', 'c', 'a', 't', 'e', 'n', 'o', ' ', 's', 't', 'r']
>>> 
qui no:

Codice: Seleziona tutto

>>> l=[1,2,3,4,5,6]
>>> l[:2]+'xxxxx'+l[3:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
>>> 
perchè non posso inserire una stringa in lista ? (le liste lo consentono)
posso però così:

Codice: Seleziona tutto

>>> l[:2]+list('xxxx')+l[3:]
[1, 2, 'x', 'x', 'x', 'x', 4, 5, 6]
>>>

non so forse inserendo direttamente nel sezionamento non calcola la lunghezza...non so.
Oppure alla fine accoda in stile append() in mezzo sarebbe una sorta di insert (miei azzardi, non so)
Questo non mi viene detto sul manuale. Provo a ricercare ancora.
Grazie
Ultima modifica di gila75 il venerdì 8 aprile 2022, 15:06, modificato 1 volta in totale.
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2854
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da DoctorStrange »

Io la vedrei in questo modo, ma non programmo in python, quindi mi riservo il beneficio del dubbio.

Per quanto riguarda la prima domanda, devi vedere l'operatore "+", in maniera diversa da come non lo si tratta comunemente. Il "+": somma, a livello di programmazione è un'operazione a tutti gli effetti definita ed associata ad ogni collection, al pari di come lo può essere l'estrazione del comune multiplo o di aaltre operazioni di aggregazione o riduzione, che posso venir definite separatamente dallo sviluppatore.

L'operatore somme, quando applicato a collection di tippo mutable od immutable, ha comportamenti diversi, in particolare, usare "+", oppure "+=" genera risultati diversi, soprattutto quando applicato a variabili di tipo immutable.

In quiesto secondo caso infatti è normale che venga generata una seconda variabile "copia" della prima, alla quale viene applicata la trasformazione che chiedi.

Se questo comportamento per le tue esigenze non è idoneo, puoi provare a "ridefinire" il comportamento dell'operatore somma con un'override e definendo una funzione separata, ma non capisco quale beneficio tu possa trarne.

PPer quanto riguarda il tuo secondoo dubbio, da quanto mi sembra di capire dal frammento di codice che hai postato, mi sembra essere semplicemente un errore di sintassi.

Scrivere:

Codice: Seleziona tutto

l[:2]+'xxxxx'+l[3:]
Non va bene, semplicemmente perche

Codice: Seleziona tutto

'xxxxx'
viene interpretato come una stringa, e non come un indice, quindi il compilatore ti dice: impossibile concatenare una stringa semplice (che sarebbe proprio xxxxx), ad una coppia di indici. Qui devi semplicemente creare un secondoo array, ci metterai dentro la tua stringa ('xxxxx') e poi passerai questo array all'operatore di concatenazione sopra.

In pratica, non puoi mischiare stringhe, puntatori ed indici, e pretendere che la concatenazione funzioni regolarmente.

Detto questo ti chiedo: ti è chiara la distinzione tra caratteri di quoting forte e debole? Per quale motivo usi sempre i caratteri di apice singolo ( ' ) ?
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da gila75 »

Grazie DoctorStrange.

Il primo quesito l'ho risolto, come detto l=l+1 non è l+=1. E qui ci siamo.
Non capisco appunto perchè il libro dica che sezionamento e concatenamento creano sempre nuovi oggetti.
Sono nuovi per i tipi immutabili, ovvio.
Detto questo ti chiedo: ti è chiara la distinzione tra caratteri di quoting forte e debole? Per quale motivo usi sempre i caratteri di apice singolo ( ' ) ?
in Python mi pare che per le stringe si possa usare entrambi:

Codice: Seleziona tutto

>>> a="casa"
>>> a
'casa'
>>> b='xxxxx'
>>> b
'xxxxx'
>>> 
viene interpretato come una stringa, e non come un indice, quindi il compilatore ti dice: impossibile concatenare una stringa semplice (che sarebbe proprio xxxxx), ad una coppia di indici. Qui devi semplicemente creare un secondoo array, ci metterai dentro la tua stringa ('xxxxx') e poi passerai questo array all'operatore di concatenazione sopra.
Molto probabilmente è così. Quello che mi confonde è che la puoi accodare e lui risolve in automatico da srt a list:

Codice: Seleziona tutto

>>> l=[1,2,3,]
>>> l+='casa'
>>> l
[1, 2, 3, 'c', 'a', 's', 'a']
>>>
sa di quanti caratteri è 'casa' e aumenta gli indici lista, infatti:

Codice: Seleziona tutto

>>> l[5]
's'
>>> 
mia aspettavo che (come risolve la lunghezza di str in fondo e aumenta gli indici) lo facesse anche in mezzo.
é una cosa che ritengo importante capire fin dall'inizio i sezionamenti, concatenamenti ecc...
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2854
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da DoctorStrange »

Le operazioni con gli array sono sempre molto elementari. Nell'array la dimensione dell'array stesso è sempre definita in fase di dichiarazione.

Quello che dici è comunque corretto, probabilmente nel python alcune operazioni sono insite nella dichiarazione stessa. Dichiarare un array senza il tipo di variabile è possibile perche in un array il compilatore è dotatoo della "type inference", ovvero è in grado di stabilire il tipo di dato delle variabili, a patto che queste siano delle primitive (stringhe nel tuo caso). Probabilmebnte se avessi provaato a fare la stessa cosa con delle collection piu complesse come hash map o tuple, non credo che avresti potuto fare quel tipo di concatenamento, senza definire tipi e funzioni specifiche.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da gila75 »

Non so, peri ll momento potrei tralasciare, all'inizio ok approfondire, ma nemmeno impazzire.
La programmazione e' cosi', tempo al tempo.
Comunque anche il metodo insert concatena una stringa...mistero
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2854
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da DoctorStrange »

Ok, come preferisci. Ma attento che la "type inference", od ereditarietà di tipo, è un concetto che è piu alla base che non all'apice dello sviluppo :D
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1624
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da nuzzopippo »

gila75 ha scritto:
martedì 5 aprile 2022, 17:55
Non so, peri ll momento potrei tralasciare, all'inizio ok approfondire, ma nemmeno impazzire.
La programmazione e' cosi', tempo al tempo.
Comunque anche il metodo insert concatena una stringa...mistero
sempre domandine complicate eh, @Gila?

Purtroppo, non sono all'altezza di dare una risposta esaustiva, speriamo nell'intervento dei maestri, ma, comunque, una tale risposta a mio parere passa per forza dalla considerazione che in python "tutto è un oggetto", e gli oggetti python hanno dei modi ben precisi per definire i loro operatori, te ne faccio un esempio, supponiamo che io voglia farmi una classe per gestire i punti nello spazio e voglia implementare la somma di due punti 3d:

Codice: Seleziona tutto

from typing import Any
class Point3D:
    def __init__(self, x: int, y: int, z: int) -> None:
        self.x = x
        self.y = y
        self.z = z
    def __add__(self, b: Any) -> Any:
        x = self.x + b.x
        y = self.y + b.y
        z = self.z + b.z
        return Point3D(x, y, z)

    
a = Point3D(1, 1, 0)
b = Point3D(1, 1, 1)
c = a + b
print(c.x, c.y, c.z)
2 2 1
scusa se ho utilizzato i typehint, sto cercando di capirli in questo periodo, comunque l'esempio sopra è abbastanza semplice, ho definito un particolare metodo nella mia classe ("__add__") che stabilisce come "sommare" due istanze della stessa (N.B., avrei anche potuto definire la rappresentazione dell'oggetto come stringa con "__str__").
Riguardo al Tuo specifico quesito sulle concatenazioni una prima indicazione si potrebbe avere con gli in-pace operators, che però dicono ben poco consultando l'help degli oggetti list

Codice: Seleziona tutto

 |  __iadd__(self, value, /)
 |      Implement self+=value.
Bisognerebbe andarsi a guardare i sorgenti (che probabilmente non sarei in grado di capire adeguatamente, dovrebbero essere in C) ma ho il sospetto che detta concatenazione in una lista funziona sugli oggetti iterabili, analogamente al metodo

Codice: Seleziona tutto

 |  extend(self, iterable, /)
 |      Extend list by appending elements from the iterable.
proviamo il Tuo esempio iniziale con entrambi i metodi:

Codice: Seleziona tutto

l = [1, 2, 3]
l += 'casa'
l
[1, 2, 3, 'c', 'a', 's', 'a']
l = [1, 2, 3]
l
[1, 2, 3]
l.extend('casa')
l
[1, 2, 3, 'c', 'a', 's', 'a']
l += (4, 5, 6)
l
[1, 2, 3, 'c', 'a', 's', 'a', 4, 5, 6]
l += (7, 8, 9)
l
[1, 2, 3, 'c', 'a', 's', 'a', 4, 5, 6, 7, 8, 9]
Come vedi il metodo "extend" e l'operatore "+=" danno lo stesso risultato e si comportano nello stesso modo anche utilizzando una tupla ... gli addendi "iterabili" credo che siano la risposta ai Tuoi quesiti.
[Edit] anzi, traducendomi la parte sugli in-place operators vedo che è proprio li la risposta lo dice chiaramente, quando parla di iadd :
For immutable targets such as strings, numbers, and tuples, the updated value is computed, but not assigned back to the input variable:
...
For mutable targets such as lists and dictionaries, the in-place method will perform the update, so no subsequent assignment is necessary:
:ciao:
Fatti non foste a viver come bruti ...
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da gila75 »

sempre domandine complicate eh, @Gila?
:lol: No,no,Nuzzo, era solo per capire se mi era sfuggito qualche concetto o se sbagliavo qualcosa.
Come detto posso tralasciare tranquillamente questi aspetti tecnici, voglio impostare diversamente questa volta lo studio:
non saltare di palo in frasca e fare esercizi solo su quello che sto studiando.
Comunque il primo problema che ho sollevato,resta oscuro:il manuale mi dice che sezionamenti e concatenamenti di liste
danno nuovi oggetti,ma a me non risulta proprio

Codice: Seleziona tutto

[1, 2, 3, 4]
>>> id (l)
139920983095432
>>> l+=['abcde']
>>> l
[1, 2, 3, 4, 'abcde']
>>> id(l)
139920983095432
>>> 
Questo è un punto chiave da chiarire direi.
Magari intende col la sintassi L=L+1 E non L+=1...bho, se no credo sia un errore
Riguardo al tuo esempio, ti ringrazio, ma lo devo guardare domani mattina che sono fresco..tanto sono a casa per un brutto
infortunio al viso :sisi:
Aggiungo solo che la "stranezza" che ho sollevato, potrebbe essere data da un qualcosa che va contro la filosofia Python.
Ricordo tempo fa una cosa simile in una discussione sul C, più o meno la stessa cosa. Era logico aspettarsi un determinato comportamento
ma per un cavillo trovato da un utente esperto si era dimostrato che si sarebbe andati contro la filosofia C e sarebbe stato un controsenso.
Riguardo list.insert() che ho citato prima ho sbagliato, non c'entra nulla.
Avatar utente
nuzzopippo
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1624
Iscrizione: giovedì 12 ottobre 2006, 11:34

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da nuzzopippo »

gila75 ha scritto:
martedì 5 aprile 2022, 20:07
Comunque il primo problema che ho sollevato,resta oscuro:il manuale mi dice che sezionamenti e concatenamenti di liste
danno nuovi oggetti,ma a me non risulta proprio
beh ... se non ho capito male, con "sezionamenti" Ti riferisci allo slicing, ed in questo caso a me risulta

Codice: Seleziona tutto

>>> id(l_2)
139652745787200
>>> l = l[2:]
>>> id(l)
139652746698816
Come vedi, assegnando allo stesso "nome" lo slicing della lista, l'indirizzo in memoria è cambiato

la "concatenazione" sarebbe la "somma" di due liste, ed anche in questo caso :

Codice: Seleziona tutto

>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> id(a)
139652746762688
>>> id(b)
139652745788288
>>> a = a + b
>>> id(a)
139652746763072
>>> 
Il fatto è che l'operatore "+=" applicato ad una lista non è una concatenazione, se vuoi identificarlo a parole potresti visualizzare l'operazione come un "append" in serie ed essendo il nome di una lista niente altro che un indirizzo di memoria che individua una area di memorizzazione per i dati puntati dalla stessa (credo si potrebbe a soldoni individuarla come un puntatore) aggiungendo degli elementi l'indirizzo non cambia

Codice: Seleziona tutto

>>> l = []
>>> id(l)
139652745786752
>>> l.append(1)
>>> id(l)
139652745786752
>>> 
... comunque non sono tranquillo in quel che dico, è ciò che credo di aver capito ma ce ne vuole per avere le idee chiare.

Ciao
Fatti non foste a viver come bruti ...
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8242
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da crap0101 »

il discorso dell' id al momento fossi in te non ci penserei troppo, che il 90% delle volte nella pratica non lo userai mai direttamente. Certo, c'è da capire comunque un paio di cose fondamentali che comunque coinvolgono id, per dire:

Codice: Seleziona tutto

>>> l = [1,2,3]
>>> ll = [l for _ in range(2)]
>>> ll
[[1, 2, 3], [1, 2, 3]]
>>> l[0]=99
>>> ll
[[99, 2, 3], [99, 2, 3]]
>>> ll[0][1]=100
>>> ll
[[99, 100, 3], [99, 100, 3]]
>>> l
[99, 100, 3]
Comunque causa impegni lavorativi :-D mi ha preceduto ottimamente nuzzopippo, per cui giusto per riepilogare sintenticamente:

Codice: Seleziona tutto

>>> l[:2]+'xxxxx'+l[3:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
l'errore è abbastanza chiaro: *non* puoi unire liste e stringhe, come neanche puoi fare con liste e tuple o con tuple e stringhe, otterresti sempre lo stesso errore. Quello che secondo me ti ha confuso è la somiglianza tra gli operatori '+'
e '+=' ...quest'ultimo però è solo un modo comodo per scrivere

Codice: Seleziona tutto

lista.extend(sequenza)
e appunto, a differenza di

Codice: Seleziona tutto

lista + stringa
lista + intero
funziona perchè accetta un qualsiasi oggetto che implementa il protocollo dell'iterazione (stringhe, tuple, set, ecc):

Codice: Seleziona tutto

>>> l.extend(set('foobar'))
>>> l
[99, 100, 3, 'a', 'r', 'b', 'o', 'f']
>>> 
 
Che poi si potrebbe volere che funzioni anche in quel modo che ti aspettavi... ehhh che dire, è stato deciso così, immagino anche per motivi pratici: il primo che mi viene in mente è (per stare all'esempio che hai portato):

Codice: Seleziona tutto

l[:2]+'xxxxx'+l[3:]
# o peggio ancora:
[0,0,0]+(1,2,3)+set(range(10))
l'oggetto risultante sarebbe una lista? o una tupla? o un set?

@DoctorStrange
Mi sembra che parli (di) un altro linguaggio :-)
in Python non c'è quoting forte o debole, la "coppia di indici" è uno "slice di liste", la type inference lasciamo stare che nelle liste ci puoi buttare dentro di tutto e in nessuno degli esempi postati c'è ombra di un array
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: [Python] Nuovo oggetto dopo concatenazione o sezionamento

Messaggio da gila75 »

Quello che secondo me ti ha confuso è la somiglianza tra gli operatori '+'
e '+='
Esattamente! Mi ha confuso. Grosso modo fanno la stessa cosa, ma il concatenamento vero e proprio è : l=l+x
l[:2]+'xxxxx'+l[3:]
# o peggio ancora:
[0,0,0]+(1,2,3)+set(range(10))
Ottimo esempio, chiarisce tutto.
(id) indirizzo lo uso solo per capire quando l'oggetto è nuovo, per fissare bene le idee sugli oggetti mutabili e non , modifiche sul posto e non.
Ritengo che sia stato chiarito tutto , siete stati davvero preziosi, grazie :)
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: Bing [Bot] e 13 ospiti