Python type() Fonksiyonu Açıklaması
Python’daki type() fonksiyonu, aslında iki işlevi birden yerine getirir:
- Bir nesnenin tam olarak hangi sınıfa ait olduğunu öğrenmek,
- Çalışma zamanında (runtime) dinamik olarak yeni sınıflar oluşturmak.
Bu yazıda type() fonksiyonunun söz dizimini (syntax), hazır ve özel sınıflarla kullanım örneklerini, dinamik sınıf oluşturmadaki rolünü ve isinstance() ile arasındaki farkları göreceğiz.
Fonksiyon oldukça basit bir yapıya sahiptir. Lafı uzatmadan hemen söz dizimine bakalım.
Python type() Fonksiyonunun Söz Dizimi
Python’da birçok yerleşik (built-in) fonksiyon vardır. Bunlardan biri olan type(), bir nesnenin türünü öğrenmek için kullanılır.
Söz dizimi şu şekildedir:
type(object)
type(name, bases, dict)
Tek argüman verildiğinde type() fonksiyonu, nesnenin tipini döndürür. Bu değer aslında nesnenin __class__ özniteliğiyle aynıdır.
Üç argüman verildiğinde ise yeni bir tip (class) döndürür. Yani çalışma anında (runtime) dinamik bir sınıf oluşturabilirsin.
- "isim" (name) → Oluşturulacak sınıfın adı olur. Bu, sınıfın
__name__özniteliğine denk gelir. - "tabanlar" (bases) → Sınıfın miras alacağı sınıfları belirtir. Bu da sınıfın
__bases__özniteliğine karşılık gelir. - "sözlük" (dict) → Sınıfın gövdesini (metod ve özelliklerini) tanımlar. Bu da sınıfın
__dict__özniteliğiyle aynıdır.
Kısacası:
- 1 argüman → Tip öğrenme (
object.__class__) - 3 argüman → Dinamik sınıf oluşturma (
__name__,__bases__,__dict__)
Bu farkı bilmek, hem günlük tip kontrollerinde hem de daha ileri seviye dinamik programlamada işine çok yarar. 🐍
Python type() Fonksiyonu Örnekleri
Şimdi type() fonksiyonunun kullanımına dair bazı örneklere bakalım.
1. Bir Python nesnesinin tipini bulmak
x = 10
print(type(x))
# <class 'int'>
s = 'abc'
print(type(s))
# <class 'str'>
from collections import OrderedDict
od = OrderedDict()
print(type(od))
# <class 'collections.OrderedDict'>
class Veri:
pass
d = Veri()
print(type(d))
# <class '__main__.Veri'>
Output
<class 'int'>
<class 'str'>
<class 'collections.OrderedDict'>
<class 'main.Veri'>
Dikkat edersen, type() fonksiyonu nesnenin tipini modül adıyla birlikte döndürüyor.
Bizim yazdığımız Python dosyası herhangi bir ayrı modül değil, doğrudan çalıştırılan bir script olduğu için modül adı otomatik olarak __main__ oluyor.
Yani özel sınıflar tanımladığında, çıktı içinde __main__.<SınıfAdı> ifadesini görmen normaldir.
2. Python Sınıflarından Detayları Çıkarmak
Diyelim ki elimizde birkaç sınıf var. Bu sınıflardan bazı meta verileri alabiliriz. Bunun için sınıfların şu öznitelikleri işimize yarar:
__class__→ Nesnenin ait olduğu sınıf__bases__→ Sınıfın miras aldığı taban sınıflar__dict__→ Sınıfın sahip olduğu metotlar ve özellikler__doc__→ Sınıfın dökümantasyon (docstring) metni
Bu öznitelikler sayesinde sınıfın yapısını daha yakından inceleyebiliriz.
class Veri:
"""Veri Sınıfı"""
v_id = 10
class AltVeri(Veri):
"""AltVeri Sınıfı"""
av_id = 20
Haydi bu sınıfların bazı özelliklerini ekrana yazdıralım.
print(Veri.__class__)
# <class 'type'>
print(Veri.__bases__)
# (<class 'object'>,)
print(Veri.__dict__)
# {'__module__': '__main__', 'v_id': 10, '__doc__': 'Veri Sınıfı', ...}
print(Veri.__doc__)
# Veri Sınıfı
print(AltVeri.__class__)
# <class 'type'>
print(AltVeri.__bases__)
# (<class '__main__.Veri'>,)
print(AltVeri.__dict__)
# {'__module__': '__main__', 'av_id': 20, '__doc__': 'AltVeri Sınıfı', ...}
print(AltVeri.__doc__)
# AltVeri Sınıfı
Output:
<class 'type'>
(<class 'object'>,)
{'module': 'main', 'doc': 'Veri Sınıfı', 'v_id': 10, 'dict': <attribute 'dict' of 'Veri' objects>, 'weakref': <attribute 'weakref' of 'Veri' objects>}
Veri Sınıfı
<class 'type'>
(<class 'main.Veri'>,)
{'module': 'main', 'doc': 'AltVeri Sınıfı', 'av_id': 20}
AltVeri Sınıfı
Benzer sınıfları type() fonksiyonunu kullanarak da oluşturabiliriz.
Veri1 = type("Veri1", (object,), {"__doc__": "Veri1 Sınıfı", "v_id": 10})
AltVeri1 = type("AltVeri1", (Veri1,), {"__doc__": "AltVeri1 Sınıfı", "av_id": 20})
print(Veri1.__class__)
# <class 'type'>
print(Veri1.__bases__)
# (<class 'object'>,)
print(Veri1.__dict__)
# {'__module__': '__main__', '__doc__': 'Veri1 Sınıfı', 'v_id': 10, ...}
print(Veri1.__doc__)
# Veri1 Sınıfı
print(AltVeri1.__class__)
# <class 'type'>
print(AltVeri1.__bases__)
# (<class '__main__.Veri1'>,)
print(AltVeri1.__dict__)
# {'__module__': '__main__', '__doc__': 'AltVeri1 Sınıfı', 'av_id': 20, ...}
print(AltVeri1.__doc__)
# AltVeri1 Sınıfı
Output:
<class 'type'>
(<class 'object'>,)
{'doc': 'Veri1 Sınıfı', 'v_id': 10, 'module': 'main', 'dict': <attribute 'dict' of 'Veri1' objects>, 'weakref': <attribute 'weakref' of 'Veri1' objects>}
Veri1 Sınıfı
<class 'type'>
(<class 'main.Veri1'>,)
{'doc': 'AltVeri1 Sınıfı', 'av_id': 20, 'module': 'main'}
AltVeri1 Sınıfı
Unutma, type() fonksiyonunu kullanarak oluşturduğumuz dinamik sınıflara fonksiyonlar (metotlar) da ekleyebiliriz.
type() Fonksiyonunun Gerçek Hayattaki Kullanımı
Python dinamik tipli (dynamically-typed) bir dil olduğu için, bir değişkenin tipini öğrenmek istediğinde type() fonksiyonunu kullanabilirsin.
Eğer bir fonksiyonunun sadece belirli tiplerde çalışmasını istiyorsan, bunun için isinstance() fonksiyonu daha doğru tercih olur.
Mesela, iki tam sayı üzerinde işlem yapan bir fonksiyon yazmak istediğimizi düşünelim. Bunu şu şekilde uygulayabiliriz:
def hesapla(x, y, op='topla'):
if not(isinstance(x, int) and isinstance(y, int)):
print(f'Hatalı Argüman Tipi - x:{type(x)}, y:{type(y)}')
raise TypeError('Uygun olmayan tip, sadece tam sayı (int) olmalı')
if op == 'fark':
return x - y
if op == 'carp':
return x * y
# varsayılan işlem toplama
return x + y
isinstance() fonksiyonu, girilen argümanların tipini doğrulamak için kullanılır.
Eğer tip kontrolü başarısız olursa, bu durumda type() fonksiyonu ile parametrelerin hangi tipte olduğunu ekrana yazdırabiliriz.
Yani özetle:
- isinstance() → Doğrulama için
- type() → Hata anında tipi göstermek için
Değişken Tiplerini Doğru Kontrol Etmek
type() bir nesnenin tam tipini öğrenmende faydalı olsa da, koşullu kontrollerde her zaman en iyi seçenek değildir. Özellikle de kalıtım (inheritance) işin içine girdiğinde.
-
type(obj) == SomeClass
Bu kontrol,objtam olarakSomeClasssınıfından türemişse True döner.
Eğerobj,SomeClass’ın bir alt sınıfından (subclass) geliyorsa False döner. -
isinstance(obj, SomeClass)
Bu kontrol iseobj’nin hemSomeClasssınıfından hem de onun alt sınıflarından biri olup olmadığını kontrol eder.
Yani daha esnek bir yöntemdir ve polimorfizm mantığıyla daha uyumludur.
Kısacası:
- Kesin sınıf kontrolü →
type() - Esnek ve kalıtım dostu kontrol →
isinstance()
type() vs isinstance() İçin En İyi Kullanım Önerileri
-
Fonksiyonlarda / Metotlarda Tip Doğrulama
Belirli bir tip veya onun alt sınıflarını kabul etmek istiyorsanisinstance()kullan. Bu yaklaşım fonksiyonlarını daha esnek ve dayanıklı hale getirir. -
Kesin Tip Tanımlama
Bir nesnenin tam olarak hangi sınıfa ait olduğunu öğrenmek ve temel sınıf ile alt sınıfları ayırt etmek istiyorsantype()kullan.
Bu genelde günlük uygulamalarda çok sık gerekmez ama framework geliştirirken veya çok özel senaryolarda işine yarayabilir. -
Hata Ayıklama ve Loglama
Bir nesnenin türünü anlamak için ekrana bastırman gerekiyorsatype()gayet idealdir. Debug sırasında ya da log tutarken hızlıca nesnenin doğasını anlamana yardımcı olur.
Sonuç
Python’daki type() fonksiyonu, nesnelerin tam yapısını anlamak ve dinamik sınıf oluşturma gibi ileri seviye senaryolarda oldukça önemli bir araçtır.
- Tek argümanlı hali → Nesnenin tam sınıfını öğrenmek, hata ayıklama ve içgörü (introspection) için çok faydalıdır.
- Üç argümanlı hali → Dinamik sınıf oluşturma sayesinde güçlü metaprogramlama imkânları sunar.
Ancak uygulama mantığında tip kontrolü yaparken, özellikle kalıtım (inheritance) söz konusu olduğunda, geliştiricilerin daha çok isinstance() kullanması önerilir. Bu sayede kod hem daha esnek hem de polimorfizme uygun hale gelir.
Daha fazla Python konusu için şu yazımıza da göz atabilirsin: