Type wbudowane

https://docs.python.org/3/library/index.html

WPROWADZENIE

Z dokumentacji Pythona: podstawowe typy wbudowane to typy liczbowe, sekwencje, mapowania, pliki, klasy, instancje i wyjątki.

Python posiada szeroki zakres podstawowych typów liczbowych: liczby całkowite (dowolnych rozmiarów), liczby zmiennoprzecinkowe, liczby zespolone. Są stringi (łańcuchy napisowe). Python jest wyposażony w kilka typów kolekcji: listy, krotki (tuples), słowniki, zbiory. Listy, krotki i napisy są sekwencjami i mają wiele wspólnych metod.

Typy danych możemy jeszcze podzielić na mutowalne (zmienne) i niemutowalne (niezmienne). Niezmienne są przede wszystkim liczby, stringi i krotki.

Warto korzystać z wbudowanych typów danych z wielu powodów:

Przegląd obiektów wbudowanych Pythona:

+-----------------+--------------------+----------------------+
| Typ obiektu     | Kategoria          | Czy podlega zmianom? |
+-----------------+--------------------+----------------------+
| Liczby          | Liczbowa           | Nie                  |
| range           | Sekwencja liczbowa | Nie (Py2 != Py3)     |
| Łańcuchy (str)  | Sekwencja tekstowa | Nie (Py2 != Py3)     |
| bytes           | Sekwencja bajtów   | Nie                  |
| bytearray       | Sekwencja bajtów   | Tak                  |
| Listy (list)    | Sekwencja          | Tak                  |
| Krotki (tuple)  | Sekwencja          | Nie                  |
| Słowniki (dict) | Odwzorowanie       | Tak                  |
| Pliki           | Rozszerzenie       | Nie dotyczy          |
| set             | Zbiór              | Tak                  |
| frozenset       | Zbiór              | Nie                  |
+-----------------+--------------------+----------------------+

Aby sprawdzić, czy obiekt jest danego typu, czy instancją klasy, korzystamy z wbudowanej funkcji isinstance(). Generalnie nie powinno się sprawdzać jawnie typu, ponieważ niszczymy wtedy elastyczność kodu. W Pythonie koduje się pod kątem interfejsów obiektów (obsługowanych operacji), a nie typów. Mamy tu związek z koncepcją polimorfizmu [polimorfizm = znaczenie operacji uzależnione jest od typu obiektów, na których się te operację wykonuje. Jest to przydatna właściwość Pythona. Przykładowo operator + działa inaczej na liczbach, a inaczej na stringach.].


# Składnia:
# isinstance(object, class-or-type-or-tuple) -> bool

if isinstance(x, float):
    print("to jest liczba zmiennoprzecinkowa")

if isinstance(x, (int, long)):   # Py2 (Py3 nie ma typu long)
    print("to jest liczba całkowita")

if isinstance(S, (set, frozenset)):
    print("to jest zbiór")

# Dawny, odradzany sposób.
# Funkcja type() zwraca obiekt typu - są różnice między Py2 i Py3.
if type(x) is type(1) or type(x) is type(1.0):
    print("to jest liczba")

if type(x) is int or type(x) is float:
    print("to jest liczba")

# Moduł types zawiera nazwy dla innych typów.
import types
dir(types)

Wbudowane stałe Pythona: False, True, None, NotImplemented, Ellipsis.

HASH

https://en.wikipedia.org/wiki/Hash_function

https://www.pythonforthelab.com/blog/what-are-hashable-objects/

Obok podziału obiektów na zmienne i niezmienne, istnieje podział na obiekty hashowalne (ang. hashable objects) i niehashowalne. Hashowanie to zasadniczo obliczanie pewnej liczby na bazie obiektu, przy czym ta liczba nie zmienia się przez cały czas życia obiektu. Wykorzystuje się je w tablicach hashowalnych, a w Pythonie przy słownikach i zbiorach (klucze w słowniku i elementy zbioru muszą być obiektami hashowalnymi).

Zauważmy, że wbudowane typy niezmienne (immutable) w Pythonie są zawsze hashowalne. Hash zależy od danych przechowywanych przez obiekt, a nie od tożsamości obiektu, tożsamość jest sprawdzana przez funkcję id(). Kiedy dwa obiekty mają ten sam hash, wtedy mogą, ale nie muszą być równe, bo może wystąpić kolizja. Kolizja jest zjawiskiem typowym, Python wtedy porównuje obiekty bezpośrednio (a == b).

Obiekty tworzone przez klasy zdefiniowane przez użytkownika są z definicji hashowalne, przy czym hash jest obliczany na bazie id().


>>> a = "abc"
>>> hash(a)   # metoda __hash__
1453079729188098211
>>> b = (1, 3, 5)
>>> hash(b)
2528501712789647984
>>> c = [1, 2]
>>> hash(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
# Dla liczb int zachodzi hash(i) = i.
>>> d = 2528501712789647984
>>> hash(d) == hash(b)   # kolizja
True
>>>

SŁOWA ZAREZERWOWANE PYTHONA

https://docs.python.org/3/library/keyword.html

Słowa kluczowe nie mogą być użyte jako nazwy zmiennych.


>>> help()     # pomoc w trybie interaktywnym
help> keywords            # wypisanie słów kluczowych
...
help> quit
>>>

import keyword   # Py3

keyword.kwlist   # lista wszystkich słów kluczowych
keyword.iskeyword("True")   # True
keyword.iskeyword("self")   # False
keyword.iskeyword("max")   # False

Słowa kluczowe Pythona: False (3.9), None (3.9), True (3.9), and, as (2.6+), assert, async (3.9), await (3.9), break (3.9), case (3.10), class, continue, def, del, elif, else, except, exec (2.x), finally, for, from, global, if, import, in, is, lambda, match (3.10), nonlocal (3.x), not, or, pass, print (2.x), raise, return, try, type (3.12), while, with (2.6+), yield (2.3+).

Inne słowa, których lepiej nie używać: NotImplemented, Ellipsis.

Z dokumentacji na temat Ellipsis: Special value used in conjunction with extended slicing syntax. It is used to indicate the presence of the ... syntax in a slice. Używane z modułami doctest, numpy. The ellipsis is used to slice higher-dimensional data structures (numpy). Ellipsis jest używane jako singleton tam, gdzie None jest niejednoznaczne.


# http://stackoverflow.com/questions/118370/
# how-do-you-use-the-ellipsis-slicing-syntax-in-python

# http://stackoverflow.com/questions/17160162/what-is-in-python-2-7
# What is [...] in Python 2.7?

# http://stackoverflow.com/questions/3993125/what-does-mean-in-numpy-code
# What does ... mean in numpy code?

>>> p = [1, 2]
>>> p[1:1] = [p]   # zapętlenie
>>> p              # Python używa ... do pokazania zapętlenia
[1, [...], 2]               # (nieskończona rekurencja)

>>> L = [0]
>>> L[0] = L       # zapętlenie
>>> L
[[...]]
>>> D = {}
>>> D[...] = 'a'
>>> D
{Ellipsis: 'a'}

Słowa zarezerwowane nie mogą być wykorzystane jako nazwy zmiennych, nazwy modułów, itp.