Arasındaki farklar isinstance()
ve type()
Python?
İle tip kontrolü
isinstance(obj, Base)
alt sınıfların ve birden fazla olası tabanın kullanılmasına izin verir:
isinstance(obj, (Base1, Base2))
oysa tip kontrolü
type(obj) is Base
yalnızca başvurulan türü destekler.
Bir sidenote olarak, is
muhtemelen daha uygun
type(obj) == Base
çünkü sınıflar tek tektir.
Tip kontrolünden kaçının - Polimorfizm kullanın (ördek yazma)
Python'da genellikle argümanlarınız için herhangi bir türe izin vermek, beklendiği gibi davranmak ve nesne beklendiği gibi davranmazsa uygun bir hata oluşturur. Bu, ördek tipleme olarak da bilinen polimorfizm olarak bilinir.
def function_of_duck(duck):
duck.quack()
duck.swim()
Yukarıdaki kod işe yarıyorsa, argümanımızın bir ördek olduğunu varsayabiliriz. Böylece başka şeylerde geçebiliriz gerçek alt ördek türleri:
function_of_duck(mallard)
ya da ördek gibi çalışır:
function_of_duck(object_that_quacks_and_swims_like_a_duck)
ve kodumuz hala çalışıyor.
Ancak, açıkça yazım denetiminin yapılmasının istendiği bazı durumlar vardır. Belki de farklı nesne türleriyle ilgili mantıklı şeyleriniz vardır. Örneğin, Pandalar Dataframe nesnesi diktelerden veya kayıtlardan oluşturulabilir. Böyle bir durumda, kodunuzun düzgün bir şekilde işleyebilmesi için ne tür bir argüman aldığını bilmesi gerekir.
Yani, soruyu cevaplamak için:
Arasındaki farklar isinstance()
ve type()
Python?
Farkı göstermeme izin ver:
type
İşleviniz belirli bir argüman alırsa (yapıcılar için ortak bir kullanım örneği) belirli bir davranış sağlamanız gerektiğini varsayalım. Böyle bir türü kontrol ederseniz:
def foo(data):
'''accepts a dict to construct something, string support in future'''
if type(data) is not dict:
# we're only going to test for dicts for now
raise ValueError('only dicts are supported for now')
Eğer bir alt sınıf olan bir diksiyon geçmeye çalışırsak dict
(yapabileceğimiz gibi, kodumuzun Liskov İkame ilkesini izlemesini bekliyorsak , bu alt tipler türler için ikame edilebilir) kod kopuyor !:
from collections import OrderedDict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
hata veriyor!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
ValueError: argument must be a dict
isinstance
Ancak kullanırsak isinstance
, Liskov İkame'yi destekleyebiliriz !:
def foo(a_dict):
if not isinstance(a_dict, dict):
raise ValueError('argument must be a dict')
return a_dict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
İadeler OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
Soyut Temel Sınıflar
Aslında daha iyisini yapabiliriz. collections
çeşitli türler için minimum protokolleri uygulayan Soyut Temel Sınıflar sağlar. Bizim durumumuzda, sadece Mapping
protokolü beklersek, aşağıdakileri yapabiliriz ve kodumuz daha da esnek hale gelir:
from collections import Mapping
def foo(a_dict):
if not isinstance(a_dict, Mapping):
raise ValueError('argument must be a dict')
return a_dict
Yoruma verilen yanıt:
Türün birden fazla sınıfa karşı kontrol etmek için kullanılabileceği belirtilmelidir. type(obj) in (A, B, C)
Evet, türlerin eşitliğini test edebilirsiniz, ancak yukarıdakiler yerine, özellikle yalnızca bu türlere izin vermedikçe, kontrol akışı için çoklu tabanları kullanın:
isinstance(obj, (A, B, C))
Fark yine, isinstance
Liskov ikamesi olarak bilinen bir özellik olan programı bozmadan ebeveyn için ikame edilebilen alt sınıfları desteklemesidir.
Daha da iyisi, bağımlılıklarınızı ters çevirin ve belirli türleri kontrol etmeyin.
Sonuç
Bu nedenle, alt sınıfların değiştirilmesini desteklemek istediğimizden, çoğu durumda, bir örneğin kesin sınıfını gerçekten bilmeniz gerekmediği sürece type
, tür denetiminden kaçınmak ve tür denetimini tercih etmek isinstance
istiyoruz.
str
veunicode
(sadece kontrol edebileceğiniz yerlerdebasestring
), birden fazla türe karşı kontrol etmek için bir demet kullanabilirsiniz. Olmadığını kontrol etmek içinsomething
ISint
veyastr
kullanımisinstance(something, (int, str))
.