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:

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 is print() een functie, met trefwoordargumenten voor algemeen gebruik:

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)"

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

Python 2.x 2.7

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)
Python 3.x 3.0

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)
Python 3.x 3.3

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é'
Python 2.x 2.6

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'
Python 3.x 3.0

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:

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 wordt het voorbeeld een beetje ingewikkelder:

Python 3.x 3.0
>>> 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:

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 uitgebreid met het range sequentie die aldus ontstaat nu een range object. Er is geen xrange type:

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

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:

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)

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:

Python 3.x 3.0
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 :

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

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

Python 3.x 3.0

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
Python 3.x 3.5

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}
Python 2.x 2.0

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
Python 3.x 3.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.x 3.0

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:

Python 2.x 2.3
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.x 3.0

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')
Python 2.x 2.0

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")
Python 3.x 3.3

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:

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 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.

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

Deze code is draagbaar in versies van 2.6 tot en met huidige releases.

Vergelijking van verschillende types

Python 2.x 2.3

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)]
Python 3.x 3.0

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 ,

Python 2.x 2.3
user_input = raw_input()

Terwijl in Python 3 gebruikersinvoer wordt geaccepteerd met behulp van de input .

Python 3.x 3.0
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() en d.items() van Python 2 moeten worden gewijzigd in list(d.keys()) , list(d.values()) en list(d.items())
  • d.iterkeys() , d.itervalues() en d.iteritems() moeten worden gewijzigd in iter(d.keys()) , of nog beter, iter(d) ; iter(d.values()) en iter(d.items()) respectievelijk
  • en tot slot kan de methode Python 2.7 de aanroepen van d.viewkeys() , d.viewvalues() en d.viewitems() worden vervangen door d.keys() , d.values() en d.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

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

naar vormen

Python 3.x 3.0
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:

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

Beide klassen bevatten nu object in hun mro (volgorde van methode-resolutie):

Python 3.x 3.0
>>> 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 :

Python 2.x 2.3
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 :

Python 2.x 2.3
>>> 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) .

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

coderen / decoderen naar hex niet langer beschikbaar

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'

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 functie cmp() nodig hebt, kunt u de uitdrukking (a > b) - (a < b) als equivalent voor cmp(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

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!'

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.

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

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:

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)]

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

Python 2.x 2.7

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)]
Python 3.x 3.0

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 met from __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:

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 retourneert round() echter het even gehele getal (ook wel afronding van bankiers genoemd ). Bijvoorbeeld:

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

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

Python 2.x 2.7
round(4.8)
# 5.0

Vanaf Python 3.0, als het tweede argument (aantal cijfers) wordt weggelaten, retourneert het een int .

Python 3.x 3.0
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.

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

Je kunt dit niet doen met None sinds Python 2.4.

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

In Python 3 zijn True , False en None nu sleutelwoorden.

Python 3.x 3.0
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 :

Python 2.x 2.3
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:

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

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:

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

In Python 3 werd het long gegevenstype echter verwijderd; maakt niet uit hoe groot het gehele getal is, het zal een int .

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

Klasse Booleaanse waarde

Python 2.x 2.7

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
Python 3.x 3.0

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow