Funkcja może być potraktowana jak obiekt o zbiorze jakiś właściwości. Weźmy sobie funkcję:
def fun(a,b=1,c='defc'):
"""DOCSTRING"""
print '{0} {1} {2}'.format(a,b,c)
O bebechach samej definicji funkcji może nam dużo powiedzieć już samo:
dir(fun)
func_doc
Zwróci nam dokumentację funkcji # 'DOCSTRING'
func_name
To nic innego jak nazwa funkcji # 'fun'
func_defaults
Krotka podające wartości domyślne funkcji # (1, 'defc')
func_code
Zwróci nam obiekt reprezentujący ciało funkcji. Możemy spróbować go wykonać używając metody exec. Oczywiście próba zakończy się niepowodzeniem ponieważ nie przekazaliśmy do kodu argumentów.
Obiekt ten jest o tyle ciekawy iż sam posiada kilka własności, które mogą pomóc nam dalej diagnozować funkcję. Na przykład:
func_code.co_argcount
Poinformuje nas o tyle ile funkcja przyjmuje parametrów
func_code.co_filename
Powie w jakim pliku została zdefiniowana funkcja
func_code.nlocals
Ilość lokalny zmiennych (łącznie z argumentami)
func_code.co_varnames
Krotka z nazwami lokalnych zmiennych (rozpoczyna się od argumentów funkcji)
Bardzo ciekawą własnością jest func_code.co_flags. Sprawdzając czy zostały dla niej ustawione konkretne bity możemy szybko dowiedzieć się kilku interesujących rzeczy.
Jeżeli w co_flags został ustawiony bit 0x04 Funkcja posługuje się parametrem *arguments. Bit 0x08 oznacza iż nasze obiekt posługuje się **kwarguments zaś 0x20 gdy funkcja jest generatorem.
Pierwszym sposobem, aby sprawdzić czy funkcja posiada, którąś z tych właściwości jest wykonanie ilorazu bitowego z poszukiwaną wartością. Tak np. jeżeli
fun.func_code.co_flags & 0x04
wyjdzie 0 oznacza iż nasza funkcja nie korzysta z *args, jeżeli otrzymamy 0x04 - korzysta.
Więcej szczegółów:
http://docs.python.org/reference/datamodel.html#index-1940
http://docs.python.org/reference/datamodel.html#index-1965
No comments:
Post a Comment