Szukaj…


Wprowadzenie

W przeciwieństwie do większości języków, Python obsługuje dwie główne wersje. Od 2008 roku, kiedy wydano Python 3, wielu dokonało tego przejścia, a wielu nie. Aby zrozumieć oba, w tej sekcji omówiono ważne różnice między Python 2 i Python 3.

Uwagi

Obecnie obsługiwane są dwie wersje Pythona: 2.7 (Python 2) i 3.6 (Python 3). Dodatkowo wersje 3.3 i 3.4 otrzymują aktualizacje zabezpieczeń w formacie źródłowym.

Python 2.7 jest wstecznie kompatybilny z większością wcześniejszych wersji Pythona i może uruchamiać kod Pythona z większości wersji Python 1.x i 2.x bez zmian. Jest szeroko dostępny, z obszerną kolekcją pakietów. Jest również uważany za przestarzały przez programistów CPython i otrzymuje tylko rozwój bezpieczeństwa i poprawiania błędów. Programiści CPython zamierzają porzucić tę wersję języka w 2020 roku .

Zgodnie z propozycją 373 dotyczącą ulepszenia Pythona nie ma planowanych przyszłych wersji Python 2 po 25 czerwca 2016 r., Ale poprawki błędów i aktualizacje zabezpieczeń będą obsługiwane do 2020 r. (Nie określa dokładnej daty w Pythonie w 2020 r. 2.)

Python 3 celowo zerwał z kompatybilnością wsteczną, aby uwzględnić obawy, które programiści mieli z rdzeniem języka. Python 3 otrzymuje nowe oprogramowanie i nowe funkcje. Jest to wersja języka, z którą programiści zamierzają się rozwijać.

W okresie między początkową wersją Pythona 3.0 a bieżącą wersją niektóre funkcje Pythona 3 zostały przeniesione z powrotem do Pythona 2.6, a inne części Pythona 3 zostały rozszerzone, aby mieć składnię zgodną z Pythonem 2. Dlatego możliwe jest pisanie Python, który będzie działał zarówno na Python 2, jak i Python 3, wykorzystując przyszłe importy i specjalne moduły (jak sześć ).

Przyszłe importowanie musi odbywać się na początku modułu:

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

Aby uzyskać więcej informacji na temat modułu __future__ , zobacz odpowiednią stronę w dokumentacji Pythona .

Narzędzie 2to3 to program w języku Python, który konwertuje kod Python 2.x na kod Python 3.x, zobacz także dokumentację Python .

Pakiet szósty zawiera narzędzia do kompatybilności z Python 2/3:

  • ujednolicony dostęp do bibliotek o zmienionych nazwach
  • zmienne dla typów łańcuchowych / Unicode
  • funkcje dla metody, która została usunięta lub której nazwa została zmieniona

Odniesienie do różnic między Python 2 i Python 3 można znaleźć tutaj .

Instrukcja drukowania a funkcja drukowania

W Pythonie 2 print jest instrukcją:

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

W Pythonie 3 print() jest funkcją z argumentami słów kluczowych do typowych zastosowań:

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

Funkcja drukowania ma następujące parametry:

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

sep jest tym, co oddziela obiekty, które przekazujesz do wydrukowania. Na przykład:

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

end jest końcem instrukcji print. Na przykład:

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

Ponowne drukowanie po wyciągu nie kończącym nowego wiersza zostanie wydrukowane w tym samym wierszu:

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

Uwaga: Dla przyszłej kompatybilności funkcja print jest również dostępna w Pythonie 2.6 i nowszych; jednak nie mogą być wykorzystywane, dopóki parsowanie do print oświadczenia jest wyłączona z

from __future__ import print_function

Ta funkcja ma dokładnie taki sam format jak Python 3, z tą różnicą, że brakuje jej parametru flush .

Uzasadnienie znajduje się w PEP 3105 .

Ciągi: Bajty kontra Unicode

Python 2.x 2.7

W Pythonie 2 istnieją dwa warianty ciągów znaków: te wykonane z bajtów typu type ( str ) i te wykonane z tekstu typu type ( unicode ).

W Pythonie 2 obiekt typu str jest zawsze sekwencją bajtów, ale jest powszechnie używany zarówno w przypadku tekstu, jak i danych binarnych.

Dosłowny ciąg znaków jest interpretowany jako ciąg bajtów.

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

Istnieją dwa wyjątki: Możesz zdefiniować literał Unicode (tekst) jawnie, poprzedzając literał u :

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

Alternatywnie możesz określić, że literały łańcuchowe całego modułu powinny tworzyć literały Unicode (tekstowe):

from __future__ import unicode_literals

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

Aby sprawdzić, czy zmienna jest ciągiem (Unicode lub ciągiem bajtów), możesz użyć:

isinstance(s, basestring)
Python 3.x 3.0

W Pythonie 3 typem str jest typ tekstowy Unicode.

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

Ponadto Python 3 dodał obiekt bytes , odpowiedni do binarnych „obiektów blob” lub zapisu do plików niezależnych od kodowania. Aby utworzyć obiekt bajtów, możesz poprzedzić literę b literałem ciągu lub wywołać metodę encode ciągu:

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

Aby sprawdzić, czy wartość jest łańcuchem, użyj:

isinstance(s, str)
Python 3.x 3.3

Możliwe jest także prefiksowanie literałów łańcuchowych za pomocą prefiksu u aby ułatwić kompatybilność między bazami kodu Python 2 i Python 3. Ponieważ w Pythonie 3 wszystkie ciągi znaków są domyślnie Unicode, poprzedzanie literału ciągów u nie ma wpływu:

u'Cafe' == 'Cafe'

Python 2 za surowy ciąg Unicode przedrostek ur nie jest obsługiwany, jednak:

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

Zauważ, że musisz encode obiekt tekstowy ( str ) Python 3, aby przekonwertować go na bytes reprezentację tego tekstu. Domyślne kodowanie tej metody to UTF-8 .

Możesz użyć decode aby zapytać obiekt bytes o reprezentowany przez niego tekst Unicode:

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

Podczas gdy typ bytes istnieje zarówno w Pythonie 2, jak i 3, typ unicode istnieje tylko w Pythonie 2. Aby użyć ukrytych ciągów Unicode w Pythonie 3 w Pythonie 2, dodaj następujący tekst na górze pliku kodu:

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

Inną ważną różnicą jest to, że indeksowanie bajtów w Pythonie 3 daje w wyniku wynik int taki:

b"abc"[0] == 97

Podczas krojenia w rozmiar jednego obiektu powstaje obiekt o długości 1 bajtu:

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

Ponadto Python 3 naprawia niektóre nietypowe zachowania w Unicode, tj. Odwracanie ciągów bajtów w Pythonie 2. Na przykład rozwiązano następujący problem :

# -*- 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

Division Integer

Standardowy symbol podziału ( / ) działa inaczej w Pythonie 3 i Pythonie 2, gdy jest stosowany do liczb całkowitych.

Podczas dzielenia liczby całkowitej przez inną liczbę całkowitą w Pythonie 3 operacja dzielenia x / y reprezentuje prawdziwy podział (używa metody __truediv__ ) i daje wynik zmiennoprzecinkowy. Tymczasem ta sama operacja w Pythonie 2 reprezentuje klasyczny podział, który zaokrągla wynik w kierunku ujemnej nieskończoności (znanej również jako zabieranie głosu ).

Na przykład:

Kod Dane wyjściowe w języku Python 2 Dane wyjściowe w języku Python 3
3 / 2 1 1.5
2 / 3 0 0,66666666666666666
-3 / 2 -2 -1,5

Zachowanie zaokrąglania do zera było przestarzałe w Pythonie 2.2 , ale pozostaje w Pythonie 2.7 ze względu na wsteczną kompatybilność i zostało usunięte w Pythonie 3.

Uwaga: Aby uzyskać wynik zmiennoprzecinkowy w Pythonie 2 (bez zaokrąglania podłogi), możemy podać jeden z operandów z kropką dziesiętną. Powyższy przykład 2/3 który daje 0 w Pythonie 2, będzie użyty jako 2 / 3.0 lub 2.0 / 3 lub 2.0/3.0 aby otrzymać 0.6666666666666666

Kod Dane wyjściowe w języku Python 2 Dane wyjściowe w języku Python 3
3.0 / 2.0 1.5 1.5
2 / 3.0 0,66666666666666666 0,66666666666666666
-3.0 / 2 -1,5 -1,5

Istnieje również operator podziału podłogi ( // ), który działa w ten sam sposób w obu wersjach: zaokrągla w dół do najbliższej liczby całkowitej. (chociaż liczba zmiennoprzecinkowa jest zwracana, gdy jest używana z __floordiv__ ) W obu wersjach operator // odwzorowuje na __floordiv__ .

Kod Dane wyjściowe w języku Python 2 Dane wyjściowe w języku 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

Można jawnie wymusić prawdziwy podział lub podział podłogi za pomocą rodzimych funkcji w module operator :

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

Jasne i jednoznaczne użycie funkcji operatora dla każdego działu może być uciążliwe. Często preferowana jest zmiana zachowania operatora / . Powszechną praktyką jest eliminowanie typowego zachowania podziału poprzez dodanie from __future__ import division jako pierwszej instrukcji w każdym module:

# needs to be the first statement in a module
from __future__ import division
Kod Dane wyjściowe w języku Python 2 Dane wyjściowe w języku Python 3
3 / 2 1.5 1.5
2 / 3 0,66666666666666666 0,66666666666666666
-3 / 2 -1,5 -1,5

from __future__ import division gwarantuje, że operator / reprezentuje prawdziwy podział i tylko w modułach zawierających import __future__ , więc nie ma istotnych powodów, aby nie włączać go we wszystkich nowych modułach.

Uwaga : Niektóre inne języki programowania używają zaokrąglania w kierunku zera (obcięcia) zamiast zaokrąglania w dół w kierunku ujemnej nieskończoności, tak jak robi to Python (tj. W tych językach -3 / 2 == -1 ). Takie zachowanie może powodować zamieszanie podczas przenoszenia lub porównywania kodu.


Uwaga na argumenty zmiennoprzecinkowe : Zamiast alternatywy from __future__ import division , można użyć zwykłego symbolu podziału / i upewnić się, że co najmniej jeden z argumentów jest zmiennoprzecinkowy: 3 / 2.0 == 1.5 . Można to jednak uznać za złą praktykę. Po prostu zbyt łatwo jest napisać average = sum(items) / len(items) i zapomnieć rzucić jeden z argumentów na zmienną wartość. Co więcej, takie przypadki mogą często unikać powiadomienia podczas testowania, np. Jeśli testujesz na tablicy zawierającej float ale otrzymujesz tablicę int w produkcji. Dodatkowo, jeśli ten sam kod jest używany w Pythonie 3, programy, które oczekują, że 3 / 2 == 1 będzie Prawdą, nie będą działać poprawnie.

Zobacz PEP 238, aby uzyskać bardziej szczegółowe uzasadnienie, dlaczego operator podziału został zmieniony w Pythonie 3 i dlaczego należy unikać podziału w starym stylu.


Więcej informacji na temat podziału można znaleźć w temacie Prosta matematyka .

Redukcja nie jest już wbudowana

W Python 2 reduce jest dostępna albo jako funkcja wbudowana, albo z pakietu functools (wersja 2.6 i nowsze), podczas gdy w Pythonie 3 reduce jest dostępna tylko z functools . Jednak składnia reduce zarówno w Python2, jak i Python3 jest taka sama i jest reduce(function_to_reduce, list_to_reduce) .

Jako przykład rozważmy zmniejszenie listy do jednej wartości przez podzielenie każdej z sąsiednich liczb. Tutaj używamy funkcji truediv z biblioteki operator .

W Pythonie 2.x jest to tak proste, jak:

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

W Pythonie 3.x przykład staje się nieco bardziej skomplikowany:

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

Możemy również użyć from functools import reduce aby uniknąć wywoływania reduce z nazwą przestrzeni nazw.

Różnice między funkcjami zakresu i Xrange

W Pythonie 2 funkcja range zwraca listę, podczas gdy xrange tworzy specjalny obiekt xrange , który jest niezmienną sekwencją, która w przeciwieństwie do innych wbudowanych typów sekwencji, nie obsługuje krojenia i nie ma metod index ani 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

W Pythonie 3 xrange został rozszerzony do sekwencji range , która w ten sposób tworzy teraz obiekt range . Nie ma typu 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

Ponadto od wersji Python 3.2 range obsługuje również krojenie, index i 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

Zaletą używania specjalnego typu sekwencji zamiast listy jest to, że interpreter nie musi przydzielać pamięci dla listy i zapełniać jej:

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)

Ponieważ to drugie zachowanie jest ogólnie pożądane, pierwsze zostało usunięte w Pythonie 3. Jeśli nadal chcesz mieć listę w Pythonie 3, możesz po prostu użyć konstruktora list() na obiekcie range :

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

Zgodność

Aby zachować zgodność między wersjami Python 2.xi Python 3.x, możesz użyć builtins modułu z zewnętrznego pakietu w future aby osiągnąć zgodność zarówno w przód, jak i wstecz :

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

range w future bibliotece obsługuje krojenie, index i count we wszystkich wersjach Pythona, podobnie jak wbudowana metoda Python 3.2+.

Rozpakowywanie Iterables

Python 3.x 3.0

W Pythonie 3 możesz rozpakować iterowalny plik, nie znając dokładnej liczby elementów, a nawet mieć zmienną, która zatrzyma jego koniec. W tym celu podajesz zmienną, która może gromadzić listę wartości. Odbywa się to poprzez umieszczenie gwiazdki przed nazwą. Na przykład rozpakowywanie 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

Uwaga: Przy użyciu *variable składni The variable zawsze będzie lista, nawet jeśli oryginalny typ nie była lista. Może zawierać zero lub więcej elementów w zależności od liczby elementów na oryginalnej liście.

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

Podobnie rozpakowywanie str :

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

Przykład rozpakowywania date ; _ jest użyty w tym przykładzie jako zmienna jednorazowa (interesuje nas tylko wartość year ):

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

Warto wspomnieć, że skoro * zjada zmienną liczbę przedmiotów, nie możesz mieć dwóch * tych samych iteracji w zadaniu - nie wiedziałoby, ile elementów trafi do pierwszego rozpakowania, a ile w drugim :

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

Do tej pory omawialiśmy rozpakowywanie zadań. * i ** zostały rozszerzone w Pythonie 3.5 . Można teraz mieć kilka operacji rozpakowywania w jednym wyrażeniu:

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

Możliwe jest również rozpakowanie iterowalnego argumentu funkcji:

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

Rozpakowanie słownika wykorzystuje dwie sąsiednie gwiazdki ** ( PEP 448 ):

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

Umożliwia to zarówno nadpisywanie starych wartości, jak i łączenie słowników.

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 usunął rozpakowywanie krotek w funkcjach. Dlatego poniższe funkcje nie działają w Pythonie 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

Szczegółowe uzasadnienie znajduje się w PEP 3113 .

Zgłaszanie wyjątków i postępowanie z nimi

Oto składnia Python 2, zwróć uwagę na przecinki , na linii raise i except linii:

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

W Pythonie 3, , składnia jest odrzucany i zastąpione przez nawias i as słowa kluczowego:

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

W celu zapewnienia kompatybilności wstecznej składnia Python 3 jest również dostępna w Python 2.6 i nowszych wersjach, dlatego należy jej używać do całego nowego kodu, który nie musi być zgodny z poprzednimi wersjami.


Python 3.x 3.0

Python 3 dodaje również łańcuchy wyjątków , w których można zasygnalizować, że przyczyną tego wyjątku był jakiś inny wyjątek. Na przykład

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

Wyjątkiem podniesione w except oświadczenia jest typu DatabaseError , ale oryginalny wyjątek jest oznaczony jako __cause__ atrybutem tego wyjątku. Gdy zostanie wyświetlone śledzenie, oryginalny wyjątek zostanie również wyświetlony w śledzeniu:

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

Jeśli wrzucisz blok except bez wyraźnego łączenia:

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

Tracenie jest

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

Żadne z nich nie jest obsługiwane w Pythonie 2.x; oryginalny wyjątek i jego śledzenie zostaną utracone, jeśli w bloku wyjątków zostanie zgłoszony inny wyjątek. Do kompatybilności można użyć następującego kodu:

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

Aby „zapomnieć” wcześniej zgłoszony wyjątek, użyj raise from None

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

Teraz ślad po prostu byłby

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

Lub w celu zapewnienia zgodności zarówno z Pythonem 2, jak i 3, możesz użyć sześciu pakietów w następujący sposób:

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

Nazwa metody .next () w iteratorach została zmieniona

W Pythonie 2 do iteratora można przechodzić przy użyciu metody o nazwie next na samym iteratorze:

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

W Pythonie 3 zmieniono nazwę metody .next na .__next__ , uznając jej rolę „magiczną”, dlatego wywołanie .next wywoła błąd AttributeError . Prawidłowym sposobem uzyskania dostępu do tej funkcji zarówno w Pythonie 2, jak i Pythonie 3 jest wywołanie next funkcji z iteratorem jako argumentem.

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

