koddla

Yazılımcıları bilgi ile güçlendirir.

Python’da bir değişkenin işlev olup olmadığını nasıl algılarım?

Bir değişkenim var ve bunun bir işleve işaret edip etmediğini bilmek istiyorum.

Akla gelen ilk yöntem isinstance kullanmak. Şöyle bir şey yapabileceğimizi düşünebiliriz:

>>> isinstance(x, function)

Ama bu kodd parçası aşağıdaki hatayı verir:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'function' is not defined

Peki bu değişkenin bir fonksiyon olduğunu nasıl anlayabiliriz?

Eğer Python 2.x veya Python 3.2+ ile çalışıyorsak callable()'i kullanabiliriz. Bu yöntem kullanım dışı bırakılmıştı, ancak şimdi tekrar kullanımda. Bu yüzden biz de tekrar kullanabiliriz. Bununla ilgili tartışmayı buradan okuyabilirsiniz: http://bugs.python.org/issue10518.

Şu şekilde yapıyoruz:

callable(obj)

Bu Python 3.x içinse, ancak 3.2’den önceyse, nesnenin bir __call__ özniteliği olup olmadığını kontrol edebiliriz.

hasattr(obj, '__call__')

Genellikle önerilen types.FunctionTypes veya inspect.isfunction yaklaşımları (aslında her ikisi de aynı şeyi yapar) bir dizi uyarıyla birlikte gelir. Mesela, Python’da olmayan işlevler için False döndürürler. Örneğin, yerleşik işlevlerin çoğu Python’da değil C’de oluşturulur, bu nedenle bunlar da False dönerler:

>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True

bu yüzden şaşırtıcı sonuçlar verebilirler.


callable() üzerinde biraz daha duralım.

Görünüşe göre, Python 3.2’de geri dönen callable()‘in yerini başka bir yöntem tutmuyor: callable(), test edilen nesnenin tp_call özelliğini kontrol eder. Bunun düz bir Python eşleniği yoktur. Önerilen testlerin çoğu çoğu zaman doğrudur:

>>> class Spam(object):
...     def __call__(self):
...         return 'OK'
>>> can_o_spam = Spam()


>>> can_o_spam()
'OK'
>>> callable(can_o_spam)
True
>>> hasattr(can_o_spam, '__call__')
True
>>> import collections
>>> isinstance(can_o_spam, collections.Callable)
True

Sınıfı biraz değiştirelim, önce __call__‘ı silelim. Sonra, biraz heyecan kaktalım ve örneğe bir sahte __call__ ekleyelim.

>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'

Bu ddurumda bunun gerçekten çağrılabilir olmadığına dikkat edin:

>>> can_o_spam()
Traceback (most recent call last):
  ...
TypeError: 'Spam' object is not callable

Şimdi callable ve hasattr yaklaşımlarını inceleyelim. callable() ile test edersek olması gereken sonucu alırız:

>>> callable(can_o_spam)
False

Ama hasattr yanlış sonuç verir:

>>> hasattr(can_o_spam, '__call__')
True

Peki isinstance()? Bu da yanlış sonuç verir:

>>> isinstance(can_o_spam, collections.Callable)
True

Sonuç? callable() en doğru sonucu verecektir.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Back to top