Ricerca…


introduzione

A differenza della maggior parte delle lingue, Python supporta due versioni principali. Dal 2008, quando è stato rilasciato Python 3, molti hanno fatto la transizione, mentre molti non l'hanno fatto. Per comprendere entrambi, questa sezione copre le importanti differenze tra Python 2 e Python 3.

Osservazioni

Ci sono attualmente due versioni supportate di Python: 2.7 (Python 2) e 3.6 (Python 3). Inoltre, le versioni 3.3 e 3.4 ricevono aggiornamenti di sicurezza in formato sorgente.

Python 2.7 è retrocompatibile con la maggior parte delle versioni precedenti di Python e può eseguire il codice Python dalla maggior parte delle versioni 1.xe 2.x di Python invariato. È ampiamente disponibile, con una vasta collezione di pacchetti. Viene anche considerato deprecato dagli sviluppatori CPython e riceve solo sicurezza e sviluppo di correzioni di errori. Gli sviluppatori CPython intendono abbandonare questa versione della lingua nel 2020 .

Secondo Python Enhancement Proposal 373 non sono previste versioni future di Python 2 dopo il 25 giugno 2016, ma correzioni di bug e aggiornamenti di sicurezza saranno supportati fino al 2020. (Non specifica quale data esatta nel 2020 sarà la data di tramonto di Python 2.)

Python 3 ha intenzionalmente rotto la compatibilità all'indietro, per affrontare le preoccupazioni che gli sviluppatori linguistici avevano del nucleo della lingua. Python 3 riceve nuovo sviluppo e nuove funzionalità. È la versione della lingua che gli sviluppatori di lingue intendono portare avanti.

Nel tempo intercorso tra la versione iniziale di Python 3.0 e la versione corrente, alcune funzionalità di Python 3 sono state sottoposte a back-port in Python 2.6 e altre parti di Python 3 sono state estese per avere la sintassi compatibile con Python 2. Pertanto è possibile scrivere Python che funzionerà sia su Python 2 che su Python 3, usando future importazioni e moduli speciali (come sei ).

Le importazioni future devono essere all'inizio del modulo:

from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')

Per ulteriori informazioni sul modulo __future__ , consultare la pagina pertinente nella documentazione di Python .

Lo strumento 2to3 è un programma Python che converte il codice Python 2.x in codice Python 3.x, vedi anche la documentazione di Python .

Il pacchetto six fornisce utility per la compatibilità con Python 2/3:

  • accesso unificato alle librerie rinominate
  • variabili per tipi string / unicode
  • funzioni per il metodo rimosso o rinominato

Un riferimento per le differenze tra Python 2 e Python 3 può essere trovato qui .

Stampa dichiarazione vs. funzione di stampa

In Python 2, la print è una dichiarazione:

Python 2.x 2.7
print "Hello World"
print                         # print a newline
print "No newline",           # add trailing comma to remove newline 
print >>sys.stderr, "Error"   # print to stderr
print("hello")                # print "hello", since ("hello") == "hello"
print()                       # print an empty tuple "()"
print 1, 2, 3                 # print space-separated arguments: "1 2 3"
print(1, 2, 3)                # print tuple "(1, 2, 3)"

In Python 3, print() è una funzione, con argomenti parola chiave per usi comuni:

Python 3.x 3.0
print "Hello World"              # SyntaxError
print("Hello World")
print()                          # print a newline (must use parentheses)
print("No newline", end="")      # end specifies what to append (defaults to newline)
print("Error", file=sys.stderr)  # file specifies the output buffer
print("Comma", "separated", "output", sep=",")  # sep specifies the separator
print("A", "B", "C", sep="")     # null string for sep: prints as ABC
print("Flush this", flush=True)  # flush the output buffer, added in Python 3.3
print(1, 2, 3)                   # print space-separated arguments: "1 2 3"
print((1, 2, 3))                 # print tuple "(1, 2, 3)"

La funzione di stampa ha i seguenti parametri:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

sep è ciò che separa gli oggetti che passi per stampare. Per esempio:

print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar

end è ciò a cui è seguita la fine della dichiarazione di stampa. Per esempio:

print('foo', 'bar', end='!') # out: foo bar!

La stampa successiva a una stampa di fine non nuova riga verrà stampata sulla stessa riga:

print('foo', end='~')
print('bar')
# out: foo~bar

Nota: per compatibilità futura, la funzione di print è disponibile anche in Python 2.6; tuttavia non può essere utilizzato a meno che l'analisi dell'istruzione di print non sia disabilitata con

from __future__ import print_function

Questa funzione ha esattamente lo stesso formato di Python 3, tranne per il fatto che manca il parametro flush .

Vedere PEP 3105 per la logica.

Stringhe: byte contro Unicode

Python 2.x 2.7

In Python 2 ci sono due varianti di stringa: quelle fatte di byte con tipo ( str ) e quelle fatte di testo con tipo ( unicode ).

In Python 2, un oggetto di tipo str è sempre una sequenza di byte, ma è comunemente usato sia per i dati di testo che per quelli binari.

Una stringa letterale viene interpretata come una stringa di byte.

s = 'Cafe'    # type(s) == str

Ci sono due eccezioni: puoi definire un letterale Unicode (testo) esplicitamente prefiggendo il letterale con u :

s = u'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == str

In alternativa, è possibile specificare che i valori letterali stringa di un intero modulo devono creare valori letterali Unicode (testo):

from __future__ import unicode_literals

s = 'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == unicode

Per verificare se la variabile è una stringa (Unicode o una stringa di byte), puoi utilizzare:

isinstance(s, basestring)
Python 3.x 3.0

In Python 3, il tipo str è un tipo di testo Unicode.

s = 'Cafe'           # type(s) == str
s = 'Café'           # type(s) == str (note the accented trailing e)

Inoltre, Python 3 ha aggiunto un oggetto bytes , adatto per "blob" binari o per scrivere in file indipendenti dalla codifica. Per creare un oggetto bytes, puoi anteporre b a un letterale stringa o chiamare il metodo encode della stringa:

# Or, if you really need a byte string:
s = b'Cafe'          # type(s) == bytes
s = 'Café'.encode()  # type(s) == bytes

Per verificare se un valore è una stringa, utilizzare:

isinstance(s, str)
Python 3.x 3.3

È anche possibile prefissare i letterali stringa con un prefisso u per facilitare la compatibilità tra le basi di codice Python 2 e Python 3. Poiché, in Python 3, tutte le stringhe sono Unicode per impostazione predefinita, la preposizione di una stringa letterale con u non ha alcun effetto:

u'Cafe' == 'Cafe'

Il prefisso di stringa Unicode non ur Python 2 non è supportato, tuttavia:

>>> ur'Café'
  File "<stdin>", line 1
    ur'Café'
           ^
SyntaxError: invalid syntax

Nota che devi encode un oggetto testo ( str ) Python 3 per convertirlo in una rappresentazione in bytes di quel testo. La codifica predefinita di questo metodo è UTF-8 .

Puoi utilizzare la decode per chiedere a un oggetto bytes quale testo Unicode rappresenta:

>>> b.decode()
'Café'
Python 2.x 2.6

Mentre il tipo di bytes esiste sia in Python 2 che in 3, il tipo unicode esiste solo in Python 2. Per usare le stringhe Unicode implicite di Python 3 in Python 2, aggiungi quanto segue all'inizio del tuo file di codice:

from __future__ import unicode_literals
print(repr("hi"))
# u'hi'
Python 3.x 3.0

Un'altra importante differenza è che l'indicizzazione dei byte in Python 3 ha come risultato un output int simile:

b"abc"[0] == 97

Mentre l'affettatura in una dimensione di un risultato in un oggetto di lunghezza 1 byte:

b"abc"[0:1] == b"a"

Inoltre, Python 3 corregge alcuni comportamenti insoliti con unicode, ovvero invertendo le stringhe di byte in Python 2. Ad esempio, il seguente problema è stato risolto:

# -*- coding: utf8 -*-
print("Hi, my name is Łukasz Langa.")
print(u"Hi, my name is Łukasz Langa."[::-1])
print("Hi, my name is Łukasz Langa."[::-1])

# Output in Python 2
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsaku�� si eman ym ,iH

# Output in Python 3
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsakuŁ si eman ym ,iH

Divisione intera

Il simbolo di divisione standard ( / ) opera in modo diverso in Python 3 e Python 2 quando applicato a numeri interi.

Quando si divide un intero di un altro intero in Python 3, l'operazione di divisione x / y rappresenta una divisione vera (utilizza il metodo __truediv__ ) e produce un risultato in virgola mobile. Nel frattempo, la stessa operazione in Python 2 rappresenta una divisione classica che arrotonda il risultato verso l'infinito negativo (noto anche come prendere la parola ).

Per esempio:

Codice Uscita Python 2 Uscita Python 3
3 / 2 1 1.5
2 / 3 0 ,6666666666666666
-3 / 2 -2 -1.5

Il comportamento di arrotondamento verso lo zero era deprecato in Python 2.2 , ma rimane in Python 2.7 per motivi di compatibilità con le versioni precedenti ed è stato rimosso in Python 3.

Nota: per ottenere un risultato float in Python 2 (senza arrotondamento del pavimento) possiamo specificare uno degli operandi con il punto decimale. L'esempio precedente di 2/3 che dà 0 in Python 2 deve essere usato come 2 / 3.0 o 2.0 / 3 o 2.0/3.0 per ottenere 0.6666666666666666

Codice Uscita Python 2 Uscita Python 3
3.0 / 2.0 1.5 1.5
2 / 3.0 ,6666666666666666 ,6666666666666666
-3.0 / 2 -1.5 -1.5

Esiste anche l' operatore della divisione floor ( // ), che funziona allo stesso modo in entrambe le versioni: si arrotonda al numero intero più vicino. (anche se un float viene restituito quando viene utilizzato con float) In entrambe le versioni l'operatore // associa a __floordiv__ .

Codice Uscita Python 2 Uscita Python 3
3 // 2 1 1
2 // 3 0 0
-3 // 2 -2 -2
3.0 // 2.0 1.0 1.0
2.0 // 3 0.0 0.0
-3 // 2.0 -2.0 -2.0

Si può forzare esplicitamente la vera divisione o divisione del piano usando le funzioni native nel modulo operator :

from operator import truediv, floordiv
assert truediv(10, 8) == 1.25            # equivalent to `/` in Python 3
assert floordiv(10, 8) == 1              # equivalent to `//`

Mentre è chiaro ed esplicito, usare le funzioni dell'operatore per ogni divisione può essere noioso. Spesso si preferisce modificare il comportamento dell'operatore / . Una pratica comune consiste nell'eliminare il tipico comportamento di divisione aggiungendo from __future__ import division come prima affermazione in ogni modulo:

# needs to be the first statement in a module
from __future__ import division
Codice Uscita Python 2 Uscita Python 3
3 / 2 1.5 1.5
2 / 3 ,6666666666666666 ,6666666666666666
-3 / 2 -1.5 -1.5

