Interpreter Python – Podstawy Których Możesz Nie Znać

Kiedy stawiamy pierwsze kroki z językiem Python, najczęstszym wyborem obok użycia IDE typu Pycharm jest użycie interpretera Python. Wiedza jak go używać jest bardzo przydatna, gdy chcemy sprawdzić zachowanie prostego kodu czy też biblioteki. Dodatkowo przydaje się także podczas debugowania z pomocą pdb oraz pracy z Django shell. Jednak zanim przejdziemy do zaawansowanych opcji używania go, zacznijmy od podstaw.

Uruchomienie interpretera

Aby uruchomić interpreter Pythona, należy w terminalu wpisać python dla interpretera Pythona w wersji <3.0, bądź python3 dla interpretera python w wersji >=3.0.1

~> python3
Python 3.9.0a4 (default, Mar  4 2020, 19:52:38) 
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Poprzez użycie komendy python3 w terminalu zostanie uruchomiony interpreter Pythona, w moim przypadku z Pythonem w wersji 3.9.0a4. Według informacji podanych na ekranie możemy wpisać help, aby otrzymać więcej informacji. Sprawdźmy to!

>>> help
Type help() for interactive help, or help(object) for help about object.

A więc help można uruchomić w trybie interaktywnym, albo przekazując jako argument konkretny obiekt. W ramach dzisiejszej zabawy przyda nam się wiedza o tym, czym jest i jak działa funkcja dir. Więc użyjmy funkcji help, aby podejrzeć dokumentacje:

>>> help(dir)
Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.

Funkcja dir

Według dokumentacji funkcji dir możemy jej użyć na dwa sposoby. Wywołanie jej bezargumentowo pokaże nam przestrzeń nazw dostępną w naszym aktualnym zakresie lokalnym. Co jest zatem dostępne?

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Mamy tutaj kilka interesujących rzeczy, niestety większość z nich jest na ten moment pusta. No może poza dwiema zmiennymi, które nas mogą zainteresować. Pierwsza z nich to __name__, a co pod nią znajdziemy?

__name__

>>> __name__
'__main__'

Pod zmienną __name__ znajduje się wartość '__main__'. Dzieje się tak, gdy jesteśmy w głównym pliku, który został wywołany, bądź, tak jak w tym przypadku, uruchomiliśmy interpreter Pythona. Właśnie tę właściwość wykorzystujemy w naszym kodzie, gdy chcemy uruchomić pewne metody tylko przy bezpośrednim uruchomieniu pliku, ale nie koniecznie chcemy, aby te metody zostały wykonane, gdy będziemy importować pewne elementy z tego pliku.

W takich sytuacjach właśnie korzystamy z if __name__ == "__main__". Dla przykładu możemy w ten sposób uruchamiać plik z testem bezpośrednio poprzez uruchomienie pliku z rozszerzeniem *.py, a także bez problemu uruchomimy taki plik poprzez pytest.

if __name__ == "__main__":
    unittest.main()

To był __name__, a co jeszcze ciekawego możemy tu znaleźć? Czym jest __builtins__?

__builtins__

>>> __builtins__
<module 'builtins' (built-in)>

Jak widzimy powyżej, jest to moduł. Co on zawiera? Poznaliśmy funkcje dir i użyliśmy jej bez argumentu. Co się zatem wydarzy, gdy jako argument przekażemy do niej nasz moduł __builtin__?

>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

To, co widać, to przestrzeń nazw dostępna w tym module. Jeśli przyjrzymy się dokładniej, to zauważymy pewne metody, z których zdarzyło nam się już korzystać, pisząc kod. Mamy całą listę wyjątków. Metody magiczne (magic methods, dunder methods), które widzieliśmy już wcześniej. Są także funkcje, a wśród nich jedne z bardziej znanych jak len czy str. Jest to moduł ze wszystkimi globalnymi funkcjami które mamy dostępne podczas pisania kodu i bez importowania czegokolwiek.

Interpreter Python daje nam wiele możliwości odkrywania nowych bibliotek czy szybkiego testowania funkcjonalności samego Pythona. Następnym razem zobaczymy, do czego ta wiedza może nam się przydać!