Diyelimki aşağıdaki gibi bir değişkenimiz var:
one = 1
Bu değişkenin veri tipini bilmek isteriz.
Elbette, Python’daki her şeyde olduğu gibi, bunu yapmanın doğru ve yanlış yolları var. Doğru yola bakalım:
type
ile veri tipi sorgulama
>>> type(one)
<type 'int'>
Döndürülen cevabı kullanarak veri tipinin ismini öğrenelim. Bunun için nesnenin __name__
özelliğini kullanabiliriz. (Bu özellik objenin ismini öğrenebileceğimiz bir kaç dunder özeliğinden biri. Çift alt çizgili özellikler dunder olarak anılır – double under : dunder. )
>>> type(one).__name__
'int'
__class__
özelliğini kullanmayın
Python’da, alt çizgi ile başlayan özellikler semantik olarak genel API içerisinde yer almaz. Dolayısıyla bu özellikleri kullanmaktan kaçınmak yararlı olacaktır. (Tabiki mutlaka gerekli olduğu durumlar hariç.)
type
fonksiyonu bize nesnenin sınıfını verdiğine göre, bu bilgiyi direkt bir şekilde almaktan kaçınırız:
>>> one.__class__
Kod yazarken genellikle bir nesnenin tipini öğrenmek istediğimizde aklımıza ilk gelen yol budur. Ne de olsa nesnenin hangi sınıfa ait olduğunu öğrenmek istiyoruz değil mi – bu sebeple type aklımıza gelmez. Örneğin, aşağıdakini yaparız:
class Foo(object):
def foo(self):
self.__class__
Bunu yapmayın. Bunun yerine, type(self)
kullanın:
class Foo(object):
def foo(self):
type(self)
type()’ın bir diğer kullanım yeri – metaclass
type()’tan bahsediyorsak type’ın bir diğer özelliği olan metaclass’lardan da kısaca bahsetmemiz gerekir.
Metaclass’lar sınıf oluşturan şeylerdir. Bir nesne oluşturmak için sınıf tanımlamamız gerekir. Python’da her şey sınıf olduğuna göre, her şeyi oluşturacak bir “şey”‘e ihtiyaç vardır. İşte burda metaclass devreye girer.
Peki bunların type() ile ilgisi ne? type birden fazla argüman ile kullanıldığında metaclass görevi görür. Yani bir sınıf oluşturur. Yani; type, Python’da arkaplanda diğer sınıfları oluşturmak için kullanılır.
type
ile şunu yaparız:
MyClass = type('MyClass', (), {})
Bu bilgiyi aklımızda tutarak tekrar konumuza dönelim. Python’da nesne türünü nasıl belirleriz?
Python’da aslında bir nesnenin türünü öğrenmek için iki fonksiyon bulunur. Birincisi olan type()
ile bir nesnenin tam olarak tipini belirleriz. İkincisi olan isinstance()
ile ise bu nesnenin türünü bir şeye karşı kontrol ederiz. Genellikle, bu sebeple, isinstance()
kullanmak isteriz. Çünkü isinstance hem dadha hızlıdır hem de tür mirasını destekler.
Haliyle, bir nesnenin türünü elde etmek için type()
fonksiyonunu kullanmalıyız. type()’a bir nesneyi tek parametre olarak verdiğimizde o nesnenin türünü alırız:
>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
Bu fonksiyon tabiki yerleşik olmayan türler için de kullanılır:
>>> class Test1 (object):
pass
>>> class Test2 (Test1):
pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True
type()
bu objenin türünü belirlese de, miras hakkında bir şey söylemez:
>>> type(b) is Test1
False
Bu durumun üstesinden gelmek için isinstance
kullanırız. Tabiki isinstance da hem yerleşik türler için hem de yerleşik olmayan türler için çalışır:
>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True
isinstance()
genellikle miras açısından tercih edilen yöntemdir. Yani sadece nesnenin tipini öğrenmek istemediğimiz zamanlarda – ne sebeple olursa olsun – type()
yerine isinstance()
kullanmayı tercih ederiz.
isinstance()
‘a vereceğimiz ikinci parametre aynı zamanda bir demet olalbilir. Bu şekilde nesnemizi birden fazla türü için kontrol edebiliriz. isinstance
demetteki türlerden birisi ile karşılık bulursa true döndürür:
>>> isinstance([], (tuple, list, set))
True
Sonuç
Öncelikle, __class__
kullanmayın. Bunun yerine type
kullanın. Eğer nesnenin türünü karşılaştırmak için kullanacaksanız veya miras önemli ise isinstance()
tercih edin.