from __future__ import division garantisce che l'operatore / rappresenta la vera divisione e solo all'interno dei moduli che contengono l'importazione __future__ , quindi non ci sono motivi validi per non abilitarlo in tutti i nuovi moduli.

Nota : alcuni altri linguaggi di programmazione utilizzano l' arrotondamento verso lo zero (troncamento) anziché l' arrotondamento verso il basso negativo come fa Python (cioè in quei linguaggi -3 / 2 == -1 ). Questo comportamento può creare confusione durante il porting o il confronto del codice.


Nota sugli operandi float : in alternativa alla from __future__ import division , si potrebbe usare il consueto simbolo di divisione / e assicurarsi che almeno uno degli operandi sia float: 3 / 2.0 == 1.5 . Tuttavia, questo può essere considerato una cattiva pratica. È troppo facile scrivere average = sum(items) / len(items) e dimenticare di lanciare uno degli argomenti per renderlo mobile. Inoltre, tali casi possono spesso eludere la notifica durante il test, ad esempio, se si prova su un array contenente float s ma si riceve una matrice di int s in produzione. Inoltre, se in Python 3 viene utilizzato lo stesso codice, i programmi che prevedono che 3/2 3 / 2 == 1 siano True non funzioneranno correttamente.

Vedi PEP 238 per ragioni più dettagliate sul perché l'operatore di divisione è stato modificato in Python 3 e perché la divisione vecchio stile dovrebbe essere evitata.


Vedi l' argomento Simple Math per ulteriori informazioni sulla divisione.

Ridurre non è più un built-in

In Python 2, reduce è disponibile sia come funzione integrata o dal pacchetto functools (versione 2.6 in poi), mentre in Python 3 la reduce è disponibile solo da functools . Tuttavia la sintassi per la reduce sia in Python2 che in Python3 è la stessa ed è reduce(function_to_reduce, list_to_reduce) .

Ad esempio, consideriamo la possibilità di ridurre un elenco a un singolo valore dividendo ciascuno dei numeri adiacenti. Qui usiamo la funzione truediv dalla libreria operator .

In Python 2.x è semplice come:

Python 2.x 2.3
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator
>>> reduce(operator.truediv, my_list)
0.008333333333333333

In Python 3.x l'esempio diventa un po 'più complicato:

Python 3.x 3.0
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator, functools
>>> functools.reduce(operator.truediv, my_list)
0.008333333333333333

Possiamo anche usare from functools import reduce per evitare di chiamare reduce con il nome del namespace.

Differenze tra le funzioni range e xrange

In Python 2, la funzione range restituisce un elenco mentre xrange crea un oggetto xrange speciale, che è una sequenza immutabile, che a differenza di altri tipi di sequenza incorporati, non supporta l'slicing e non ha né index né metodi di count :

Python 2.x 2.3
print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

In Python 3, xrange stato espanso alla sequenza di range , che ora crea un oggetto range . Non esiste un tipo xrange :

Python 3.x 3.0
print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

Inoltre, dal momento che Python 3.2, range supporta anche affettare, index e count :

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

Il vantaggio di usare un tipo di sequenza speciale invece di una lista è che l'interprete non deve allocare memoria per un elenco e popolarlo:

Python 2.x 2.3
# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

Poiché il secondo comportamento è generalmente desiderato, il primo è stato rimosso in Python 3. Se vuoi comunque avere un elenco in Python 3, puoi semplicemente usare il costruttore di list() su un oggetto range :

Python 3.x 3.0
print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Compatibilità

Per mantenere la compatibilità tra le versioni di Python 2.xe di Python 3.x, è possibile utilizzare il modulo builtins dal pacchetto esterno future per ottenere sia compatibilità builtins compatibilità all'indietro :

Python 2.x 2.0
#forward-compatible
from builtins import range

for i in range(10**8):
    pass
Python 3.x 3.0
#backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

L' range nella future libreria supporta slicing, index e count in tutte le versioni di Python, proprio come il metodo built-in su Python 3.2+.

Disimballare Iterables

Python 3.x 3.0

In Python 3, puoi decomprimere un iterabile senza conoscere il numero esatto di elementi in esso contenuti e persino avere una variabile che tenga la fine del iterabile. Per questo, si fornisce una variabile che può raccogliere un elenco di valori. Questo viene fatto mettendo un asterisco prima del nome. Ad esempio, decomprimere un list :

first, second, *tail, last = [1, 2, 3, 4, 5]
print(first)
# Out: 1
print(second)
# Out: 2
print(tail)
# Out: [3, 4]
print(last)
# Out: 5

Nota : quando si utilizza la sintassi *variable , la variable sarà sempre un elenco, anche se il tipo originale non era un elenco. Può contenere zero o più elementi a seconda del numero di elementi nell'elenco originale.

first, second, *tail, last = [1, 2, 3, 4]
print(tail)
# Out: [3]

first, second, *tail, last = [1, 2, 3]
print(tail)
# Out: []
print(last)
# Out: 3

Allo stesso modo, scompattando un str :

begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']

Esempio di disimballaggio di una date ; _ è usato in questo esempio come variabile throwaway (ci interessa solo il valore year ):

person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016

Vale la pena ricordare che, dal momento che * mangia un numero variabile di elementi, non è possibile avere due * s per lo stesso iterabile in un compito - non saprebbe quanti elementi vanno nel primo disimballaggio, e quanti nel secondo :

*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment
Python 3.x 3.5

