Masz listę produktów, tekst z formularza albo słownik z danymi i chcesz szybko sprawdzić, ile zawiera elementów. Najczęściej wywołujesz len(obiekt), które zwraca liczbę elementów, choć wynik zależy od tego, co Python uznaje za element i jaki typ danych przekazujesz.
[search_image]funkcja len w Pythonie przykład kodu lista napis słownik[/search_image]
Jedno wywołanie, kilka różnych znaczeń długości
len()zwraca liczbę elementów sekwencji albo kolekcji.- Dla słownika otrzymasz liczbę kluczy, a dla tekstu liczbę znaków rozumianych jako punkty kodowe Unicode.
- Generator nie ma ustalonej długości, więc
len(generator)kończy się błędem. - Do sprawdzania, czy kolekcja jest pusta, czytelniejszy zapis to
if not kolekcja. - Własna klasa może współpracować z
len(), jeśli zdefiniujesz w niej metodę__len__().
len() zwraca liczbę elementów, a nie rozmiar obiektu
Najprostszy przykład wygląda tak:
imiona = ["Ola", "Jan", "Marek"]
liczba_imion = len(imiona)
print(liczba_imion) # 3
Funkcja nie analizuje zawartości każdego elementu. Dla listy liczy pozycje, dla krotki elementy, dla zbioru wartości, a dla słownika klucze. Oficjalna dokumentacja wbudowanej funkcji len wymienia między innymi napisy, bajty, krotki, listy, zakresy, słowniki i zbiory jako obiekty obsługujące takie wywołanie.
| Obiekt | Kod | Wynik | Co jest liczone |
|---|---|---|---|
| Lista | len([10, 20, 30]) |
3 | Elementy listy |
| Krotka | len(("a", "b")) |
2 | Elementy krotki |
| Słownik | len({"id": 7, "aktywny": True}) |
2 | Klucze |
| Zbiór | len({2, 2, 4, 6}) |
3 | Unikalne elementy |
| Zakres | len(range(5, 15)) |
10 | Wartości generowane przez zakres |
Najczęstsza pomyłka pojawia się przy strukturach zagnieżdżonych. Dla danych poniżej wynik wynosi 2, ponieważ lista zawiera dwa wiersze, chociaż w środku znajduje się łącznie pięć liczb:
wiersze = [[1, 2], [3, 4, 5]]
print(len(wiersze)) # 2
print(len(wiersze[0])) # 2
print(len(wiersze[1])) # 3
Jeżeli potrzebujesz liczby wszystkich wartości wewnątrz wierszy, pytanie brzmi już inaczej. Wtedy trzeba przejść po zagnieżdżonych kolekcjach, bo samo len(wiersze) opisuje wyłącznie zewnętrzną listę.
Przy tekście len() liczy punkty kodowe, nie bajty UTF-8
Tekst potrafi wyglądać jak jeden znak, a w pamięci lub podczas wysyłania przez sieć zajmować kilka bajtów. W Pythonie str jest sekwencją punktów kodowych Unicode, natomiast bytes przechowuje wartości bajtowe. To dwa różne poziomy danych.
tekst = "ą"
dane = tekst.encode("utf-8")
print(len(tekst)) # 1
print(len(dane)) # 2
Wynik 1 oznacza jeden punkt kodowy w obiekcie tekstowym. Wynik 2 oznacza dwa bajty po zakodowaniu znaku ą w UTF-8. Z tego powodu len(napis) nie odpowiada automatycznie liczbie bajtów pliku, żądania HTTP ani pola w bazie danych. Szczegóły tej różnicy opisuje dokumentacja typów tekstowych Pythona, a praktyczne rozróżnienie znajdziesz także w materiale o kodowaniu UTF-8.
Przy ograniczeniu formularza trzeba więc najpierw ustalić, czego dotyczy limit. Dla limitu 50 znaków użyj len(tekst). Dla limitu 50 bajtów sprawdź długość wyniku kodowania:
tekst = "Zażółć gęślą jaźń"
liczba_znakow = len(tekst)
liczba_bajtow = len(tekst.encode("utf-8"))
print(liczba_znakow)
print(liczba_bajtow)
Ta różnica potrafi zmienić działanie walidacji. Tekst może przejść test liczby znaków, a jednocześnie przekroczyć limit narzucony przez protokół albo usługę, która liczy rozmiar danych po zakodowaniu.
Do pustej kolekcji użyj warunku, a do liczenia elementów funkcji
Czasem nie potrzebujesz liczby. Chcesz wyłącznie wiedzieć, czy lista zawiera dane. W takim przypadku ten zapis:
zadania = []
if not zadania:
print("Brak zadań")
jest czytelniejszy niż if len(zadania) == 0. Pusta lista, krotka, napis, słownik i zbiór są traktowane jako fałsz logiczny. PEP 8 zaleca korzystanie z tej właściwości sekwencji zamiast sprawdzania długości w warunku.
| Sytuacja | Prawdopodobna przyczyna lub skutek | Co zrobić |
|---|---|---|
| Chcesz wyświetlić liczbę wszystkich rekordów | Potrzebujesz długości kolekcji | Użyj len(rekordy) |
| Chcesz sprawdzić, czy lista jest pusta | Nie potrzebujesz konkretnej liczby | Użyj if not lista |
| Chcesz policzyć elementy spełniające warunek | len() policzyłoby także elementy niespełniające warunku |
Użyj sum(warunek for element in dane) |
| Przekazujesz generator | Generator nie przechowuje gotowej długości | Przetwórz go iteracyjnie albo utwórz listę, jeśli potrzebujesz liczby |
Sprawdzasz argument, który może być None |
if not argument potraktuje jako pustą także wartość 0 lub pusty tekst |
Użyj if argument is None, gdy sprawdzasz brak wartości |
Generator dobrze pokazuje granicę działania tej funkcji:
liczby = (liczba for liczba in range(5))
print(len(liczby)) # TypeError
Generator produkuje wartości dopiero podczas iteracji, więc nie ma ustalonego rozmiaru, który można odczytać bez uruchamiania całego procesu. Konwersja do listy zadziała, lecz zużyje pamięć i jednocześnie pobierze wszystkie elementy:
liczby = (liczba for liczba in range(5))
lista_liczb = list(liczby)
print(len(lista_liczb)) # 5
Reguła jest prosta. Jeśli potrzebujesz liczby, użyj len(); jeśli potrzebujesz tylko odpowiedzi tak lub nie, sprawdź prawdziwość obiektu; jeśli dane powstają strumieniowo, nie zakładaj, że mają długość.
Własna klasa może działać z len() dzięki __len__()
Ta funkcja nie jest zarezerwowana dla list i słowników. Własny obiekt również może udostępniać długość, jeśli klasa definiuje metodę __len__():
class Koszyk:
def __init__(self, produkty):
self.produkty = produkty
def __len__(self):
return len(self.produkty)
koszyk = Koszyk(["kawa", "herbata", "cukier"])
print(len(koszyk)) # 3
Metody z podwójnym podkreśleniem, nazywane metodami specjalnymi, opisują sposób współpracy obiektu z językiem. Według modelu danych Pythona __len__() powinna zwracać nieujemną liczbę całkowitą. Gdy wynik wynosi zero, obiekt może być także uznany za fałsz w warunku.
Własną klasę można oznaczyć jako obiekt o znanym rozmiarze także przy pomocy collections.abc.Sized. Ten abstrakcyjny interfejs opisuje obiekty, które zapewniają metodę __len__(), więc pozwala sprawdzić, czy dana wartość obsługuje długość bez zgadywania jej konkretnego typu.
from collections.abc import Sized
def pokaz_rozmiar(obiekt):
if isinstance(obiekt, Sized):
return len(obiekt)
return None
Przy projektowaniu własnej klasy trzeba najpierw ustalić, co ma być liczone. W koszyku może chodzić o liczbę pozycji produktowych, a w systemie rezerwacji o liczbę osób. Sama metoda będzie poprawna technicznie, lecz jej znaczenie musi być jasne dla osoby korzystającej z obiektu. Wynik możesz potem wyświetlić przez funkcję print w Pythonie, ale prezentacja nie zmienia tego, co faktycznie zwraca len().
W kilku przypadkach długość wymaga dodatkowej ostrożności
Najbardziej zaskakujący przypadek dotyczy ogromnego zakresu:
zakres = range(2 ** 100)
print(len(zakres))
W CPython takie wywołanie może zakończyć się błędem OverflowError, ponieważ długość przekracza limit reprezentowany przez sys.maxsize. Sam obiekt range nie przechowuje wszystkich wartości w pamięci, lecz funkcja nadal musi zwrócić długość w obsługiwanym typie liczbowym.
Inna pułapka pojawia się przy metodzie __length_hint__(). Nie zastępuje ona __len__(). Jest tylko podpowiedzią dla operacji, które mogą wcześniej zarezerwować miejsce na wynik. Oficjalna dokumentacja modelu danych zaznacza, że podpowiedź może być większa albo mniejsza od rzeczywistej długości i nie jest wymagana do poprawnego działania programu.
from operator import length_hint
iterator = iter([10, 20, 30])
print(length_hint(iterator))
Nie używaj length_hint() do walidowania danych biznesowych, limitów użytkownika ani warunków bezpieczeństwa. Do takich decyzji potrzebujesz rzeczywistej liczby elementów albo jawnego przejścia po danych.
Jeszcze jedna granica dotyczy słowników. len(dane) odpowiada liczbie kluczy, a nie liczbie wszystkich wartości zagnieżdżonych w strukturze. Dla obiektu poniżej wynik wynosi 2, mimo że wewnątrz znajdują się trzy wartości liczbowe:
dane = {
"punkty": [10, 20],
"bonus": 5
}
print(len(dane)) # 2
Gdy decyzja zależy od zawartości, a nie od liczby kluczy, trzeba wybrać właściwe wyrażenie, na przykład len(dane["punkty"]) albo osobne zliczanie wartości. To drobne rozróżnienie często decyduje o tym, czy raport pokaże liczbę rekordów, pól czy pojedynczych danych.
Najlepszy skrót myślowy do codziennej pracy z len()
Możesz zapamiętać cztery pytania, które szybko prowadzą do poprawnego rozwiązania:
- Co jest elementem? W słowniku klucz, w napisie punkt kodowy, w liście pozycja.
- Czy potrzebujesz liczby? Jeśli nie, użyj testu logicznego zamiast
len(). - Czy obiekt ma gotową długość? Generator jej nie udostępnia, a własna klasa może wymagać
__len__(). - Czy chodzi o znaki czy bajty? Przy transmisji i limitach technicznych sprawdź także wynik
.encode("utf-8").
Uważam, że największą pułapką nie jest sama składnia len(obiekt), tylko bezrefleksyjne założenie, że „długość” zawsze oznacza to samo. Gdy najpierw nazwiesz jednostkę, którą chcesz policzyć, wybór między len(), warunkiem logicznym, iteracją i kodowaniem tekstu staje się dużo prostszy.
W praktyce funkcja pozostaje bardzo krótka, lecz opiera się na protokole obiektu. To właśnie dlatego ten sam zapis działa dla listy, słownika, własnej klasy i wielu innych kolekcji, a dla generatora albo liczby kończy się innym rezultatem.
