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.
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 |
Ç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.
>>> 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
>>> 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 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.
>>> 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
>>> 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 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.
>>> 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'>
>>> 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.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.7.9
Zamanlama range()
192.091515064
Zamanlama xrange()
121.89577198
Python 3.4.2
Zamanlama range()
189.21216359100072
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
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)
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
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__'
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
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.
from platform import python_version print 'Python', python_version() raise IOError, "file error"
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
from platform import python_version print('Python', python_version()) raise IOError, "file error"
Python 3.4.2
File "<ipython-input-3-25f049caebb0>", line 1
raise IOError, "file error"
^
SyntaxError: invalid syntax
from platform import python_version print('Python', python_version()) raise IOError("file error")
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 3 versiyonunda istisna işlemlerinde ufak değişiklikler oldu. Bu değişiklik python 3 versiyonunda 'as' kullanımı zorunluluğu eklenmiştir.
from platform import python_version print 'Python', python_version() try: test_pythontr except NameError, err: print err, '--> Hata mesajimiz
Python 2.7.9
name 'test_pythontr' is not defined --> Hata mesajimiz
from platform import python_version print('Python', python_version()) try: test_pythontr except NameError as err: print(err, '--> Hata mesajimiz')
name 'test_pythontr' is not defined --> Hata mesajimiz
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.
from platform import python_version print 'Python', python_version() my_generator = (letter for letter in 'abcdefg') next(my_generator) my_generator.next()
Python 2.7.9
'a'
'b'
from platform import python_version my_generator = (letter for letter in 'abcdefg') next(my_generator)
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'
İ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 sözdizimi biçimini desteklemiyor. Onun yerine şeklinde kullanmalısınız. Aradaki farklılıklara dikkat edin.
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
once: i = 1
anlama:
sonra: i = 4
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)
once: i = 1
anlama:
sonra: i = 1
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)
Python 2.7.9
> 'foo' = False
(1, 2) > 'foo' = True
> (1, 2) = False
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()
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.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.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'>
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.
from platform import python_version print 'Python', python_version() print range(3) print type(range(3))
Python 2.7.9
<type 'list'>
from platform import python_version print('Python', python_version()) print(range(3)) print(type(range(3))) print(list(range(3))) print(type(str(3)))
Python 3.4.2
range(0, 3)
<class 'range'>
<class 'str'>
Python 3'te listeleri artık iade etmeyen daha sık kullanılan fonksiyonlar ve methodlar:
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)
Python 2.7.9
16.0
17.0
from platform import python_version print('Python', python_version()) round(15.5) round(16.5)
Python 2 ve 3 ile ilgili olarak okumanızı tavsiye ettiğimiz diğer makaleler.
Yorumlar