Ten kod jest przenośny w wersjach od 2.6 do aktualnych wydań.

Porównanie różnych typów

Python 2.x 2.3

Obiekty różnych typów można porównywać. Wyniki są arbitralne, ale spójne. Są one uporządkowane w taki sposób, że None jest mniejsza niż cokolwiek innego, typy numeryczne są mniejsze niż typy nienumeryczne, a wszystko inne jest uporządkowane leksykograficznie według typu. Zatem liczba int jest mniejsza niż str a tuple jest większa niż 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

Zrobiono to pierwotnie, aby można było sortować listę typów mieszanych, a obiekty grupować według typu:

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

Pojawia się wyjątek podczas porównywania różnych (nienumerycznych) typów:

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

Aby posortować listy mieszane w Pythonie 3 według typów i osiągnąć zgodność między wersjami, musisz podać klucz do posortowanej funkcji:

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

Użycie str jako funkcji key tymczasowo konwertuje każdy element na ciąg tylko dla celów porównania. Następnie widzi ciąg znaków rozpoczynający się od [ , ' , { lub 0-9 i jest w stanie posortować te (i wszystkie następujące znaki).

Wprowadzane przez użytkownika

W Pythonie 2 dane wejściowe użytkownika są akceptowane przy użyciu funkcji raw_input ,

Python 2.x 2.3
user_input = raw_input()

Podczas gdy w Pythonie 3 dane wejściowe użytkownika są akceptowane przy użyciu funkcji input .

Python 3.x 3.0
user_input = input()

W Pythonie 2, input funkcja zaakceptuje wejście i zinterpretować. Chociaż może to być przydatne, ma kilka względów bezpieczeństwa i zostało usunięte w Pythonie 3. Aby uzyskać dostęp do tej samej funkcjonalności, można użyć eval(input()) .

Aby skrypt był przenośny w obu wersjach, możesz umieścić kod poniżej w górnej części skryptu Python:

try:
    input = raw_input
except NameError:
    pass

Zmiany metody słownikowej

W Pythonie 3 wiele metod słownikowych różni się zachowaniem od Pythona 2, a wiele też zostało usuniętych: has_key , iter* i view* zniknęły. Zamiast d.has_key(key) , który był od dawna przestarzały, należy teraz użyć key in d .

W Pythonie 2 keys metod słownikowych, values i items zwracają listy. W Pythonie 3 zwracają obiekty widoku ; obiekty widoku nie są iteratorami i różnią się od nich na dwa sposoby, a mianowicie:

  • mają rozmiar (można na nich użyć funkcji len )
  • można je powtarzać wiele razy

Dodatkowo, podobnie jak w iteratorach, zmiany w słowniku są odzwierciedlane w obiektach widoku.

Python 2.7 przeportował te metody z Python 3; są dostępne jako viewkeys , wartości viewvalues i viewitems . Aby przekształcić kod Python 2 na kod Python 3, odpowiednie formularze to:

  • d.keys() , d.values() i d.items() w Pythonie 2 należy zmienić na list(d.keys()) , list(d.values()) i list(d.items())
  • d.iterkeys() , d.itervalues() i d.iteritems() należy zmienić na iter(d.keys()) lub nawet lepiej, iter(d) ; iter(d.values()) i iter(d.items()) odpowiednio
  • i wreszcie metoda Python 2.7 wywołuje d.viewkeys() , d.viewvalues() i d.viewitems() można zastąpić d.keys() , d.values() i d.items() .

Przenoszenie kodu w języku Python 2, który iteruje klucze, wartości lub elementy słownika podczas mutowania, jest czasem trudne. Rozważać:

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

Kod wygląda tak, jakby działał podobnie w Pythonie 3, ale tam metoda keys zwraca obiekt widoku, a nie listę, a jeśli słownik zmienia rozmiar podczas iteracji, kod Python 3 RuntimeError: dictionary changed size during iteration awarii z RuntimeError: dictionary changed size during iteration . Rozwiązaniem jest oczywiście prawidłowe wpisanie for key in list(d) .

Podobnie obiekty widoku zachowują się inaczej niż iteratory: nie można na nich używać funkcji next() i nie można wznowić iteracji; zamiast tego uruchomiłby się ponownie; Jeżeli kod Pythona 2 przechodzi przez wartość powrotną d.iterkeys() , d.itervalues() lub d.iteritems() sposobu wymagającej iterację zamiast iterowalny, to powinny być iter(d) , iter(d.values()) lub iter(d.items()) w Pythonie 3.

Instrukcja exec jest funkcją w Pythonie 3

W Pythonie 2 exec jest instrukcją ze specjalną składnią: exec code [in globals[, locals]]. W Python 3 exec jest teraz funkcją: exec(code, [, globals[, locals]]) , a składnia Python 2 wywoła błąd SyntaxError .

Ponieważ zmieniono print z instrukcji na funkcję, dodano również import __future__ . Nie istnieje jednak from __future__ import exec_function , ponieważ nie jest potrzebna: instrukcja exec w Pythonie 2 może być również używana ze składnią, która wygląda dokładnie tak, jak wywołanie funkcji exec w Pythonie 3. W ten sposób można zmienić instrukcje

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

do form

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

a te ostatnie formy gwarantują identyczne działanie zarówno w Pythonie 2, jak i Pythonie 3.

błąd funkcji hasattr w Pythonie 2

W Pythonie 2, gdy właściwość zgłosi błąd, hasattr zignoruje tę właściwość, zwracając wartość 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

Ten błąd został naprawiony w Python3. Więc jeśli używasz Python 2, użyj

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

lub zamiast tego użyj getattr

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

Zmieniono nazwy modułów

Zmieniono nazwę kilku modułów w bibliotece standardowej:

Stara nazwa Nowe imie
_winreg winreg
ConfigParser configparser
copy_reg copyreg
Kolejka kolejka
SocketServer serwer gniazd
_markupbase znaczniki
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

Niektóre moduły zostały nawet przekonwertowane z plików do bibliotek. Jako przykład weź tkinter i urllib z góry.

Zgodność

Zachowując zgodność między wersjami Python 2.xi 3.x, można użyć future pakietu zewnętrznego, aby umożliwić importowanie standardowych pakietów bibliotek najwyższego poziomu z nazwami Python 3.x w wersjach Python 2.x.

Stałe ósemkowe

W Python 2 literał ósemkowy można zdefiniować jako

>>> 0755  # only Python 2

Aby zapewnić zgodność krzyżową, użyj

0o755  # both Python 2 and Python 3

Wszystkie klasy są „klasami w nowym stylu” w Pythonie 3.

W Pythonie 3.x wszystkie klasy są klasami w nowym stylu ; podczas definiowania nowego klasy python domyślnie powoduje, że dziedziczy on po object . Jako takie, określenie object w definicji class jest całkowicie opcjonalne:

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

Obie te klasy zawierają teraz object w swoim mro (kolejność rozwiązywania metod):

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

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

W Python 2.x klasy są domyślnie klasami w starym stylu; nie dziedziczą domyślnie po object . Powoduje to, że semantyka klas różni się w zależności od tego, czy jawnie dodamy object jako class bazową:

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

W takim przypadku, jeśli spróbujemy wydrukować __mro__ Y , __mro__ podobne dane wyjściowe jak w przypadku Python 3.x :

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

Dzieje się tak, ponieważ podczas definiowania go jawnie dziedziczyliśmy Y po obiekcie: class Y(object): pass . W przypadku klasy X która nie dziedziczy po obiekcie, atrybut __mro__ nie istnieje, próba uzyskania do niego dostępu powoduje błąd AttributeError .

Aby zapewnić zgodność między obiema wersjami Pythona, klasy można zdefiniować z object jako klasą podstawową:

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

Alternatywnie, jeśli zmienna __metaclass__ jest ustawiona na type w zakresie globalnym, wszystkie później zdefiniowane klasy w danym module mają domyślnie nowy styl bez potrzeby jawnego dziedziczenia po object :

__metaclass__ = type

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

Usunięto operatory <> i ``, równoznaczne z! = I repr ()

W Pythonie 2 <> jest synonimem != ; podobnie, `foo` jest synonimem 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

kodowanie / dekodowanie na hex nie jest już dostępne

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'

Jednak, jak sugeruje komunikat o błędzie, możesz użyć modułu codecs , aby osiągnąć ten sam wynik:

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'

Zauważ, że codecs.encode zwraca obiekt bytes . Aby uzyskać obiekt str po prostu decode do ASCII:

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

usunięta funkcja cmp w Pythonie 3

W Pythonie 3 wbudowana funkcja cmp została usunięta wraz ze specjalną metodą __cmp__ .

Z dokumentacji:

Funkcję cmp() należy traktować jako __cmp__() , a specjalna metoda __cmp__() nie jest już obsługiwana. Użyj __lt__() do sortowania, __eq__() z __hash__() i innymi szczegółowymi porównaniami w razie potrzeby. (Jeśli naprawdę potrzebujesz funkcji cmp() , możesz użyć wyrażenia (a > b) - (a < b) jako odpowiednika cmp(a, b) .)

Ponadto wszystkie funkcje wbudowane, które przyjęły cmp parametr teraz akceptować tylko key słowa kluczowego tylko parametr.

W module functools znajduje się również przydatna funkcja cmp_to_key(func) która pozwala przekonwertować funkcję cmp styl key :

Przekształć funkcję porównania w starym stylu w funkcję kluczową. Używany z narzędziami, które akceptują kluczowe funkcje (takie jak sorted() , min() , max() , heapq.nlargest() , heapq.nsmallest() , itertools.groupby() ). Ta funkcja jest używana przede wszystkim jako narzędzie przejściowe dla programów konwertowanych z Python 2, które wspierały użycie funkcji porównawczych.

Nieszczelne zmienne w rozumieniu listy

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

Jak widać z przykładu, w Pythonie 2 wyciekła wartość x : zamaskowała ona hello world! i wydrukował U , ponieważ była to ostatnia wartość x po zakończeniu pętli.

Jednak w Pythonie 3 x drukuje pierwotnie zdefiniowany hello world! , ponieważ zmienna lokalna ze zrozumienia listy nie maskuje zmiennych z otaczającego zakresu.

Dodatkowo, ani wyrażenia generatora (dostępne w Pythonie od wersji 2.5), ani słownik, ani zestaw wyrażeń (które zostały przeniesione do Pythona 2.7 z Pythona 3) nie wyciekają zmiennych w Pythonie 2.

Zauważ, że zarówno w Pythonie 2, jak i Pythonie 3, zmienne będą przeciekać do otaczającego zakresu, gdy używa się pętli for:

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

mapa()

map() jest wbudowanym narzędziem, które jest przydatne do zastosowania funkcji do elementów iterowalnych. W Pythonie 2 map zwraca listę. W Pythonie 3 map zwraca obiekt mapy , który jest generatorem.

# 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']

W Pythonie 2 możesz przekazać None aby służył jako funkcja tożsamości. To już nie działa w Pythonie 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

Ponadto, przy przejściu więcej niż jeden iterable jako argument w Pythonie 2, map tarcze krótsze iterables z None (podobny do itertools.izip_longest ). W Pythonie 3 iteracja zatrzymuje się po najkrótszej iteracji.

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

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

Uwaga : zamiast map rozważ użycie list, które są zgodne z Python 2/3. Zamiana map(str, [1, 2, 3, 4, 5]) :

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

filter (), map () i zip () zwracają iteratory zamiast sekwencji

Python 2.x 2.7

W filter Python 2 wbudowane funkcje map i zip zwracają sekwencję. map i zip zawsze zwracają listę, podczas gdy z filter typ zwrotu zależy od typu danego parametru:

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

W filter Python 3 iterator map i zip zwraca zamiast tego:

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

Ponieważ Python 2 itertools.izip jest odpowiednikiem Python 3 zip izip został usunięty z Python 3.

Import bezwzględny / względny

W Pythonie 3 PEP 404 zmienia sposób importowania z Pythona 2. Implikowany import względny nie jest już dozwolony w pakietach, a from ... import * jest dozwolony tylko w kodzie poziomu modułu.

Aby osiągnąć zachowanie Python 3 w Python 2:

  • funkcję importu bezwzględnego można włączyć za pomocą opcji from __future__ import absolute_import
  • zachęca się do wyraźnego względnego importu zamiast domyślnego importu względnego

Dla wyjaśnienia, w Pythonie 2 moduł może importować zawartość innego modułu znajdującego się w tym samym katalogu w następujący sposób:

import foo

Zauważ, że lokalizacja foo jest niejednoznaczna na podstawie samej instrukcji importu. Ten rodzaj niejawnego importu względnego jest zatem odradzany na rzecz jawnego importu względnego , który wygląda następująco:

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

Kropka . pozwala na jednoznaczne zadeklarowanie lokalizacji modułu w drzewie katalogów.


Więcej na temat importu względnego

Zastanów się nad pakietem zdefiniowanym przez użytkownika o nazwie shapes . Struktura katalogów jest następująca:

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

circle.py , square.py i triangle.py wszystkie importują util.py jako moduł. Jak będą odnosić się do modułu na tym samym poziomie?

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

LUB

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

The . służy do importu względnego na tym samym poziomie.

Teraz rozważ alternatywny układ modułu shapes :

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

Jak te 3 klasy będą odnosić się do util.py?

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

LUB

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

.. służy do importu względnego na poziomie nadrzędnym. Dodaj więcej . s z liczbą poziomów między rodzicem a dzieckiem.

Plik I / O

file nie jest już wbudowaną nazwą w wersji 3.x ( open nadal działa).

Wewnętrzne szczegóły pliku I / O zostały przeniesione do standardowego modułu biblioteki io , który jest także nowym domem 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'

Tryb pliku (tekst kontra plik binarny) określa teraz typ danych generowanych przez odczyt pliku (i typ wymagany do zapisu):

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

Domyślnie kodowanie plików tekstowych jest zwracane przez locale.getpreferredencoding(False) . Aby jawnie określić kodowanie, użyj parametru słowa kluczowego encoding :

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

Funkcja round () przerywa remis i zwraca typ

remis w rundzie ()

W Pythonie 2 użycie round() na liczbie równej dwóm liczbom całkowitym zwróci wartość najdalszą od 0. Na przykład:

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

Jednak w Pythonie 3 round() zwróci parzystą liczbę całkowitą (aka zaokrąglenia bankowców ). Na przykład:

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

Funkcja round () jest zgodna ze strategią zaokrąglania od połowy do parzystości, która zaokrągla liczby w połowie do najbliższej parzystej liczby całkowitej (na przykład, round(2.5) zwraca teraz 2 zamiast 3,0).

Zgodnie z odniesieniem w Wikipedii , jest to również znane jako zaokrąglanie bezstronne, zaokrąglanie zbieżne, zaokrąglanie statystyki , holenderskie, zaokrąglanie Gaussa lub zaokrąglanie nieparzyste .

Zaokrąglanie od połowy do nawet jest częścią standardu IEEE 754, a także jest domyślnym trybem zaokrąglania w Microsoft .NET.

Ta strategia zaokrąglania ma tendencję do zmniejszania całkowitego błędu zaokrąglania. Ponieważ średnio liczba zaokrąglonych w górę jest równa liczbie zaokrąglonych w dół, błędy zaokrąglania są anulowane. Inne metody zaokrąglania mają tendencję do odchylenia w górę lub w dół w średnim błędzie.


typ zwrotu round ()

Funkcja round() zwraca typ float w Pythonie 2.7

Python 2.x 2.7
round(4.8)
# 5.0

Począwszy od Pythona 3.0, jeśli drugi argument (ilość cyfr) jest pominięty, zwraca int .

Python 3.x 3.0
round(4.8)
# 5

Prawda, fałsz i brak

W Python 2 True , False i None są wbudowanymi stałymi. Co oznacza, że można je ponownie przypisać.

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

Nie można tego zrobić z None od wersji Python 2.4.

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

W Pythonie 3 True , False i None są teraz słowami kluczowymi.

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

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

Zwraca wartość podczas zapisu do obiektu pliku

W Pythonie 2 pisanie bezpośrednio do uchwytu pliku zwraca None :

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

W Pythonie 3 pisanie do uchwytu zwróci liczbę znaków zapisanych podczas pisania tekstu oraz liczbę bajtów zapisanych podczas pisania bajtów:

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

W Pythonie 2 każda liczba całkowita większa niż C ssize_t byłaby konwertowana na long typ danych, oznaczony sufiksem L na literale. Na przykład w 32-bitowej wersji Pythona:

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

Jednak w Pythonie 3 long typ danych został usunięty; bez względu na to, jak duży jest liczbą całkowitą, to będzie int .

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

Klasa Wartość logiczna

Python 2.x 2.7

W Pythonie 2, jeśli chcesz samodzielnie zdefiniować wartość logiczną klasy, musisz zaimplementować metodę __nonzero__ w swojej klasie. Wartość domyślna to 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

W Pythonie 3 zamiast __bool__ jest używane __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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow