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
Özellik | Isteğe bağlı olarak | Zorunlu olarak | Efekt |
nested_scopes | 2.1.0b1 | 2.2 | PEP 227: Statically Nested Scopes |
generators | 2.2.0a1 | 2.3 | PEP 255: Simple Generators |
division | 2.2.0a2 | 3.0 | PEP 238: Changing the Division Operator |
absolute_import | 2.5.0a1 | 3.0 | PEP 328: Imports: Multi-Line and Absolute/Relative |
with_statement | 2.5.0a1 | 2.6 | PEP 343: The “with” Statement |
print_function | 2.6.0a2 | 3.0 | PEP 3105: Make print a function |
unicode_literals | 2.6.0a2 | 3.0 | PEP 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ü?