Python Language
Onverenigbaarheden die van Python 2 naar Python 3 gaan
Zoeken…
Invoering
In tegenstelling tot de meeste talen ondersteunt Python twee hoofdversies. Sinds 2008, toen Python 3 werd uitgebracht, hebben velen de overstap gemaakt, terwijl velen dat niet hebben gedaan. Om beide te begrijpen, behandelt dit gedeelte de belangrijke verschillen tussen Python 2 en Python 3.
Opmerkingen
Er zijn momenteel twee ondersteunde versies van Python: 2.7 (Python 2) en 3.6 (Python 3). Bovendien ontvangen versies 3.3 en 3.4 beveiligingsupdates in bronformaat.
Python 2.7 is achterwaarts compatibel met de meeste eerdere versies van Python en kan Python-code van de meeste 1.x- en 2.x-versies van Python ongewijzigd uitvoeren. Het is breed verkrijgbaar, met een uitgebreide verzameling pakketten. Het wordt ook beschouwd als verouderd door de CPython-ontwikkelaars en ontvangt alleen beveiliging en bug-fix ontwikkeling. De CPython-ontwikkelaars zijn van plan deze versie van de taal in 2020 te verlaten.
Volgens Python Enhancement Voorstel 373 zijn er geen geplande toekomstige releases van Python 2 na 25 juni 2016, maar bugfixes en beveiligingsupdates worden ondersteund tot 2020. (Het specificeert niet welke exacte datum in 2020 de zonsondergangsdatum van Python zal zijn 2.)
Python 3 brak opzettelijk achteruit-compatibiliteit, om de zorgen van de taalontwikkelaars met de kern van de taal weg te nemen. Python 3 ontvangt nieuwe ontwikkeling en nieuwe functies. Het is de versie van de taal waarmee de taalontwikkelaars verder willen gaan.
In de loop van de tijd tussen de eerste release van Python 3.0 en de huidige versie, werden sommige functies van Python 3 back-ported naar Python 2.6, en andere delen van Python 3 werden uitgebreid om syntax te hebben die compatibel is met Python 2. Daarom is het mogelijk om te schrijven Python die werkt op zowel Python 2 als Python 3, door toekomstige import en speciale modules (zoals zes ) te gebruiken.
Toekomstige invoer moet aan het begin van uw module staan:
from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')
Zie de relevante pagina in de Python-documentatie voor meer informatie over de __future__
module.
De 2to3-tool is een Python-programma dat Python 2.x-code omzet in Python 3.x-code, zie ook de Python-documentatie .
Pakket zes biedt hulpprogramma's voor compatibiliteit met Python 2/3:
- uniforme toegang tot hernoemde bibliotheken
- variabelen voor string / unicode-types
- functies voor de methode die is verwijderd of waarvan de naam is gewijzigd
Een verzoek om verschillen tussen Python 2 en Python 3 vindt hier .
Afdrukverklaring versus afdrukfunctie
In Python 2 is print
een statement:
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 is print()
een functie, met trefwoordargumenten voor algemeen gebruik:
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)"
De afdrukfunctie heeft de volgende parameters:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
sep
is wat de objecten scheidt die u wilt afdrukken. Bijvoorbeeld:
print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar
end
is waar het einde van de afdrukopdracht door wordt gevolgd. Bijvoorbeeld:
print('foo', 'bar', end='!') # out: foo bar!
Opnieuw afdrukken na een niet-nieuwe regel met een einde-instructie wordt op dezelfde regel afgedrukt:
print('foo', end='~')
print('bar')
# out: foo~bar
Opmerking: Voor toekomstige compatibiliteit, print
functie is ook beschikbaar in Python 2.6 zijn gelegd; maar het kan niet worden gebruikt, tenzij het ontleden van de print
statement is uitgeschakeld met
from __future__ import print_function
Deze functie heeft exact dezelfde indeling als die van Python 3, behalve dat deze de parameter flush
mist.
Zie PEP 3105 voor de reden.
Tekenreeksen: Bytes versus Unicode
In Python 2 zijn er twee varianten van tekenreeksen: die van bytes met type ( str
) en die van tekst met type ( unicode
).
In Python 2 is een object van het type str
altijd een byte-reeks, maar wordt meestal gebruikt voor zowel tekst als binaire gegevens.
Een letterlijke tekenreeks wordt geïnterpreteerd als een byte-reeks.
s = 'Cafe' # type(s) == str
Er zijn twee uitzonderingen: u kunt een letterlijke Unicode (tekst) expliciet definiëren door het letterlijke vooraf te laten gaan door u
:
s = u'Café' # type(s) == unicode
b = 'Lorem ipsum' # type(b) == str
Als alternatief kunt u opgeven dat de stringliterals van een hele module Unicode (tekst) literals moeten maken:
from __future__ import unicode_literals
s = 'Café' # type(s) == unicode
b = 'Lorem ipsum' # type(b) == unicode
Om te controleren of uw variabele een string is (Unicode of een byte-string), kunt u het volgende gebruiken:
isinstance(s, basestring)
In Python 3 is het str
type een Unicode-teksttype.
s = 'Cafe' # type(s) == str
s = 'Café' # type(s) == str (note the accented trailing e)
Bovendien heeft Python 3 een bytes
object toegevoegd, geschikt voor binaire "blobs" of schrijven naar coderingsonafhankelijke bestanden. Om een bytes-object te maken, kunt u b
voorafgaan door een letterlijke tekenreeks of de encode
de tekenreeks aanroepen:
# Or, if you really need a byte string:
s = b'Cafe' # type(s) == bytes
s = 'Café'.encode() # type(s) == bytes
Gebruik om te testen of een waarde een string is:
isinstance(s, str)
Het is ook mogelijk om stringliterals te prefixen met een u
prefix om de compatibiliteit tussen Python 2 en Python 3-codebases te vergemakkelijken. Omdat in Python 3 alle tekenreeksen standaard Unicode zijn, heeft een letterlijke tekenreeks voorafgaan met u
geen effect:
u'Cafe' == 'Cafe'
Het onbewerkte Unicode-tekenreeksvoorvoegsel ur
Python 2 wordt echter niet ondersteund:
>>> ur'Café'
File "<stdin>", line 1
ur'Café'
^
SyntaxError: invalid syntax
Merk op dat u een Python 3-tekstobject ( str
) moet encode
om het te converteren naar een bytes
van die tekst. De standaardcodering van deze methode is UTF-8 .
U kunt decode
gebruiken om een bytes
object te vragen voor welke Unicode-tekst het vertegenwoordigt:
>>> b.decode()
'Café'
Hoewel het type bytes
voorkomt in zowel Python 2 als 3, bestaat het type unicode
alleen in Python 2. Om de impliciete Unicode-tekenreeksen van Python 3 in Python 2 te gebruiken, voegt u het volgende toe aan de bovenkant van uw codebestand:
from __future__ import unicode_literals
print(repr("hi"))
# u'hi'
Een ander belangrijk verschil is dat indexeringsbytes in Python 3 resulteren in een int
uitvoer zoals deze:
b"abc"[0] == 97
Terwijl het snijden in een grootte van één resulteert in een object van lengte 1 bytes:
b"abc"[0:1] == b"a"
Bovendien lost Python 3 wat ongebruikelijk gedrag op met Unicode, dat wil zeggen het omkeren van byte-strings in Python 2. Het volgende probleem is bijvoorbeeld opgelost:
# -*- 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
Integer divisie
De standaardverdeling teken ( /
) werkt anders in Python 3 Python en 2 wanneer toegepast op gehele getallen.
Wanneer een geheel getal wordt __truediv__
door een ander geheel getal in Python 3, vertegenwoordigt de __truediv__
x / y
een echte deling (gebruikt de methode __truediv__
) en produceert een drijvend __truediv__
. Ondertussen vertegenwoordigt dezelfde operatie in Python 2 een klassieke verdeling die het resultaat naar beneden afrondt naar negatieve oneindigheid (ook bekend als het woord nemen ).
Bijvoorbeeld:
Code | Python 2-uitgang | Python 3-uitgang |
---|---|---|
3 / 2 | 1 | 1.5 |
2 / 3 | 0 | ,6666666666666666 |
-3 / 2 | -2 | -1.5 |
Het afronden naar nul-gedrag werd afgeschaft in Python 2.2 , maar blijft in Python 2.7 omwille van achterwaartse compatibiliteit en werd verwijderd in Python 3.
Opmerking: om een zwevend resultaat in Python 2 te krijgen (zonder afronding van de vloer) kunnen we een van de operanden met de decimale punt opgeven. Het bovenstaande voorbeeld van 2/3
dat 0
geeft in Python 2 zal worden gebruikt als 2 / 3.0
of 2.0 / 3
of 2.0/3.0
om 0.6666666666666666
te krijgen
Code | Python 2-uitgang | Python 3-uitgang |
---|---|---|
3.0 / 2.0 | 1.5 | 1.5 |
2 / 3.0 | ,6666666666666666 | ,6666666666666666 |
-3.0 / 2 | -1.5 | -1.5 |
Er is ook de operator voor vloerdeling ( //
), die in beide versies op dezelfde manier werkt: deze rondt af naar het dichtstbijzijnde gehele getal. (hoewel een float wordt geretourneerd wanneer deze wordt gebruikt met floats) In beide versies wordt de //
-operator __floordiv__
aan __floordiv__
.
Code | Python 2-uitgang | Python 3-uitgang |
---|---|---|
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 |
Men kan expliciet ware verdeling of vloerdeling afdwingen met behulp van native functies in de operator
:
from operator import truediv, floordiv
assert truediv(10, 8) == 1.25 # equivalent to `/` in Python 3
assert floordiv(10, 8) == 1 # equivalent to `//`
Hoewel duidelijk en expliciet, kan het gebruik van operatorfuncties voor elke divisie vervelend zijn. Het gedrag van de operator /
zal vaak de voorkeur hebben. Een veel voorkomende praktijk is het elimineren van typisch divisiegedrag door het toevoegen from __future__ import division
als de eerste instructie in elke module:
# needs to be the first statement in a module
from __future__ import division
Code | Python 2-uitgang | Python 3-uitgang |
---|---|---|
3 / 2 | 1.5 | 1.5 |
2 / 3 | ,6666666666666666 | ,6666666666666666 |
-3 / 2 | -1.5 | -1.5 |
from __future__ import division
garandeert dat de /
operator echte divisie vertegenwoordigt en alleen binnen de modules die de __future__
import bevatten, dus er zijn geen dwingende redenen om het niet in alle nieuwe modules in te schakelen.
Opmerking : sommige andere programmeertalen gebruiken afronding naar nul (truncatie) in plaats van naar beneden af te ronden naar negatieve oneindigheid zoals Python doet (dwz in die talen -3 / 2 == -1
). Dit gedrag kan verwarring veroorzaken bij het overdragen of vergelijken van code.
Opmerking over float-operanden : als alternatief voor de from __future__ import division
, zou u het gebruikelijke divisiesymbool kunnen gebruiken /
en ervoor zorgen dat ten minste een van de operanden een float is: 3 / 2.0 == 1.5
. Dit kan echter als een slechte gewoonte worden beschouwd. Het is gewoon te gemakkelijk om average = sum(items) / len(items)
en een van de argumenten te vergeten om te zweven. Bovendien kunnen dergelijke gevallen tijdens het testen vaak aan een melding ontsnappen, bijvoorbeeld als u test op een array met float
maar een array met int
's in productie ontvangt. Bovendien, als dezelfde code wordt gebruikt in Python 3, werken programma's die verwachten dat 3/2 3 / 2 == 1
True is, niet correct.
Zie PEP 238 voor meer gedetailleerde redenen waarom de divisie-operator is veranderd in Python 3 en waarom een indeling in oude stijl moet worden vermeden.
Zie het onderwerp Simple Math voor meer informatie over deling.
Reduce is niet langer ingebouwd
In Python 2 is reduce
beschikbaar als een ingebouwde functie of uit het functools
pakket (vanaf versie 2.6), terwijl in Python 3 reduce
alleen beschikbaar is via functools
. De syntaxis voor reduce
in zowel Python2 als Python3 is echter hetzelfde en is reduce(function_to_reduce, list_to_reduce)
.
Laten we als voorbeeld overwegen om een lijst te reduceren tot een enkele waarde door elk van de aangrenzende getallen te delen. Hier gebruiken we de truediv
functie uit de operator
.
In Python 2.x is het zo simpel als:
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator
>>> reduce(operator.truediv, my_list)
0.008333333333333333
In Python 3.x wordt het voorbeeld een beetje ingewikkelder:
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator, functools
>>> functools.reduce(operator.truediv, my_list)
0.008333333333333333
We kunnen ook gebruik maken from functools import reduce
om te voorkomen dat reduce
met de naamruimte.
Verschillen tussen bereik- en xrange-functies
In Python 2, range
functie een lijst terwijl xrange
wordt een speciale xrange
object, dat een onveranderlijke sequentie, die in tegenstelling tot andere ingebouwde types sequentie niet support snijden en noch index
of count
methoden:
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
uitgebreid met het range
sequentie die aldus ontstaat nu een range
object. Er is geen xrange
type:
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
Bovendien ondersteunt het range
sinds Python 3.2 ook slicing, index
en 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
Het voordeel van het gebruik van een speciaal sequentietype in plaats van een lijst, is dat de tolk geen geheugen hoeft toe te wijzen voor een lijst en deze moet invullen:
# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# MemoryError
print(xrange(100000000000000000))
# Out: xrange(100000000000000000)
Aangezien deze laatste gedrag in het algemeen gewenst is, werd de voormalige verwijderd in Python 3. Als u nog wilt een lijst in Python 3, kunt u gewoon het gebruik list()
aannemer op een range
object:
print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Compatibiliteit
Om de compatibiliteit tussen zowel de Python 2.x- als de Python 3.x-versies te behouden, kunt u de builtins
module uit het future
pakket future
gebruiken om zowel voorwaartse compatibiliteit als achterwaartse compatibiliteit te bereiken :
#forward-compatible
from builtins import range
for i in range(10**8):
pass
#backward-compatible
from past.builtins import xrange
for i in xrange(10**8):
pass
Het range
in de future
bibliotheek ondersteunt slicing, index
en count
in alle Python-versies, net als de ingebouwde methode op Python 3.2+.
Iterables uitpakken
In Python 3 kun je een iterable uitpakken zonder het exacte aantal items te kennen, en zelfs een variabele aan het einde van de iterable hebben. Daarvoor geeft u een variabele op die een zoeklijst kan verzamelen. Dit doet u door een asterisk voor de naam te plaatsen. Bijvoorbeeld, een list
uitpakken:
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
Opmerking : wanneer u de syntaxis van de *variable
, is de variable
altijd een lijst, zelfs als het oorspronkelijke type geen lijst was. Het kan nul of meer elementen bevatten, afhankelijk van het aantal elementen in de oorspronkelijke lijst.
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
Evenzo, een str
uitpakken:
begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']
Voorbeeld van het uitpakken van een date
; _
Wordt gebruikt in dit voorbeeld als een wegwerpartikel variabele (we zijn alleen geïnteresseerd in year
-waarde):
person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016
Het is vermeldenswaard dat, omdat *
een variabel aantal items opeet, je geen twee *
s voor dezelfde iterable in een opdracht kunt hebben - het zou niet weten hoeveel elementen in de eerste uitpakken gaan en hoeveel in de tweede :
*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment
Tot nu toe hebben we het uitpakken in opdrachten besproken. *
en **
werden uitgebreid in Python 3.5 . Het is nu mogelijk om meerdere uitpakhandelingen in één expressie uit te voeren:
{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}
Het is ook mogelijk om een iterabele uit te pakken in functieargumenten:
iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5
Bij het uitpakken van een woordenboek worden twee aangrenzende sterren **
( PEP 448 ) gebruikt:
tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
# Out: {'x': 1, 'y': 2, 'z': 3}
Dit maakt zowel het overschrijven van oude waarden als het samenvoegen van woordenboeken mogelijk.
dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}
Python 3 verwijderde tuple uitpakken in functies. Daarom werkt het volgende niet 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
Zie PEP 3113 voor gedetailleerde redenen.
Opheffen en hanteren Uitzonderingen
Dit is de Python 2 syntax, let op de komma's ,
op de raise
en except
lijnen:
try:
raise IOError, "input/output error"
except IOError, exc:
print exc
In Python 3, de ,
syntax wordt beëindigd en vervangen door haakjes en as
trefwoord:
try:
raise IOError("input/output error")
except IOError as exc:
print(exc)
Voor achterwaartse compatibiliteit is de syntaxis van Python 3 ook beschikbaar in Python 2.6 en hoger, dus deze moet worden gebruikt voor alle nieuwe code die niet compatibel hoeft te zijn met eerdere versies.
Python 3 voegt ook uitzonderingsketen toe , waarin u kunt aangeven dat een andere uitzondering de oorzaak van deze uitzondering was. Bijvoorbeeld
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}') from e
De uitzondering die in de except
statement wordt opgeworpen, is van het type DatabaseError
, maar de oorspronkelijke uitzondering is gemarkeerd als het kenmerk __cause__
van die uitzondering. Wanneer de traceback wordt weergegeven, wordt de oorspronkelijke uitzondering ook weergegeven in de 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')
Als je een except
blok gooit zonder expliciete kettingvorming:
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}')
De traceback is
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')
Geen van beide wordt ondersteund in Python 2.x; de oorspronkelijke uitzondering en de traceback ervan gaan verloren als een andere uitzondering wordt opgeworpen in het uitzonderingsblok. De volgende code kan worden gebruikt voor compatibiliteit:
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")
Gebruik raise from None
de eerder geworpen uitzondering te "vergeten"
try:
file = open('database.db')
except FileNotFoundError as e:
raise DatabaseError('Cannot open {}') from None
Nu zou de traceback eenvoudig zijn
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Of om het compatibel te maken met zowel Python 2 als 3 kunt u het six- pakket als volgt gebruiken:
import six
try:
file = open('database.db')
except FileNotFoundError as e:
six.raise_from(DatabaseError('Cannot open {}'), None)
.next () methode op iterators hernoemd
In Python 2 kan een iterator worden doorkruist met behulp van een methode met de naam next
op de iterator zelf:
g = (i for i in range(0, 3))
g.next() # Yields 0
g.next() # Yields 1
g.next() # Yields 2
In Python 3 is de .next
methode hernoemd naar .__next__
, waarbij de "magische" rol .__next__
wordt erkend, dus het aanroepen van .next
zal een AttributeError
oproepen. De juiste manier om toegang te krijgen tot deze functionaliteit in zowel Python 2 als Python 3 is door de next
functie met de iterator als argument aan te roepen.
g = (i for i in range(0, 3))
next(g) # Yields 0
next(g) # Yields 1
next(g) # Yields 2
Deze code is draagbaar in versies van 2.6 tot en met huidige releases.
Vergelijking van verschillende types
Verschillende soorten objecten kunnen worden vergeleken. De resultaten zijn willekeurig, maar consistent. Ze zijn zo geordend dat None
minder is dan iets anders, numerieke typen zijn kleiner dan niet-numerieke typen en al het andere is lexicografisch geordend per type. Een int
is dus minder dan een str
en een tuple
is groter dan een 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
Dit werd oorspronkelijk gedaan om een lijst met gemengde typen te sorteren en objecten te groeperen op type:
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)]
Er wordt een uitzondering gemaakt bij het vergelijken van verschillende (niet-numerieke) typen:
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()
Om gemengde lijsten in Python 3 op type te sorteren en compatibiliteit tussen versies te bereiken, moet u een sleutel voor de gesorteerde functie opgeven:
>>> 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}]
Door str
als de key
wordt elk item tijdelijk alleen ter vergelijking geconverteerd naar een string. Vervolgens wordt de tekenreeksrepresentatie weergegeven die begint met [
, '
, {
of 0-9
en kan deze (en alle volgende tekens) sorteren.
Gebruikers invoer
In Python 2 wordt gebruikersinvoer geaccepteerd met de functie raw_input
,
user_input = raw_input()
Terwijl in Python 3 gebruikersinvoer wordt geaccepteerd met behulp van de input
.
user_input = input()
In Python 2, de input
zal de functie accepteren input en interpreteren. Hoewel dit nuttig kan zijn, heeft het verschillende beveiligingsoverwegingen en is het verwijderd in Python 3. Om toegang te krijgen tot dezelfde functionaliteit, kan eval(input())
worden gebruikt.
Om een script draagbaar te houden tussen de twee versies, kunt u de onderstaande code boven aan uw Python-script plaatsen:
try:
input = raw_input
except NameError:
pass
Woordenboekmethode verandert
In Python 3 verschillen veel van de woordenboekmethoden in gedrag behoorlijk van Python 2, en vele zijn ook verwijderd: has_key
, iter*
en view*
zijn verdwenen. In plaats van d.has_key(key)
, die al lang niet meer werd gebruikt, moet nu de key in d
.
In Python 2 retourneert woordenboekmethoden keys
, values
en items
retourlijsten. In Python 3 keren ze in plaats daarvan view- objecten terug; de view-objecten zijn geen iterators en ze verschillen er op twee manieren van, namelijk:
- ze hebben maat (men kan de
len
functie erop gebruiken) - ze kunnen vele malen worden herhaald
Bovendien worden, net als bij iterators, de wijzigingen in het woordenboek weerspiegeld in de weergaveobjecten.
Python 2.7 heeft deze methoden teruggevoerd vanuit Python 3; ze zijn beschikbaar als viewkeys
, viewvalues
en viewitems
. Om Python 2-code om te zetten in Python 3-code zijn de overeenkomstige vormen:
-
d.keys()
,d.values()
end.items()
van Python 2 moeten worden gewijzigd inlist(d.keys())
,list(d.values())
enlist(d.items())
-
d.iterkeys()
,d.itervalues()
end.iteritems()
moeten worden gewijzigd initer(d.keys())
, of nog beter,iter(d)
;iter(d.values())
eniter(d.items())
respectievelijk - en tot slot kan de methode Python 2.7 de aanroepen van
d.viewkeys()
,d.viewvalues()
end.viewitems()
worden vervangen doord.keys()
,d.values()
end.items()
.
Het is soms lastig om Python 2-code over te dragen die itereert over woordenboeksleutels, waarden of items tijdens het muteren. Overwegen:
d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
if key.isalpha():
del d[key]
De code ziet eruit alsof het op dezelfde manier zou werken in Python 3, maar daar retourneert de keys
een weergaveobject, geen lijst, en als het woordenboek van grootte verandert terwijl het wordt herhaald, crasht de Python 3-code met RuntimeError: dictionary changed size during iteration
. De oplossing is natuurlijk om goed te schrijven for key in list(d)
.
Evenzo gedragen weergaveobjecten zich anders dan iterators: men kan daarop geen next()
gebruiken en men kan iteratie niet hervatten ; het zou in plaats daarvan opnieuw opstarten; als de Python 2-code de retourwaarde van d.iterkeys()
, d.itervalues()
of d.iteritems()
aan een methode die een iterator verwacht in plaats van een iterabele , dan is dat iter(d)
, iter(d.values())
of iter(d.items())
in Python 3.
exec-instructie is een functie in Python 3
In Python 2 is exec
een statement, met speciale syntaxis: exec code [in globals[, locals]].
In Python 3 is exec
nu een functie: exec(code, [, globals[, locals]])
, en de syntaxis van Python 2 verhoogt een SyntaxError
.
Omdat print
van instructie werd veranderd in een functie, werd ook een __future__
import toegevoegd. Er is echter geen from __future__ import exec_function
, omdat het niet nodig is: de exec-instructie in Python 2 kan ook worden gebruikt met syntaxis die precies lijkt op de aanroep van de exec
functie in Python 3. U kunt dus de instructies wijzigen
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars
naar vormen
exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)
en de laatste vormen werken gegarandeerd identiek in zowel Python 2 als Python 3.
hasattr-functiebug in Python 2
Wanneer in Python 2 een eigenschap een fout hasattr
zal hasattr
deze eigenschap negeren en False
retourneren.
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
Deze bug is opgelost in Python3. Dus als je Python 2 gebruikt, gebruik dan
try:
a.get
except AttributeError:
print("no get property!")
of gebruik getattr
plaats daarvan getattr
p = getattr(a, "get", None)
if p is not None:
print(p)
else:
print("no get property!")
Hernoemde modules
Enkele modules in de standaardbibliotheek zijn hernoemd:
Oude naam | Nieuwe naam |
---|---|
_winreg | winreg |
ConfigParser | configparser |
copy_reg | copyreg |
Wachtrij | wachtrij |
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 |
Sommige modules zijn zelfs geconverteerd van bestanden naar bibliotheken. Neem als voorbeeld tkinter en urllib van bovenaf.
Compatibiliteit
Als u de compatibiliteit tussen beide Python 2.x- en 3.x-versies wilt behouden, kunt u het future
externe pakket gebruiken om het importeren van standaardbibliotheekpakketten op het hoogste niveau met Python 3.x-namen in Python 2.x-versies mogelijk te maken.
Octale constanten
In Python 2 kan een octaal letterlijk worden gedefinieerd als
>>> 0755 # only Python 2
Gebruik om compatibiliteit te garanderen
0o755 # both Python 2 and Python 3
Alle klassen zijn "nieuwe stijl klassen" in Python 3.
In Python 3.x
alle klassen klassen in nieuwe stijl ; wanneer het definiëren van een nieuwe klasse python impliciet laat erven van object
. Als zodanig specificeren object
in een class
definitie een volledig optioneel:
class X: pass
class Y(object): pass
Beide klassen bevatten nu object
in hun mro
(volgorde van methode-resolutie):
>>> X.__mro__
(__main__.X, object)
>>> Y.__mro__
(__main__.Y, object)
In Python 2.x
klassen standaard klassen in oude stijl; ze erven niet impliciet van het object
. Dit zorgt ervoor dat de semantiek van de klassen te verschillen afhankelijk van of we expliciet toe te voegen object
als een base class
:
class X: pass
class Y(object): pass
In dit geval, als we proberen de __mro__
van Y
af te drukken, verschijnt een vergelijkbare uitvoer als die in het geval van Python 3.x
:
>>> Y.__mro__
(<class '__main__.Y'>, <type 'object'>)
Dit gebeurt omdat we Y
expliciet van het object hebben laten erven bij het definiëren: class Y(object): pass
. Voor klasse X
die niet van het object __mro__
kenmerk __mro__
niet. Als u toegang probeert te krijgen, resulteert dit in een AttributeError
.
Om compatibiliteit tussen beide versies van Python te garanderen , kunnen klassen met object
worden gedefinieerd als een basisklasse:
class mycls(object):
"""I am fully compatible with Python 2/3"""
Als alternatief, als de variabele __metaclass__
is ingesteld om te type
op globaal bereik, zijn alle vervolgens gedefinieerde klassen in een bepaalde module impliciet nieuw van stijl zonder expliciet van het object
erven:
__metaclass__ = type
class mycls:
"""I am also fully compatible with Python 2/3"""
Operators verwijderd <> en ``, synoniem met! = En repr ()
In Python 2 is <>
een synoniem voor !=
; op dezelfde manier is `foo`
een synoniem voor repr(foo)
.
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
>>> 1 <> 2
File "<stdin>", line 1
1 <> 2
^
SyntaxError: invalid syntax
>>> `foo`
File "<stdin>", line 1
`foo`
^
SyntaxError: invalid syntax
coderen / decoderen naar hex niet langer beschikbaar
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
"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'
Echter, zoals voorgesteld door het foutbericht, kunt u de codecs
module gebruiken om hetzelfde resultaat te bereiken:
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'
Merk op dat codecs.encode
een bytes
object retourneert. Om een str
object te verkrijgen, decode
u gewoon naar ASCII:
codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'
cmp-functie verwijderd in Python 3
In Python 3 werd de ingebouwde functie cmp
verwijderd, samen met de speciale methode __cmp__
.
Uit de documentatie:
De functie
cmp()
moet worden behandeld als verdwenen en de speciale methode__cmp__()
wordt niet langer ondersteund. Gebruik__lt__()
voor het sorteren,__eq__()
met__hash__()
en andere uitgebreide vergelijkingen indien nodig. (Als u echt de functiecmp()
nodig hebt, kunt u de uitdrukking(a > b) - (a < b)
als equivalent voorcmp(a, b)
.)
Bovendien accepteren alle ingebouwde functies die de cmp
parameter hebben geaccepteerd nu alleen de parameter key
only.
In de functools
module is er ook een handige functie cmp_to_key(func)
waarmee je van een cmp
achtige functie naar een key
kunt converteren:
Transformeer een vergelijkingsfunctie in oude stijl naar een sleutelfunctie. Gebruikt met tools die belangrijke functies te accepteren (zoals
sorted()
,min()
,max()
,heapq.nlargest()
,heapq.nsmallest()
,itertools.groupby()
). Deze functie wordt voornamelijk gebruikt als een overgangstool voor programma's die worden geconverteerd vanuit Python 2 die het gebruik van vergelijkingsfuncties ondersteunen.
Gelekte variabelen in lijstbegrip
x = 'hello world!'
vowels = [x for x in 'AEIOU']
print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'
x = 'hello world!'
vowels = [x for x in 'AEIOU']
print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'hello world!'
Zoals te zien is in het voorbeeld, was in Python 2 de waarde van x
gelekt: het maskeerde hello world!
en uitgeprint U
, aangezien dit de laatste waarde van x
als de lus beëindigd.
Echter, in Python 3 x
drukt de oorspronkelijk gedefinieerde hello world!
, omdat de lokale variabele uit het lijstbegrip geen variabelen uit het omringende bereik maskeert.
Bovendien lekken noch generatoruitdrukkingen (beschikbaar in Python sinds 2.5), noch woordenboek of setbegrippen (die werden teruggevoerd naar Python 2.7 uit Python 3) variabelen in Python 2.
Merk op dat in zowel Python 2 als Python 3 variabelen in het omringende bereik lekken bij gebruik van een for-lus:
x = 'hello world!'
vowels = []
for x in 'AEIOU':
vowels.append(x)
print(x)
# Out: 'U'
kaart()
map()
is een ingebouwde functie die handig is voor het toepassen van een functie op elementen van een iterabele. In Python 2 retourneert map
een lijst. In Python 3, map
retourneert een kaartobject, die een generator.
# 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 kunt u None
doorgeven om als identiteitsfunctie te dienen. Dit werkt niet meer in Python 3.
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
>>> 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
Bovendien, bij het passeren meerdere iterable als argument Python 2, map
pads de kortere iterables met None
(vergelijkbaar met itertools.izip_longest
). In Python 3 stopt de iteratie na de kortste iteratie.
In Python 2:
>>> 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:
>>> 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)]
Opmerking : gebruik in plaats van map
lijstbegrippen, die compatibel zijn met Python 2/3. map(str, [1, 2, 3, 4, 5])
vervangen map(str, [1, 2, 3, 4, 5])
:
>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']
filter (), map () en zip () retourneren iterators in plaats van reeksen
In Python 2 filter
map
en zip
ingebouwde functies een reeks terug. map
en zip
retourneren altijd een lijst, terwijl met filter
het retourtype afhankelijk is van het type gegeven parameter:
>>> 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)]
In Python 3 filter
, map
en zip
return iterator in plaats daarvan:
>>> 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)]
Sinds Python 2 is itertools.izip
equivalent van Python 3 zip
izip
is verwijderd op Python 3.
Absolute / relatieve invoer
In Python 3 verandert PEP 404 de manier waarop import werkt vanuit Python 2. Impliciete relatieve import is niet langer toegestaan in pakketten en from ... import *
import is alleen toegestaan in code op moduleniveau.
Om het gedrag van Python 3 in Python 2 te bereiken:
- de absolute
from __future__ import absolute_import
kan worden ingeschakeld metfrom __future__ import absolute_import
- expliciete relatieve invoer wordt aangemoedigd in plaats van impliciete relatieve invoer
Ter verduidelijking: in Python 2 kan een module de inhoud van een andere module in dezelfde map als volgt importeren:
import foo
Merk op dat de locatie van foo
dubbelzinnig is alleen al vanuit de importverklaring. Dit type impliciete relatieve import wordt dus afgeraden ten gunste van expliciete relatieve import , die er als volgt uitzien:
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
De stip .
staat een expliciete verklaring van de modulelocatie in de mapstructuur toe.
Meer over relatieve importen
Overweeg een door de gebruiker gedefinieerd pakket dat shapes
. De mappenstructuur is als volgt:
shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py
circle.py
, square.py
en triangle.py
importeren alle util.py
als een module. Hoe zullen ze verwijzen naar een module op hetzelfde niveau?
from . import util # use util.PI, util.sq(x), etc
OF
from .util import * #use PI, sq(x), etc to call functions
De .
wordt gebruikt voor relatieve invoer op hetzelfde niveau.
Overweeg nu een alternatieve lay-out van de shapes
:
shapes
├── __init__.py
|
├── circle
│ ├── __init__.py
│ └── circle.py
|
├── square
│ ├── __init__.py
│ └── square.py
|
├── triangle
│ ├── __init__.py
│ ├── triangle.py
|
└── util.py
Hoe zullen deze 3 klassen nu verwijzen naar util.py?
from .. import util # use util.PI, util.sq(x), etc
OF
from ..util import * # use PI, sq(x), etc to call functions
De ..
wordt gebruikt voor relatieve invoer op bovenliggend niveau. Voeg meer toe .
s met aantal niveaus tussen de ouder en het kind.
Bestand I / O
file
is niet langer een ingebouwde naam in 3.x ( open
werkt nog steeds).
Interne details van bestands-I / O zijn verplaatst naar de standaard bibliotheek io
module, die ook de nieuwe thuisbasis van 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'
De bestandsmodus (tekst versus binair) bepaalt nu het type gegevens dat wordt geproduceerd door het lezen van een bestand (en het type dat vereist is voor het schrijven):
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
De codering voor tekstbestanden is standaard ingesteld op alles wat wordt geretourneerd door locale.getpreferredencoding(False)
. Gebruik de parameter encoding
sleutelwoord om een codering expliciet op te geven:
with open('old_japanese_poetry.txt', 'shift_jis') as text:
haiku = text.read()
Het round () functie tie-breaking en return type
ronde () gelijkspel breekt
In Python 2 zal het gebruik van round()
op een getal dat even dicht bij twee gehele getallen ligt, het getal het verst van 0. Bijvoorbeeld:
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 retourneert round()
echter het even gehele getal (ook wel afronding van bankiers genoemd ). Bijvoorbeeld:
round(1.5) # Out: 2
round(0.5) # Out: 0
round(-0.5) # Out: 0
round(-1.5) # Out: -2
De functie round () volgt de strategie van de halve tot de even afronding die halverwege getallen naar het dichtstbijzijnde even gehele getal afrondt (bijvoorbeeld, round(2.5)
retourneert nu 2 in plaats van 3.0).
Per referentie in Wikipedia staat dit ook bekend als onpartijdige afronding , convergente afronding , statisticusafronding , Nederlandse afronding , Gaussiaanse afronding of oneven-even afronding .
Halve tot gelijkmatige afronding maakt deel uit van de IEEE 754- standaard en het is ook de standaardafrondingsmodus in .NET van Microsoft.
Deze afrondingsstrategie heeft de neiging de totale afrondingsfout te verminderen. Aangezien gemiddeld het aantal naar boven afgeronde getallen hetzelfde is als het aantal naar beneden afgeronde getallen, worden afrondingsfouten opgeheven. Andere afrondingsmethoden hebben in de regel de neiging om een opwaartse of neerwaartse afwijking in de gemiddelde fout te hebben.
round () retourtype
De functie round()
retourneert een float
type in Python 2.7
round(4.8)
# 5.0
Vanaf Python 3.0, als het tweede argument (aantal cijfers) wordt weggelaten, retourneert het een int
.
round(4.8)
# 5
Waar, onwaar en geen
In Python 2 zijn True
, False
en None
ingebouwde constanten. Wat betekent dat het mogelijk is om ze opnieuw toe te wijzen.
True, False = False, True
True # False
False # True
Je kunt dit niet doen met None
sinds Python 2.4.
None = None # SyntaxError: cannot assign to None
In Python 3 zijn True
, False
en None
nu sleutelwoorden.
True, False = False, True # SyntaxError: can't assign to keyword
None = None # SyntaxError: can't assign to keyword
Retourwaarde bij schrijven naar een bestandsobject
In Python 2 retourneert schrijven rechtstreeks naar een bestandsingang None
:
hi = sys.stdout.write('hello world\n')
# Out: hello world
type(hi)
# Out: <type 'NoneType'>
In Python 3 retourneert schrijven naar een handle het aantal tekens dat is geschreven bij het schrijven van tekst en het aantal bytes dat is geschreven bij het schrijven van bytes:
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
lang versus int
In Python 2 wordt elk geheel getal groter dan een C ssize_t
omgezet in het long
gegevenstype, aangegeven met een L
achtervoegsel op de letterlijke waarde. Bijvoorbeeld op een 32-bits versie van Python:
>>> 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
In Python 3 werd het long
gegevenstype echter verwijderd; maakt niet uit hoe groot het gehele getal is, het zal een int
.
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>
Klasse Booleaanse waarde
Als u in Python 2 zelf een Booleaanse waarde voor een klasse wilt definiëren, moet u de __nonzero__
methode in uw klasse implementeren. De waarde is standaard True.
class MyClass:
def __nonzero__(self):
return False
my_instance = MyClass()
print bool(MyClass) # True
print bool(my_instance) # False
In Python 3 wordt __bool__
gebruikt in plaats van __nonzero__
class MyClass:
def __bool__(self):
return False
my_instance = MyClass()
print(bool(MyClass)) # True
print(bool(my_instance)) # False