Finora abbiamo discusso di disfare i compiti. * e ** sono stati estesi in Python 3.5 . Ora è possibile avere diverse operazioni di spacchettamento in un'unica espressione:

{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}
Python 2.x 2.0

È anche possibile decomprimere un argomento iterabile in funzione:

iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5
Python 3.x 3.5

La decompressione di un dizionario utilizza due stelle adiacenti ** ( PEP 448 ):

tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
 # Out: {'x': 1, 'y': 2, 'z': 3}

Ciò consente sia la sovrascrittura dei vecchi valori sia la fusione dei dizionari.

dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}
Python 3.x 3.0

Python 3 ha rimosso la disimballaggio tuple nelle funzioni. Quindi quanto segue non funziona in Python 3

# Works in Python 2, but syntax error in Python 3:
map(lambda (x, y): x + y, zip(range(5), range(5)))
# Same is true for non-lambdas:
def example((x, y)):
    pass

# Works in both Python 2 and Python 3:
map(lambda x: x[0] + x[1], zip(range(5), range(5)))
# And non-lambdas, too:
def working_example(x_y):
    x, y = x_y
    pass

Vedi PEP 3113 per informazioni dettagliate.

Sollevamento e gestione delle eccezioni

Questa è la sintassi di Python 2, nota le virgole , raise e except linee:

Python 2.x 2.3
try:
    raise IOError, "input/output error"
except IOError, exc:
    print exc

In Python 3, la sintassi , viene eliminata e sostituita da parentesi e la parola chiave as :

try:
    raise IOError("input/output error")
except IOError as exc:
    print(exc)

Per compatibilità con le versioni precedenti, la sintassi di Python 3 è disponibile anche in Python 2.6, quindi dovrebbe essere utilizzata per tutti i nuovi codici che non devono essere compatibili con le versioni precedenti.


Python 3.x 3.0

Python 3 aggiunge anche il concatenamento delle eccezioni , in cui è possibile segnalare che qualche altra eccezione è stata la causa di questa eccezione. Per esempio

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from e

L'eccezione sollevata __cause__ except è di tipo DatabaseError , ma l'eccezione originale è contrassegnata come l'attributo __cause__ di tale eccezione. Quando viene visualizzato il traceback, l'eccezione originale verrà visualizzata anche nel traceback:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Se lanci un blocco except senza concatenamento esplicito:

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}')

Il traceback è

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Python 2.x 2.0

Nessuno dei due è supportato in Python 2.x; l'eccezione originale e il suo traceback saranno persi se viene sollevata un'altra eccezione nel blocco eccetto. Il seguente codice può essere utilizzato per la compatibilità:

import sys
import traceback

try:
    funcWithError()
except:
    sys_vers = getattr(sys, 'version_info', (0,))
    if sys_vers < (3, 0):
        traceback.print_exc()
    raise Exception("new exception")
Python 3.x 3.3

Per "dimenticare" l'eccezione precedentemente generata, usa raise from None

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from None

Ora il traceback sarebbe semplicemente

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

Oppure per renderlo compatibile con entrambi i Python 2 e 3 è possibile utilizzare il pacchetto sei in questo modo:

import six
try:
    file = open('database.db')
except FileNotFoundError as e:
    six.raise_from(DatabaseError('Cannot open {}'), None)

.next () metodo sugli iteratori rinominato

In Python 2, un iteratore può essere attraversato usando un metodo chiamato next sull'iteratore stesso:

Python 2.x 2.3
g = (i for i in range(0, 3))
g.next()  # Yields 0
g.next()  # Yields 1
g.next()  # Yields 2

In Python 3 il metodo .next è stato rinominato in .__next__ , riconoscendo il suo ruolo "magico", quindi chiamando .next genererà un AttributeError . Il modo corretto per accedere a questa funzionalità sia in Python 2 che in Python 3 è chiamare la funzione next con l'iteratore come argomento.

Python 3.x 3.0
g = (i for i in range(0, 3))
next(g)  # Yields 0
next(g)  # Yields 1
next(g)  # Yields 2

Questo codice è portatile tra le versioni dalla 2.6 alla versione corrente.

Confronto tra diversi tipi

Python 2.x 2.3

Oggetti di diverso tipo possono essere confrontati. I risultati sono arbitrari, ma coerenti. Sono ordinati in modo tale che None sia inferiore a qualsiasi altra cosa, i tipi numerici sono più piccoli dei tipi non numerici e tutto il resto è ordinato lessicograficamente per tipo. Quindi, un int è minore di un str e una tuple è maggiore di una list :

[1, 2] > 'foo'
# Out: False
(1, 2) > 'foo'
# Out: True
[1, 2] > (1, 2)
# Out: False
100 < [1, 'x'] < 'xyz' < (1, 'x')
# Out: True

Inizialmente era stato fatto in modo da poter ordinare un elenco di tipi misti e raggruppare gli oggetti per tipo:

l = [7, 'x', (1, 2), [5, 6], 5, 8.0, 'y', 1.2, [7, 8], 'z']
sorted(l)
# Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'x', 'y', 'z', (1, 2)]
Python 3.x 3.0

Viene sollevata un'eccezione quando si confrontano diversi tipi (non numerici):

1 < 1.5
# Out: True

[1, 2] > 'foo'
# TypeError: unorderable types: list() > str()
(1, 2) > 'foo'
# TypeError: unorderable types: tuple() > str()
[1, 2] > (1, 2)
# TypeError: unorderable types: list() > tuple()

Per ordinare gli elenchi misti in Python 3 in base ai tipi e per ottenere la compatibilità tra le versioni, è necessario fornire una chiave per la funzione ordinata:

>>> list = [1, 'hello', [3, 4], {'python': 2}, 'stackoverflow', 8, {'python': 3}, [5, 6]]
>>> sorted(list, key=str)
# Out: [1, 8, [3, 4], [5, 6], 'hello', 'stackoverflow', {'python': 2}, {'python': 3}]

L'utilizzo di str come funzione key converte temporaneamente ciascun elemento in una stringa solo ai fini del confronto. Quindi vede la rappresentazione della stringa che inizia con [ , ' , { o 0-9 ed è in grado di ordinare quelli (e tutti i seguenti caratteri).

Input dell'utente

In Python 2, l'input dell'utente è accettato usando la funzione raw_input ,

Python 2.x 2.3
user_input = raw_input()

Mentre in Python 3 l'input dell'utente è accettato usando la funzione di input .

Python 3.x 3.0
user_input = input()

In Python 2, l' input funzione accetta input e interpretarlo. Anche se questo può essere utile, ha diverse considerazioni sulla sicurezza ed è stato rimosso in Python 3. Per accedere alla stessa funzionalità, è possibile utilizzare eval(input()) .

Per mantenere uno script portatile tra le due versioni, puoi inserire il codice sotto la parte superiore del tuo script Python:

try:
    input = raw_input
except NameError:
    pass

Modifiche al metodo dei dizionari

In Python 3, molti dei metodi del dizionario sono molto diversi nel comportamento di Python 2, e molti sono stati rimossi: has_key , iter* e view* sono spariti. Invece di d.has_key(key) , che era stato a lungo deprecato, è necessario utilizzare la key in d .

In Python 2, le keys metodi del dizionario, i values e gli items restituiscono gli elenchi. In Python 3 restituiscono invece gli oggetti vista ; gli oggetti vista non sono iteratori e differiscono da essi in due modi:

  • hanno dimensioni (si può usare la funzione len su di loro)
  • possono essere ripetuti più volte

Inoltre, come con gli iteratori, le modifiche nel dizionario si riflettono negli oggetti vista.

Python 2.7 ha eseguito il backport di questi metodi da Python 3; sono disponibili come viewkeys , viewvalues e viewitems . Per trasformare il codice Python 2 in codice Python 3, i moduli corrispondenti sono:

  • d.keys() , d.values() e d.items() di Python 2 dovrebbero essere cambiati in list(d.keys()) , list(d.values()) ed list(d.items())
  • d.iterkeys() , d.itervalues() e d.iteritems() dovrebbero essere modificati in iter(d.keys()) , o anche meglio iter(d) ; iter(d.values()) e iter(d.items()) rispettivamente
  • e infine il metodo Python 2.7 chiama d.viewkeys() , d.viewvalues() e d.viewitems() può essere sostituito con d.keys() , d.values() e d.items() .

Porting Python 2 codice che itera su chiavi, valori o voci del dizionario, mentre la sua mutazione è a volte difficile. Tenere conto:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
    if key.isalpha():
        del d[key]

Il codice sembra funzionare in modo simile in Python 3, ma il metodo keys restituisce un oggetto vista, non una lista, e se il dizionario cambia dimensione mentre viene iterato, il codice Python 3 si bloccherà con RuntimeError: dictionary changed size during iteration . La soluzione è ovviamente quella di scrivere correttamente for key in list(d) .

Allo stesso modo, gli oggetti vista si comportano diversamente dagli iteratori: non si può usare next() su di essi, e non si può riprendere l' iterazione; sarebbe invece ricominciare; se il codice Python 2 supera il valore restituito da d.iterkeys() , d.itervalues() o d.iteritems() a un metodo che si aspetta un iteratore invece di un iterabile , allora dovrebbe essere iter(d) , iter(d.values()) o iter(d.items()) in Python 3.

la dichiarazione exec è una funzione in Python 3

In Python 2, exec è un'istruzione, con una sintassi speciale: exec code [in globals[, locals]]. In Python 3 exec è ora una funzione: exec(code, [, globals[, locals]]) , e la sintassi Python 2 solleverà un SyntaxError .

Poiché la print stata modificata da una funzione in una funzione, è stata aggiunta un'importazione __future__ . Tuttavia, non esiste from __future__ import exec_function , poiché non è necessario: l'istruzione exec in Python 2 può anche essere utilizzata con una sintassi che assomiglia esattamente alla exec funzione exec in Python 3. In questo modo è possibile modificare le istruzioni

Python 2.x 2.3
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars

alle forme

Python 3.x 3.0
exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)

e queste ultime sono garantite per funzionare in modo identico sia in Python 2 che in Python 3.

hasattr bug di funzionalità in Python 2

In Python 2, quando una proprietà hasattr un errore, hasattr ignorerà questa proprietà, restituendo False .

class A(object):
    @property
    def get(self):
        raise IOError


class B(object):
    @property
    def get(self):
        return 'get in b'

a = A()
b = B()

print 'a hasattr get: ', hasattr(a, 'get')
# output False in Python 2 (fixed, True in Python 3)
print 'b hasattr get', hasattr(b, 'get')
# output True in Python 2 and Python 3

Questo bug è stato risolto in Python3. Quindi se usi Python 2, usa

try:
    a.get
except AttributeError:
    print("no get property!")

o usa invece getattr

p = getattr(a, "get", None)
if p is not None:
    print(p)
else:
    print("no get property!")

Moduli rinominati

Alcuni moduli nella libreria standard sono stati rinominati:

Vecchio nome Nuovo nome
_winreg winreg
ConfigParser ConfigParser
copy_reg copyreg
Coda coda
SocketServer SocketServer
_markupbase markupbase
repr reprlib
test.test_support test.support
Tkinter Tkinter
tkFileDialog tkinter.filedialog
urllib / urllib2 urllib, urllib.parse, urllib.error, urllib.response, urllib.request, urllib.robotparser

Alcuni moduli sono stati addirittura convertiti da file in librerie. Prendi tkinter e urllib dall'alto come esempio.

Compatibilità

Quando si mantiene la compatibilità tra entrambe le versioni di Python 2.xe 3.x, è possibile utilizzare il future pacchetto esterno per abilitare l'importazione di pacchetti di libreria standard di livello superiore con nomi Python 3.x nelle versioni di Python 2.x.

Costanti ottali

In Python 2, un letterale ottale potrebbe essere definito come

>>> 0755  # only Python 2

Per garantire la compatibilità incrociata, utilizzare

0o755  # both Python 2 and Python 3

Tutte le classi sono "classi di nuovo stile" in Python 3.

In Python 3.x tutte le classi sono classi di nuovo stile ; quando la definizione di una nuova classe python la rende implicitamente ereditata object . In quanto tale, specificare l' object in una definizione di class è completamente facoltativo:

Python 3.x 3.0
class X: pass
class Y(object): pass

Entrambe queste classi ora contengono object nel loro mro (ordine di risoluzione dei metodi):

Python 3.x 3.0
>>> X.__mro__
(__main__.X, object)

>>> Y.__mro__
(__main__.Y, object)

In Python 2.x classi sono, di default, classi vecchio stile; non ereditano implicitamente object . Questo fa sì che la semantica delle classi differisca a seconda se aggiungiamo esplicitamente l' object come una class base:

Python 2.x 2.3
class X: pass
class Y(object): pass

In questo caso, se proviamo a stampare il __mro__ di Y , __mro__ un output simile a quello nel caso Python 3.x :

Python 2.x 2.3
>>> Y.__mro__
(<class '__main__.Y'>, <type 'object'>)

Questo accade perché abbiamo esplicitamente fatto ereditare Y dall'oggetto quando lo definiamo: class Y(object): pass . Per la classe X che non eredita da un oggetto, l'attributo __mro__ non esiste, il tentativo di accedervi produce un AttributeError .

Per garantire la compatibilità tra entrambe le versioni di Python, le classi possono essere definite con object come classe base:

class mycls(object):
    """I am fully compatible with Python 2/3"""

In alternativa, se la variabile __metaclass__ è impostata su type at global scope, tutte le classi definite successivamente in un dato modulo sono implicitamente di nuovo stile senza bisogno di ereditare esplicitamente da object :

__metaclass__ = type

class mycls:
    """I am also fully compatible with Python 2/3"""

Operatori rimossi <> e ``, sinonimi di! = E repr ()

In Python 2, <> è un sinonimo di != ; allo stesso modo, `foo` è un sinonimo di repr(foo) .

Python 2.x 2.7
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
Python 3.x 3.0
>>> 1 <> 2
  File "<stdin>", line 1
    1 <> 2
       ^
SyntaxError: invalid syntax
>>> `foo`
  File "<stdin>", line 1
    `foo`
    ^
SyntaxError: invalid syntax

codifica / decodifica in esadecimale non più disponibile

Python 2.x 2.7
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
Python 3.x 3.0
"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'str' object has no attribute 'decode'

b"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs

'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs

b'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# AttributeError: 'bytes' object has no attribute 'encode'

Tuttavia, come suggerito dal messaggio di errore, è possibile utilizzare il modulo codecs per ottenere lo stesso risultato:

import codecs
codecs.decode('1deadbeef4', 'hex')
# Out: b'\x1d\xea\xdb\xee\xf4'
codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
# Out: b'1deadbeef4'

Si noti che codecs.encode restituisce un oggetto bytes . Per ottenere un oggetto str basta decode in ASCII:

codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'

funzione cmp rimossa in Python 3

In Python 3 la funzione integrata di cmp stata rimossa, insieme al metodo speciale __cmp__ .

Dalla documentazione:

La funzione cmp() dovrebbe essere considerata come andata, e il metodo speciale __cmp__() non è più supportato. Utilizzare __lt__() per l'ordinamento, __eq__() con __hash__() e altri confronti ricchi secondo necessità. (Se hai davvero bisogno della funzionalità cmp() , potresti usare l'espressione (a > b) - (a < b) come equivalente per cmp(a, b) .)

Inoltre tutte le funzioni built-in che hanno accettato il parametro cmp ora accettano solo il parametro key keyword only.

Nel modulo functools è anche utile la funzione cmp_to_key(func) che consente di convertire da una funzione stile cmp a una funzione stile- key :

Trasforma una funzione di confronto vecchio stile in una funzione chiave. Utilizzato con strumenti che accettano funzioni chiave (come sorted() , min() , max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ). Questa funzione viene principalmente utilizzata come strumento di transizione per i programmi in fase di conversione da Python 2 che supporta l'utilizzo di funzioni di confronto.

Variabili trapelate nella comprensione delle liste

Python 2.x 2.3
x = 'hello world!'
vowels = [x for x in 'AEIOU'] 

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'   
Python 3.x 3.0
x = 'hello world!'
vowels = [x for x in 'AEIOU']

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'hello world!'

Come si può vedere dall'esempio, in Python 2 è stato trapelato il valore di x : è mascherato hello world! e stampato U , poiché questo era l'ultimo valore di x quando il ciclo terminava.

Tuttavia, in Python 3 x stampato il hello world! originariamente definito hello world! , poiché la variabile locale dalla comprensione della lista non maschera le variabili dall'ambito circostante.

Inoltre, né le espressioni del generatore (disponibili in Python dal 2.5) né le definizioni del dizionario o dell'insieme (che sono state trasferite a Python 2.7 da Python 3) perdono variabili in Python 2.

Nota che sia in Python 2 che in Python 3, le variabili penetreranno nell'ambiente circostante quando si utilizza un ciclo for:

x = 'hello world!'
vowels = []
for x in 'AEIOU':
    vowels.append(x)
print(x)
# Out: 'U'

carta geografica()

map() è un builtin utile per applicare una funzione agli elementi di un iterabile. In Python 2, la map restituisce una lista. In Python 3, map restituisce un oggetto map , che è un generatore.

# Python 2.X
>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
>>> type(_)
>>> <class 'list'>

# Python 3.X
>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x*>
>>> type(_)
<class 'map'>

# We need to apply map again because we "consumed" the previous map....
>>> map(str, [1, 2, 3, 4, 5])
>>> list(_)
['1', '2', '3', '4', '5']

In Python 2, è possibile passare None per fungere da funzione di identità. Questo non funziona più in Python 3.

Python 2.x 2.3
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
Python 3.x 3.0
>>> list(map(None, [0, 1, 2, 3, 0, 5]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Inoltre, quando si passa più di un iterable come argomento in Python 2, map esegue il pad dei file itertools.izip_longest più brevi con None (simile a itertools.izip_longest ). In Python 3, l'iterazione si interrompe dopo il più breve iterabile.

In Python 2:

Python 2.x 2.3
>>> map(None, [1, 2, 3], [1, 2], [1, 2, 3, 4, 5])
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

In Python 3:

Python 3.x 3.0
>>> list(map(lambda x, y, z: (x, y, z), [1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2)]

# to obtain the same padding as in Python 2 use zip_longest from itertools
>>> import itertools
>>> list(itertools.zip_longest([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

Nota : al posto della map considera l'utilizzo delle list comprehensions, che sono compatibili con Python 2/3. Sostituzione map(str, [1, 2, 3, 4, 5]) :

>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']

filter (), map () e zip () restituiscono gli iteratori anziché le sequenze

Python 2.x 2.7

Nel filter Python 2, le funzioni incorporate di map e zip restituiscono una sequenza. map e zip restituiscono sempre una lista mentre con filter il tipo restituito dipende dal tipo di parametro dato:

>>> s = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> s
'abc'
>>> s = map(lambda x: x * x, [0, 1, 2])
>>> s
[0, 1, 4]
>>> s = zip([0, 1, 2], [3, 4, 5])
>>> s
[(0, 3), (1, 4), (2, 5)]
Python 3.x 3.0

Nel filter Python 3, map e zip restituiscono invece iterator:

>>> it = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> it
<filter object at 0x00000098A55C2518>
>>> ''.join(it)
'abc'
>>> it = map(lambda x: x * x, [0, 1, 2])
>>> it
<map object at 0x000000E0763C2D30>
>>> list(it)
[0, 1, 4]
>>> it = zip([0, 1, 2], [3, 4, 5])
>>> it
<zip object at 0x000000E0763C52C8>
>>> list(it)
[(0, 3), (1, 4), (2, 5)]

Poiché Python 2 itertools.izip è equivalente a Python 3 zip izip è stato rimosso su Python 3.

Importazioni assolute / relative

In Python 3, PEP 404 cambia il modo in cui le importazioni funzionano da Python 2. Le importazioni relative implicite non sono più consentite nei pacchetti e from ... import * import sono consentite solo nel codice a livello di modulo.

Per ottenere il comportamento di Python 3 in Python 2:

  • la funzione di importazione assoluta può essere abilitata con from __future__ import absolute_import
  • le importazioni relative esplicite sono incoraggiate al posto delle importazioni relative implicite

Per chiarimenti, in Python 2, un modulo può importare il contenuto di un altro modulo situato nella stessa directory come segue:

import foo

Si noti che la posizione di foo è ambigua dalla sola dichiarazione di importazione. Questo tipo di importazione relativa implicita è quindi scoraggiato a favore delle importazioni relative esplicite , che assomigliano alle seguenti:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

Il punto . consente una dichiarazione esplicita della posizione del modulo all'interno dell'albero delle directory.


Maggiori informazioni sulle importazioni relative

Prendi in considerazione un pacchetto definito dall'utente chiamato shapes . La struttura della directory è la seguente:

shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py

circle.py , square.py e triangle.py importano util.py come modulo. Come faranno riferimento a un modulo nello stesso livello?

 from . import util # use util.PI, util.sq(x), etc

O

 from .util import * #use PI, sq(x), etc to call functions

Il . è usato per importazioni relative allo stesso livello.

Ora, considera un layout alternativo del modulo shapes :

shapes
├── __init__.py
|
├── circle
│   ├── __init__.py
│   └── circle.py
|
├── square
│   ├── __init__.py
│   └── square.py
|
├── triangle
│   ├── __init__.py
│   ├── triangle.py
|
└── util.py

Ora, in che modo queste 3 classi si riferiscono a util.py?

 from .. import util # use util.PI, util.sq(x), etc

O

 from ..util import * # use PI, sq(x), etc to call functions

Il .. è usato per importazioni relative a livello di genitore. Aggiungi altro . s con il numero di livelli tra genitore e figlio.

File I / O

file non è più un nome incorporato in 3.x ( open funziona ancora).

I dettagli interni del file I / O sono stati spostati nel modulo io libreria standard, che è anche la nuova casa di StringIO :

import io
assert io.open is open # the builtin is an alias
buffer = io.StringIO()
buffer.write('hello, ') # returns number of characters written
buffer.write('world!\n')
buffer.getvalue() # 'hello, world!\n'

La modalità file (testo vs binario) ora determina il tipo di dati prodotti dalla lettura di un file (e il tipo richiesto per la scrittura):

with open('data.txt') as f:
    first_line = next(f)
    assert type(first_line) is str
with open('data.bin', 'rb') as f:
    first_kb = f.read(1024)
    assert type(first_kb) is bytes

La codifica per i file di testo ha come valore predefinito quello che viene restituito da locale.getpreferredencoding(False) . Per specificare esplicitamente una codifica, utilizzare il parametro della parola chiave encoding :

with open('old_japanese_poetry.txt', 'shift_jis') as text:
    haiku = text.read()

La funzione round () tie-break e return

round () tie break

In Python 2, l'uso di round() su un numero uguale a due numeri interi restituirà quello più lontano da 0. Ad esempio:

Python 2.x 2.7
round(1.5)  # Out: 2.0
round(0.5)  # Out: 1.0
round(-0.5)  # Out: -1.0
round(-1.5)  # Out: -2.0

In Python 3 tuttavia, round() restituirà l'intero pari (ovvero l'arrotondamento dei banchieri ). Per esempio:

Python 3.x 3.0
round(1.5)  # Out: 2
round(0.5)  # Out: 0
round(-0.5)  # Out: 0
round(-1.5)  # Out: -2

La funzione round () segue la strategia di arrotondamento da mezzo a arrotondamento che arrotonderà i numeri a metà fino al numero intero pari più vicino (ad esempio, round(2.5) restituisce 2 anziché 3.0).

Come riferimento in Wikipedia , questo è anche conosciuto come arrotondamento imparziale , arrotondamento convergente , arrotondamento di uno statistico, arrotondamento olandese , arrotondamento gaussiano o arrotondamento dispari-pari .

La metà dell'arrotondamento è parte dello standard IEEE 754 ed è anche la modalità di arrotondamento predefinita in .NET di Microsoft.

Questa strategia di arrotondamento tende a ridurre l'errore di arrotondamento totale. Poiché in media la quantità di numeri arrotondati è uguale alla quantità di numeri arrotondati, gli errori di arrotondamento vengono annullati. Altri metodi di arrotondamento tendono invece ad avere una tendenza verso l'alto o verso il basso nell'errore medio.


round () tipo di ritorno

La funzione round() restituisce un tipo float in Python 2.7

Python 2.x 2.7
round(4.8)
# 5.0

A partire da Python 3.0, se il secondo argomento (numero di cifre) viene omesso, restituisce un int .

Python 3.x 3.0
round(4.8)
# 5

Vero, Falso e Nessuno

In Python 2, True , False e None sono costanti incorporate. Il che significa che è possibile riassegnarli.

Python 2.x 2.0
True, False = False, True
True   # False
False  # True

Non puoi farlo con None da Python 2.4.

Python 2.x 2.4
None = None  # SyntaxError: cannot assign to None

In Python 3, True , False e None ora sono le parole chiave.

Python 3.x 3.0
True, False = False, True  # SyntaxError: can't assign to keyword

None = None  # SyntaxError: can't assign to keyword

Restituisce valore quando si scrive su un oggetto file

In Python 2, scrivere direttamente su un handle di file restituisce None :

Python 2.x 2.3
hi = sys.stdout.write('hello world\n')
# Out: hello world
type(hi)
# Out: <type 'NoneType'>

In Python 3, la scrittura su un handle restituirà il numero di caratteri scritti durante la scrittura del testo e il numero di byte scritti durante la scrittura di byte:

Python 3.x 3.0
import sys

char_count = sys.stdout.write('hello world 🐍\n')
# Out: hello world 🐍
char_count
# Out: 14

byte_count = sys.stdout.buffer.write(b'hello world \xf0\x9f\x90\x8d\n')
# Out: hello world 🐍
byte_count
# Out: 17

long vs. int

In Python 2, qualsiasi intero più grande di un C ssize_t verrebbe convertito nel tipo di dati long , indicato da un suffisso L sul letterale. Ad esempio, su una build di Python a 32 bit:

Python 2.x 2.7
>>> 2**31
2147483648L
>>> type(2**31)
<type 'long'>
>>> 2**30
1073741824
>>> type(2**30)
<type 'int'>
>>> 2**31 - 1  # 2**31 is long and long - int is long
2147483647L

Tuttavia, in Python 3, il long tipo di dati è stato rimosso; non importa quanto sia grande il numero intero, sarà un int .

Python 3.x 3.0
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>

Classe Valore booleano

Python 2.x 2.7

In Python 2, se si desidera definire un valore booleano della classe da soli, è necessario implementare il metodo __nonzero__ sulla classe. Il valore è True per impostazione predefinita.

class MyClass:
    def __nonzero__(self):
        return False

my_instance = MyClass()
print bool(MyClass)       # True
print bool(my_instance)   # False
Python 3.x 3.0

In Python 3, __bool__ è usato al posto di __nonzero__

class MyClass:
    def __bool__(self):
        return False

my_instance = MyClass()
print(bool(MyClass))       # True
print(bool(my_instance))   # False


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow