Podgląd zmiennych w Pythonie - globals, locals, vars i dir
Czytanie kodu dużych programów to niezwykle wymagające zadanie - nawet proste rzeczy mogą przyprawić o zawrót głowy. Na przykład:
- Jak szybko wyszukać wszystkie nazwy zmiennych i wartości w danym skrypcie?
- Jak sprawdzić wszystkie nazwy zmiennych i wartości w dużej funkcji lub klasie?
- Jak odnaleźć listę obecnych atrybutów danego obiektu?
Możemy oczywiście szukać linijka po linijce, ucząc się nazw na pamięć lub spisywać je na kartce papieru. To jednak bardzo niepythonowe.
Ciężej jest czytać kod, niż go napisać - Joel Spolsky, autor bloga programistycznego Joel on Software
Aby ułatwić sobie życie, możemy wykorzystać 4 funkcje Pythona, który posłużą nam do wyświetlania nazw zmiennych oraz wartości z jakiegoś zakresu. Nauczycie się tutaj jak z nich korzystać, a po czymś takim przeglądanie kodu będzie czystą przyjemnością.
Funkcja 1: globals()
Jak sama nazwa wskazuje, globals()
pokaże nam informacje dotyczące zakresu globalnego. Jeśli otworzymy konsolę i wpiszemy globals()
, to zwrócony zostanie dict
zawierający wszystkie nazwy i wartości zmiennych w zakresie globalnym.
>>> globals()
{'__name__': '__main__', '__doc__': None, ...}
(Niektóre dane wyjściowe w tym artykule zostały uproszczone przy pomocy … aby łatwiej się je czytało)
Jeśli dodamy jedną zmienną:
>>> Master = "Yang"
>>> globals
{'__name__': '__main__', '__doc__': None, ... ,'Master': 'Yang'}
Ponieważ funkcja globals()
zwraca nam dict
, to możemy nim manipulować w celu wydobycia tych dane, które nas interesują:
>>> [n for n in globals() if not n.startswith('__')]
['sys', 'Master']
Jak widać w powyższym przykładzie, użyliśmy wyrażenia listowego do wydobycia wszystkich nazw zmiennych i to bez dwóch najbardziej prawdopodobnych wyników.
Funkcja 2: locals()
Funkcja locals()
to bułka z masłem, o ile dobrze znamy globals()
. Jak sama nazwa wskazuje, zwraca ona dict zawierający wszystkie nazwy lokalne oraz wartości.
def top_developer():
name = "Yang"
country = "UK"
print(locals())
top_developer()
# {'name': 'Yang', 'country': 'UK'}
Tak swoją drogą, to jeśli wywołamy locals()
w zakresie globalnym, to rezultat będzie taki sam, jak w przypadku wywołania globals()
.
>>> globals() is locals()
True
Funkcja 3: vars()
Funkcja vars()
zwróci __dict__
, czyli słownik wykorzystywany do przechowywania atrybutów obiektu. Jej rezultat byłby taki sam, gdybyśmy wywołali __dict__
w sposób bezpośredni.
class TopDeveloper:
def __init__(self):
self.name = "Yang"
self.country = "UK"
me = TopDeveloper()
print(vars(me))
# {'name': 'Yang', 'country': 'UK'}
print(vars(me) is me.__dict__)
# True
Przykład użycia funkcji vars()
Nie każdy obiekt będzie posiadał __dict__
, a więc metody vars()
możemy używać tylko w niektórych częściach obiektów.
year = 2020
vars(year)
# Traceback (most recent call last):
# File "<input>", line 1, in <module>
# TypeError: vars() argument must have __dict__ attribute
Jak widać w powyższym przykładzie, typ obiektu int nie posiada __dict__
, a więc użycie w nim vars()
wyrzuci TypeError
.
Funkcja 4: dir()
Funkcja dir()
pomaga nam pokazać listę nazw w ekwiwalentnym zasięgu.
class TopDeveloper:
def __init__(self):
self.name = "Yang"
self.country = "UK"
me = TopDeveloper()
print(dir(me))
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'country', 'name']
Tak naprawdę to dir wywołuje __dir__()
w sposób wewnętrzny.
class TopDeveloper:
def __init__(self):
self.name = "Yang"
self.country = "UK"
def __dir__(self):
return [1, 2, 3]
me = TopDeveloper()
print(dir(me))
# [1, 2, 3]
Jak widać powyżej, jeśli zmienimy sposób działania __dir__
, to rezultat dir()
również się zmieni.
Podsumowanie
Te 4 funkcje przydają się do wyświetlania nazw i wartości. Używa się ich w Pythonie, aby szybciej zobaczyć, co jest zdefiniowane w skryptach, obiektach itd. podczas przeglądania kodu danego programu.
Oryginał tekstu w języku angielskim możesz przeczytać tutaj.