Pythontr

husonet | Tarih: 25.01.2017

Python 2 ve 3 arasındaki farklar

Python 2.7 ve Python 3.x arasındaki temel farklar örneklerle birlikte.

Birçok kullanıcı Python programlama diline başlarken hangi sürümle başlaması gerektiğini merak eder. Esasen yapılması gereken versiyonları göz ardı ederek okumaktan hoşlandığınız sitelerin dökümantasyonlarını takip edebilir ve sonradan aradaki farkları tespit edebilirsiniz.


Fakat yeni bir projeye başlıyorsanız ve versiyon seçme şansınız varsa Python 2 yada Python 3 için kullanmayı planladığınız kütüphaneleri desteklediği sürece doğru ya da yanlış diyemeyiz. Bununla birlikte, bu versiyonlardan biri için kod yazıyorsanız ve ileriki süreçte diğer versiyona aktarmak isterseniz Python'ın bu en popüler iki versiyonu arasındaki temel farklılıklara göz atmanız faydalı olacaktır.


from __future__ import division

Yazdığınız kod için ileride Python 3 versiyonunu hedefliyorsanız Python 2 versiyonunda uyumlu olmayan bazı anahtar kelime ve özellikleri kullanmamıza olanak sağlayan __future__ paketlerini import etmeniz önerilir. Örneğin, Python 2.x'te Python 3.x'in tamsayı bölme işlem davranışını istiyorsanız aşağıdaki örnek gibi yapabilirsiniz.


>>> print 8/7
1
>>> from __future__ import division
>>> print 8/7
1.14285714286

ÖzellikIsteğe bağlı olarakZorunlu olarakEfekt
nested_scopes2.1.0b12.2PEP 227: Statically Nested Scopes
generators2.2.0a12.3PEP 255: Simple Generators
division2.2.0a23.0PEP 238: Changing the Division Operator
absolute_import2.5.0a13.0PEP 328: Imports: Multi-Line and Absolute/Relative
with_statement2.5.0a12.6PEP 343: The “with” Statement
print_function2.6.0a23.0PEP 3105: Make print a function
unicode_literals2.6.0a23.0PEP 3112: Bytes literals in Python 3000

Python 2 ve 3 arasında print fonksiyonu farklılıkları


Çok fazla önemi olmayan ve en çok bilinen bir değişikliktir ancak yine de belirtmek gerekir. Python 2'nin print fonskiyon bildirimi print() fonksiyonu aslında değişiklik python3 versiyonunda parantez kullanımıdır.


Python 2'de ek parantezler ile ilgili bir hata oluşmaz, aksine, yazdırma işlevi Python'u parantezler olmadan 2 yönlü olarak kullanımını destekler, Python 3'te bir SyntaxError hatası verir.


Python 2
>>> from platform import python_version
>>> print 'Python', python_version()
>>> print 'Merhaba Dunya'
Merhaba Dunya
>>> print ('Merhaba Dunya')
Merhaba Dunya
>>> print "text", ; print 'Aynı satıra daha fazla metin yazdır'
text Aynı satıra daha fazla metin yazdır

Python 3
>>> from platform import python_version
>>> print('Python', python_version())
Python 3.4.2
>>> print('Merhaba Dunya')
Merhaba Dunya
>>> print("text,", end="")
text,>>> print('Aynı satıra daha fazla metin yazdır') # .py dosyasında yazılınca direkt çıktılar birleşik olacaktır.
Aynı satıra daha fazla metin yazdır

Python 3 versiyonunda print fonksiyonu ve SyntaxError hatası gösterimi


>>> print 'Merhaba Dunya!'
File "<stdin>", line 1
print 'Merhaba Dunya!'
^
SyntaxError: Missing parentheses in call to 'print'

Not: Python 2 vasıtasıyla yukarıdaki "Merhaba, Dünya" yazısı oldukça normal görünür. Bununla birlikte, print için parantezlerin içinde birden fazla öğe varsa, Python 2'de "deyime" dönüşür.


>>> from platform import python_version
>>> print 'Python', python_version()
Python 2.7.9
>>> print('a', 'b')
('a', 'b')
>>> print 'a', 'b'
a b

Python 2 ve 3 arasında tamsayı bölme farklılıkları


Python 2 versiyonunda Python 3 kodunu çalıştırırsanız tamsayı bölme işleminde bir tehlike oluşturursunuz. Bu tehlike farkedilmeyebilir. Python 2 versiyonunda yapılan bölme işlemlerini anlaşılabilir olması için aşağıdaki örnekler incelenebilir.


Python 2
>>> from platform import python_version
>>> print 'Python', python_version()
Python 2.7.9
>>> print '3 / 2 =', 3 / 2
3 / 2 = 1
>>> print '3 // 2 =', 3 // 2
3 // 2 = 1
>>> print '3 / 2.0 =', 3 / 2.0
3 / 2.0 = 1.5
>>> print '3 // 2.0 =', 3 // 2.0
3 // 2.0 = 1.0

Python 3
>>> from platform import python_version
>>> print('Python', python_version())
Python 3.4.2
>>> print('3 / 2 =', 3 / 2)
3 / 2 = 1.5
>>> print('3 // 2 =', 3 // 2)
3 // 2 = 1
>>> print('3 / 2.0 =', 3 / 2.0)
3 / 2.0 = 1.5
>>> print('3 // 2.0 =', 3 // 2.0)
3 // 2.0 = 1.0

Python 2 ve 3 arasında Unicode farklılıkları


Python 2 de ASCII str() turleri ayrıca unicode turleri vardır. Ancak bayt tipi yoktur.


Python 3'te sonunda Unicode (utf-8) dizeleri ve 2 bayt sınıfları eklenmiştir; byte ve bytearrays.


Python 2
>>> from platform import python_version
>>> print 'Python', python_version()
Python 2.7.9
>>> print type(unicode('Bu bir python3 str turu gibidir'))
<type 'unicode'>
>>> print type(b'byte turu yok')
<type 'str'>
>>> print 'onlar gercekten' + b' ayni'
onlar gercekten ayni
>>> print type(bytearray(b'bytearray garip olsada var'))
<type 'bytearray'>

Python 3
>>> from platform import python_version
>>> print('Dizeler şimdi utf-8 \u03BCnico\u0394é!')
Dizeler şimdi utf-8 μnicoΔé!
>>> print('Python', python_version(), end="")
>>> print(' veri', type(b' depolamak icin byte'))
Python 3.4.2 veri <class 'bytes'>

print('ve Python', python_version(), end="")
print(' ve de', type(bytearray(b'bytearrays')))
ve Python 3.4.2 ve de <class 'bytearray'>

'note that we cannot add a string' + b'bytes for data'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bytes' object to str implicitly

Python 2 ve 3 arasındaki xrange kullanımı farklılıkları


Python 2.x'te iterable nesneler için xrange() fonksiyonun kullanımı popülerdir, örneğin for-loop veya list ya da set-dictionary-comprehension işlemleri.


Tembel değerlendirme "lazy-evaluation" sayesinde, üzerinde yalnızca bir kez yinelemeniz gerekiyorsa (örneğin, bir for döngüsü içinde). range() fonksiyondan avantajı , xrange() fonksiyonun daha hızlı olmasıdır. Bununla birlikte, yinelemeyi defalarca tekrar ederseniz, nesiller her seferinde sıfırdan tekrarlandığından önerilmez.


Python 3'te range() fonksiyonu xrange() fonksiyonuna dönüştürüldü. xrange() fonksiyonu artık mevcut değildir. (xrange() fonksiyonu, Python 3'te bir NameError oluşturuyor).


import timeit
from platform import python_version

n = 100000
def test_range(n):
for i in range(n):
pass

def test_xrange(n):
for i in xrange(n):
pass

print ('Python', python_version())
print ('Zamanlama range()')
print (timeit.timeit("test_range(n)", setup="from __main__ import test_range;n=10000"))
print ('Zamanlama xrange()')
print (timeit.timeit("test_xrange(n)", setup="from __main__ import test_xrange;n=10000"))

Python 2 Sonuçlar

Python 2.7.9
Zamanlama range()
192.091515064
Zamanlama xrange()
121.89577198


Python 3 Sonuçlar

Python 3.4.2
Zamanlama range()
189.21216359100072


Python 3 xrange() fonksiyonu NameError hatası döndürür


Zamanlama xrange()
Traceback (most recent call last):
File "test.py", line 17, in <module>
print (timeit.timeit("test_xrange(n)", setup="from __main__ import test_xrange;n=10000"))
File "/usr/lib/python3.4/timeit.py", line 213, in timeit
return Timer(stmt, setup, timer).timeit(number)
File "/usr/lib/python3.4/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
File "test.py", line 10, in test_xrange
for i in xrange(n):
NameError: name 'xrange' is not defined


Python 3'teki range nesneleri için __contains__ methodu

Bahsedilmesi gereken bir konuda Python 3'teki __contains__ methodları. Bu methodlar tamsayılar ve Boolean türleri için Python 3.x range fonksiyonun "look-up" larını önemli ölçüde hızlandırabilir.


from platform import python_version
x = 10000000
def val_in_range(x, val):
return val in range(x)
def val_in_xrange(x, val):
return val in xrange(x)
print('Python', python_version())
assert(val_in_range(x, x/2) == True)
assert(val_in_range(x, x//2) == True)
%timeit val_in_range(x, x/2)
%timeit val_in_range(x, x//2)

Sonuçlar

Python 3.4.2
1 loops, best of 3: 429 ms per loop
1000000 loops, best of 3: 444 ns per loop


Sonuçlara baktığımızda tamsayı bölme işleminin ondalıklı sayıya bölme işleminden yaklaşık 60.000 kadar daha hızlı olduğu gözükmektedir. Bununla birlikte, Python 2.x'in range veya xrange'sında bir __contains__ methodu bulunmadığından, "look-up speed" tamsayılar veya float'lar için o kadar fark olmayacaktır:


print 'Python', python_version()
assert(val_in_xrange(x, x/2.0) == True)
assert(val_in_xrange(x, x/2) == True)
assert(val_in_range(x, x/2) == True)
assert(val_in_range(x, x//2) == True)
%timeit val_in_xrange(x, x/2.0)
%timeit val_in_xrange(x, x/2)
%timeit val_in_range(x, x/2.0)
%timeit val_in_range(x, x/2)

Python 2.7.7
1 loops, best of 3: 256 ms per loop
10 loops, best of 3: 57.6 ms per loop
1 loops, best of 3: 307 ms per loop
1 loops, best of 3: 232 ms per loop


__contain__ methodu henüz Python 2.x'e eklenmemiştir.
print('Python', python_version())
range.__contains__

Python 2.7.7



---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)

<ipython-input-7-05327350dafb> in <module>()
1 print 'Python', python_version()
----> 2 range.__contains__


AttributeError: 'builtin_function_or_method' object has no attribute '__contains__'


Python 2 ve 3'teki hız farkları hakkında not edin


Bazı test sonuçların Python 3'ün range() ile Python2'nin xrange() arasındaki hız farkları gözlenebilir. Genellikle aynı hız beklenir. Bununla birlikte, burada fark yalnızca Python 3'ün genelde Python 2'den daha yavaş çalışmaya eğilimli olmasından kaynaklanıyor.


def test_while():
i = 0
while i < 20000:
i += 1
return
print('Python', python_version())
%timeit test_while()

Python 3.4.1
100 loops, best of 3: 2.68 ms per loop


print 'Python', python_version()
%timeit test_while()

Python 2.7.6
1000 loops, best of 3: 1.72 ms per loop


İstisna Fırlatma


Python 2, 'eski' ve 'yeni' sözdizimlerini kabul ettiğinde, istisna argümanını parantez içine almıyorsak, Python 3 bir SyntaxError oluşturur.


Python 2
from platform import python_version
print 'Python', python_version()
raise IOError, "file error"

Sonuçlar

Python 2.7.9
---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-3-25f049caebb0> in <module>()
----> 1 raise IOError, "file error"

IOError: file error


Python 2 versiyonunda esasen ileriye dönük uyumluluk için parantez içinde de istisna gönderebiliriz.


raise IOError("file error")

---------------------------------------------------------------------------
IOError Traceback (most recent call last)
<ipython-input-5-6f1c43f525b2> in <module>()
----> 1 raise IOError("file error")

IOError: file error


Python 3
from platform import python_version
print('Python', python_version())
raise IOError, "file error"

Sonuçlar

Python 3.4.2
File "<ipython-input-3-25f049caebb0>", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax


Python 3'te bir istisna oluşturmak için doğru yol:


from platform import python_version
print('Python', python_version())
raise IOError("file error")

Sonuçlar

Python 3.4.2
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-6-6f1c43f525b2> in <module>()
----> 1 raise IOError("file error")

OSError: file error


Python İstisna 'Exception' Yönetimleri


Python 3 versiyonunda istisna işlemlerinde ufak değişiklikler oldu. Bu değişiklik python 3 versiyonunda 'as' kullanımı zorunluluğu eklenmiştir.


Python 2 İstisna Yönetimi
from platform import python_version
print 'Python', python_version()
try:
test_pythontr
except NameError, err:
print err, '--> Hata mesajimiz

Sonuç


Python 2.7.9
name 'test_pythontr' is not defined --> Hata mesajimiz


Python 3 İstisna Yönetimi
from platform import python_version
print('Python', python_version())
try:
test_pythontr
except NameError as err:
print(err, '--> Hata mesajimiz')

Sonuç

name 'test_pythontr' is not defined --> Hata mesajimiz


Python next() fonksiyonu ve next() methodu


Python next() fonksiyonu yaygın olarak kullanılan fonksiyon ve methodlardan biridir. Python 2 versiyonlarında her iki şekilde de kullanılabilir fakat Python 3 versiyonlarında sadece method olarak kullanılır.


Pyhton 2
from platform import python_version
print 'Python', python_version()
my_generator = (letter for letter in 'abcdefg')
next(my_generator)
my_generator.next()

Sonuçlar

Python 2.7.9
'a'
'b'


Python 3
from platform import python_version
my_generator = (letter for letter in 'abcdefg')
next(my_generator)

Sonuçlar

Python 3.4.2
'a'


Python 3 aşağıdaki işleme izin vermez.


my_generator.next()

---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-125f388bb61b> in <module>()
----> 1 my_generator.next()

AttributeError: 'generator' object has no attribute 'next'


Döngüsel değişkenler ve genel ad alanı sızıntısı 'namespace leak'


İyi haber: Python 3.x'de for-loop değişkenleri artık genel ad alanına sızmazlar!


Bu, Python 3.x'te yapılan ve Python 3.0'da Yenilikler adlı bölümde açıklanan değişikliğe gider:


Liste anlama kavramları, artık [... for var in item1, item2, ...] sözdizimi biçimini desteklemiyor. Onun yerine [... for var in (item1, item2, ...)] şeklinde kullanmalısınız. Aradaki farklılıklara dikkat edin.


Python 2
from platform import python_version
print 'Python', python_version()
i = 1
print 'once: i =', i
print 'anlama: ', [i for i in range(5)]
print 'sonra: i =', i

Sonuçlar

once: i = 1
anlama: [0, 1, 2, 3, 4]
sonra: i = 4


Python 3
from platform import python_version
print('Python', python_version())
i = 1
print('once: i =', i)
print('anlama:', [i for i in range(5)])
print('sonra: i =', i)

Sonuçlar

once: i = 1
anlama: [0, 1, 2, 3, 4]
sonra: i = 1


Karşılaştırma yapılamaz türleri karşılaştırma


Python 3'teki bir diğer güzel değişiklik, karşılaştırma yapılamaz türleri karşılaştırmaya çalışırsak, bir TypeError uyarısı olarak ortaya çıkmasıdır.


from platform import python_version
print 'Python', python_version()
print "[1, 2] > 'foo' = ", [1, 2] > 'foo'
print "(1, 2) > 'foo' = ", (1, 2) > 'foo'
print "[1, 2] > (1, 2) = ", [1, 2] > (1, 2)

Sonuçlar

Python 2.7.9
[1, 2] > 'foo' = False
(1, 2) > 'foo' = True
[1, 2] > (1, 2) = False


Python 3
from platform import python_version
print('Python', python_version())
print("[1, 2] > 'foo' = ", [1, 2] > 'foo')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-d9318fcf3f58> in <module>()
----> 1 print("[1, 2] > 'foo' = ", [1, 2] > 'foo')

TypeError: unorderable types: list() > str()
print("(1, 2) > 'foo' = ", (1, 2) > 'foo')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-19130f56ae47> in <module>()
----> 1 print("(1, 2) > 'foo' = ", (1, 2) > 'foo')

TypeError: unorderable types: tuple() > str()
print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-1c8c3a110b67> in <module>()
----> 1 print("[1, 2] > (1, 2) = ", [1, 2] > (1, 2))

TypeError: unorderable types: list() > tuple()

Kullanıcı girdilerini input() aracılığıyla ayrıştırma


Python input() fonksiyonu Python 3'te düzenlendi, böylece kullanıcı girişlerini daima str nesneleri olarak tanımlar. Python 2'de tehlikeli davranışlardan kaçınmak ve giriş yapılan değerleri sadece string olarak tanımlamak için raw_input() fonksiyonunu kullanmamız gerekir.


Python 2
Python 2.7.9 (default, Jun 29 2016, 13:08:31) ....
>>> my_input = input('Bir sayi gir: ')
Bir sayi gir: 231
>>> type(my_input)
<type 'int'>
>>> my_input = raw_input('Bir sayi gir: ')
Bir sayi gir: 231
>>> type(my_input)
<type 'str'>

Python 3
Python 3.4.2 (default, Oct  8 2014, 10:45:20) ....
Type "help", "copyright", "credits" or "license" for more information.
>>> my_input = input('Bir sayi gir: ')
Bir sayi gir: 231
>>> type(my_input)
<class 'str'>

Listeler yerine tekrarlanabilir nesneler döndürme


Daha önce xrange bölümünde gördüğümüz gibi, bazı fonksiyonlar ve methodlar, iterasyon nesnelerini Python 3'te - Python 2'deki listeler yerine döndürür.


Bununla birlikte yalnız bir kez tekrarladığımız zaman bellekten tasarruf ederiz. Fakat ihtiyaç duyduğumuzda birden fazla yenilemek mümkündür fakat yenilemeler verimli olmaz.


Gerçekten liste objelerine ihtiyaç duyulduğu durumlar için iterable nesnesini list() fonksiyonuyla birlikte basit bir şekilde listeye dönüştürebiliriz.


Python 2
from platform import python_version
print 'Python', python_version()
print range(3)
print type(range(3))

Sonuçlar

Python 2.7.9
[0, 1, 2]
<type 'list'>


Python 3
from platform import python_version
print('Python', python_version())
print(range(3))
print(type(range(3)))
print(list(range(3)))
print(type(str(3)))

Sonuçlar

Python 3.4.2
range(0, 3)
<class 'range'>
[0, 1, 2]
<class 'str'>


Python 3'te listeleri artık iade etmeyen daha sık kullanılan fonksiyonlar ve methodlar:


  • zip()
  • map()
  • filter()
  • dictionary’s .keys() method
  • dictionary’s .values() method
  • dictionary’s .items() method

Python Yuvarlama İşlemleri


Python 3, ondalık sayıları yuvarlamak için biçim olarak şu andaki standart yolu benimser. Fakat Python 3'te ondalıklar sonraki yada önceki çift numaraya yuvarlanır. Kod taşınabilirliği için bir sıkıntı olmamasına rağmen, sözde yuvarlanmaya kıyasla daha iyi bir yoldur, çünkü büyük sayılara yönelik önyargıları önler. Örnek 17.5 = 18'e 16.5 = 16'a dönüşümü vb..


from platform import python_version
print 'Python', python_version()
round(15.5)
round(16.5)

Sonuçlar

Python 2.7.9
16.0
17.0


Python 3
from platform import python_version
print('Python', python_version())
round(15.5)
round(16.5)

Python 2 ve Python 3 hakkında daha fazla makale


Python 2 ve 3 ile ilgili olarak okumanızı tavsiye ettiğimiz diğer makaleler.


Python 2'mi Python 3'mü?