Pierwsze kroki z danymi¶
Powyżej stwierdziliśmy, że Python wspiera paradygmat programowania zorientowanego obiektowo, co oznacza, że dane są centralnym punktem skupienia podczas rozwiązywania problemów. W Pythonie, jak również w innych językach programowania obiektowego, definiujemy klasę jako nośnik opisu tego jak dane wyglądają (ich stan) i co dane mogą zrobić (zachowanie). Klasy są analogią do abstrakcyjnych typów danych, ponieważ użytkownik zaznajomiony jest tylko ze stanem i zachowaniem konkretnego danej. Zdefiniowane dane nazywane są obiektami w paradygmacie programowania obiektowego. Obiekt jest instancją klasy.
Rodzaje wbudowanych danych Atomowych¶
Powtórkę rozpoczniemy od rozważań dotyczących atomowych typów danych. Python posiada dwie główne, wbudowane klasy numeryczne, które implementują typy danych liczb całkowitych i zmienno przecinkowych. Klasy te noszą odpowiednio nazwy int i float. Standardowe operacje arytmetyczne, +, -, *, /, oraz ** (potęgowanie), mogą być zapisane w nawiasach wymuszając inną kolejność działań, aniżeli wynika to z priorytetów użytych operatorów. Inne bardzo przydatne operacje to reszta z dzielenia – operator modulo %, oraz dzielenie całkowite - //. Zwróć uwagę, że przy dzieleniu (/) dwóch liczb całkowitych, rezultat jest liczbą zmienno-przecinkową. Operator dzielenia całkowitego odrzuca część ułamkową wyniku, zwracając jedynie część całkowitą.
Logiczny typ danych, zrealizowany w Python jako klasa bool, będzie bardzo przydatny do reprezentowania wartości logicznych. Obiekt typu bool może być jedynie w jednym z dwóch stanów - Prawda lub Fałsz. Standardowe operatory logiczne to and, or, i not.
>>> True
True
>>> False
False
>>> False or True
True
>>> not (False or True)
False
>>> True and True
True
Obiekty typu logicznego są również stosowane jako wyniki operacji porównania, takich jak równość (==) i większy niż (\(>\)). Ponadto, operatory relacyjne i operatory logiczne mogą być łączone ze sobą, tworząc bardziej złożone zagadnienia logiczne. Tabela 1 pokazuje relacyjne i logiczne operatory z przykładami ich użycia przedstawionymi poniżej jej.
Nazwa działania | Operator | Wyjaśnienie |
---|---|---|
mniej niż | \(<\) | Operator mniej niż |
więcej niż | \(>\) | Operator więcej niż |
mniejszy bądź równy | \(<=\) | Operator mniejszy bądź równy |
większy bądź równy | \(>=\) | Operator większy bądź równy |
równy | \(==\) | Operator równości |
nierówny | \(!=\) | Operator nierówności |
logiczna koniunkcja | \(and\) | Oba argumenty są Prawdziwe dla prawdziwego rezultatu |
logiczna alternatywa | \(or\) | Jeden lub drugi z argumentów jest Prawdziwy dla prawdziwego rezultatu |
logiczna negacja | \(not\) | Negacja prawdziwych wartości, Fałsz staje się Prawdą, a Prawda Fałszem |
Identyfikatory są używane w językach programowania jako nazwy. W Pythonie, identyfikatory zaczynają się od litery lub znaku podkreślenia (_), rozróżniają wielkość liter i mogą być dowolnej długości. Pamiętaj, że dobrym zwyczajem jest nadawać nazwy, które mają znaczenie ściśle powiązane z kontekstem programu, co poprawia jego czytelność i zrozumienie.
W Python zmienna tworzona jest, gdy jej nazwa użyta jest po raz pierwszy po lewej stronie instrukcji przypisania. Umożliwia to powiązanie nazwy z wartością. Zmienna stanie się referencją do danej, a nie samą daną. Rozważmy poniższą sesję:
>>> theSum = 0
>>> theSum
0
>>> theSum = theSum + 1
>>> theSum
1
>>> theSum = True
>>> theSum
True
Wyrażenie theSum = 0 tworzy zmienną o nazwie theSum oraz powiązanie jej do obiektu danych 0 (patrz Figure 3). Ogólnie rzecz ujmując, prawa strona instrukcji przypisania jest przetwarzana, a referencja do obiektu będącego wynikiem zostaje “przypisana” do nazwy po lewej stronie. W tym miejscu naszego przykładu, zmienna jest liczbą całkowitą, ponieważ jest to typ danej do której się odnosi theSum. Jeśli typ danej ulegnia zmianie jak pokazano powyżej (patrz Figure 4), w przypadku wartości logicznej True, również zmieni się typ zmiennej theSum (teraz typu boolean). Wyrażenie przypisania zmienia referencję do jakiej odnosi się zmienna. Jest to dynamiczna cecha Python. Ta sama zmienna może być powiązana z wieloma różnymi typami danych.
Złożone typy danych - kolekcje¶
Oprócz klas numerycznych i logicznych, Python posiada wiele niezbędnych klas tworzących kolekcje wbudowane. Listy, łańcuchy i krotki to uporządkowane kolekcje, o podobnej strukturze, ale różniące się szczegółami zastosowania, które należy prawidłowo zrozumieć aby je właściwie użyć. Zbiory (sets) i słowniki (dictionaries) to kolekcje nieuporządkowane.
Lista to uporządkowana kolekcja referencji do obiektów danych Pythona, która może być również pusta. Listy są zapisywane są jako wartości oddzielane przecinkami, ujęte w nawiasach kwadratowych.Pusta lista to po prostu``[ ]``. Listy są heterogeniczne, co oznacza, że obiekty danych nie muszą należeć do tych samych klas, a kolekcja może być przypisana do zmiennej jak poniżej. Poniższy fragment pokazuje obiekty różnych typów Pythona zawarte w liście.
>>> [1,3,True,6.5]
[1, 3, True, 6.5]
>>> myList = [1,3,True,6.5]
>>> myList
[1, 3, True, 6.5]
Zauważ, że próba obliczenia listy w Python zwraca ją samą. Jednakże, w celu zapamiętywania listy do dalszego jej przetworzenia, jej odniesienie musi być przypisane do zmiennej.
Ponieważ listy uważa się za sekwencje, udostępniają one szereg operacji wspólnych dla każdej sekwencji w Python. Tabela 2 przedstawia te operacje, a następny kod źródłowy pokazuje ich użycie.
Typ operacji | Operator | Wyjaśnienie |
---|---|---|
indeksowanie | [ ] | Dostęp elementu sekwencji |
konkatenacja | + | scal sekwencje razem |
odwzorowanie | * | Odwzorowanie listy wielokrotnie |
przeszukiwanie | in | Pytanie, czy element jest w sekwencji |
długość | len | Zapytaj o liczbę elementów w sekwencji |
wycinanie | [ : ] | Wydzielenie fragmentu sekwencji |
Należy pamiętać, że wskaźniki dla list (sekwencji) rozpoczynają sie od 0. Operacja wycięcia (slice), myList[1:3], zwraca listę elementów, poczynając od pozycji indeksowanej przez 1 w górę aż do elementu nr 3, który już nie jest w niej ujęty.
Czasami potrzeba zainicjować listę. Można to w szybki sposób osiągnąć za pomocą operatora odwzorowania np.:
>>> myList = [0] * 6
>>> myList
[0, 0, 0, 0, 0, 0]
Bardzo ważnym aspektem dotyczącym odwzorowania jest to, że otrzymany rezultat składa się z powtórzeń referencji do sekwencji obiektów danych. Kolejny przykład dobrze to obrazuje:
Zmienna A zawiera kolekcję trzech odniesień do oryginalnej listy nazwanej myList. Zmiana jednego elementu z myList objawia się trzykrotnie w zmiennej A.
Listy wspierają metody, przeznaczone do budowy struktur danych. Tabela 3 przedstawia wykaz tych metod, a kolejny przykład ich użycie.
Nazwa metody | Zastosowanie | Wyjaśnienie |
---|---|---|
append | alist.append(item) | Dodaje nowy element na koniec listy |
insert | alist.insert(i,item) | Wstawia element do listy na pozycji ‘i-tej’ |
pop | alist.pop() | Usuwa oraz zwraca ostatni element na liście |
pop | alist.pop(i) | Usuwa oraz zwraca i-ty element z listy |
sort | alist.sort() | Modyfikuje listę która ma być przesortowana ( ) |
reverse | alist.reverse() | Modyfikuje listę do odwrotnej kolejności ( ) |
del | del alist[i] | Usuwa element na pozycji i-tej |
index | alist.index(item) | Zwraca indeks pierwszego pojawienia się elementu item |
count | alist.count(item) | Zwraca liczbę wystąpień elementu item |
remove | alist.remove(item) | Usuwa pierwsze wystąpienie elementu item w liście |
Widać, że niektóre z metod, jak np.: pop, zwracają wartości, a także modyfikują listę. Inne, takie jak reverse, tylko modyfikują listę. Operacja pop domyślnie działa na końcu listy, ale można również wymusić usunięcie i zwrot określonego elementu. Zakres indeksowania dla tych metod rozpoczyna się od 0. Powinieneś również zauważyć znane Ci odwołanie obiektu do metody poprzez operator kropki myList.append(False) co można oczytać jako “poproś obiekt myList aby wywołał swoją metodę append wraz z parametrem o wartość False.”
>>> (54).__add__(21)
75
>>>
W tym fragmencie kodu wywołujemy obiekt 54 będący liczbą całkowitą do wykonywania metody add (tzw __add__ w Python) i przekazując 21 jako wartość parametru. Wynikiem jest suma 75. Oczywiście, zwykle piszemy to jako 54+21. Powiemy o wiele więcej na temat tych metod w dalszej części rozdziału.
Często używaną funkcją Python, która jest zwykle omawiana w połączeniu z listami jest range. Tworzy ona obiekt zakresu, który reprezentuje sekwencję kolejnych wartości. Dzięki funkcji list, możliwe jest wyświetlenie obiektu zakresu jako listy co przedstawia poniższy przykład:
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5,10)
range(5, 10)
>>> list(range(5,10))
[5, 6, 7, 8, 9]
>>> list(range(5,10,2))
[5, 7, 9]
>>> list(range(10,1,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2]
>>>
Obiekt zakresu reprezentuje sekwencję liczb całkowitych. Domyślnie rozpoczyna się od 0 jednak po podaniu większej ilości parametrów możliwe jest modyfikowanie wartości początkowej, końcowej, a nawet pomijanych liczb. W pierwszym przykładzie, sewkencja rozpoczyna się od 0 i rośnie w górę aż do 10, które jest z niej wyłączone. Drugi przykład, range(5,10) startuje od 5 i rośnie w górę aż do 10, które również jest z niej wyłączone. Kolejne wywołanie range(5,10,2) również zaczyna od 5, ale rośnie w górę co dwa (10 wyłączone z sekwencji). Ostatnia funkcja list(range(10,1,-1)) tworzy zakres malejący od 10 w doł aż do 1. Tu również wartość skrajna (1) jest wyłączona.
Stringi (łańcuchy znaków) są to sekwencje kolekcji liter, cyfr i symboli, które w językach programowania nazywne są znakami. Wartości typu string są rozróżniane od identyfikatorów za pomocą symbolu cudzysłowia (pojedynczego lub podwójnego).
>>> "David"
'David'
>>> myName = "David"
>>> myName[3]
'i'
>>> myName*2
'DavidDavid'
>>> len(myName)
5
>>>
Ponieważ ciągi znaków są sekwencjami, wszystkie operacje opisane powyżej działają zgodnie z oczekiwaniami. Dodatkowo stringi posiadają szereg metod, z których niektóre są pokazane w Tabela 4. Na przykład,
>>> myName
'David'
>>> myName.upper()
'DAVID'
>>> myName.center(10)
' David '
>>> myName.find('v')
2
>>> myName.split('v')
['Da', 'id']
Spośród nich, metoda split (podział) będzie bardzo przydatna podczas przetwarzania danych. Jej wywołanie tworzy listę z sekwencjami znaków wydzielonymi ze stringa, gdzie punktem podziału jest podany parametr. W przykładzie użyto do tego znaku v. Jeśli parametr nie został określony przy wywołaniu metoda split dzieli string na podstawie białych znaków tj. spacji, tabulatorów oraz początku nowej linii.
Nazwa metody | Zastosowanie | Wyjaśnienie |
---|---|---|
center | astring.center(w) | Zwraca string wyśrodkowany w polu o szerokości w |
count | astring.count(item) | Zwraca ilość wystąpień elementu item w łańcuchu znaków |
ljust | astring.ljust(w) | Zwraca string wyrównany do lewej w polu o szerokości w |
lower | astring.lower() | Zwraca string składający się z małych liter |
rjust | astring.rjust(w) | Zwraca string wyrównany do prawej w polu o szerokości w |
find | astring.find(item) | Zwraca indeks pierwszego wystąpienia elementu item w stringu |
split | astring.split(schar) | Dzieli string na mniejsze sekwencje wydzielone przez schar |
Główna różnica pomiędzy listami i ciągami znaków polega na tym, że listy mogą być modyfikowane podczas gdy ciągi nie. Listy określa się jako mutowalne, a stringi jako niemutowalne. Na przykład, możesz zmodyfikować element listy za pomocą odwołania przez indeks i przypisania nowej wartości. W przypadku stringa taka zmiana jest niedozwolona.
>>> myList
[1, 3, True, 6.5]
>>> myList[0]=2**10
>>> myList
[1024, 3, True, 6.5]
>>>
>>> myName
'David'
>>> myName[0]='X'
Traceback (most recent call last):
File "<pyshell#84>", line 1, in -toplevel-
myName[0]='X'
TypeError: object doesn't support item assignment
>>>
Krotki są bardzo podobne do list w tym, że są to heterogeniczne sekwencje danych. Różnica jest taka, że krotka jest niemodyfikowalna (niemutowalna), podobnie jak ciąg znaków. Krotka nie może być zmieniona. Krotki są zapisywane jako wartości oddzielone przecinkami w nawiasach. Jako sekwencje, mogą używać każdej operacji wcześniej opisanej. Na przykład,
>>> myTuple = (2,True,4.96)
>>> myTuple
(2, True, 4.96)
>>> len(myTuple)
3
>>> myTuple[0]
2
>>> myTuple * 3
(2, True, 4.96, 2, True, 4.96, 2, True, 4.96)
>>> myTuple[0:2]
(2, True)
>>>
Jeśli jednak spróbujesz zmienić element krotki, otrzymasz błąd. Zauważ, że komunikat o błędzie informuje o miejscu i przyczynie problemu.
>>> myTuple[1]=False
Traceback (most recent call last):
File "<pyshell#137>", line 1, in -toplevel-
myTuple[1]=False
TypeError: object doesn't support item assignment
>>>
Set (zbiór) jest to nieuporządkowana kolekcja pusta lub nie, zawierająca niemutowalne obiekty danych Python. Zbiory nie pozwalają na duplikaty i są zapisywane jako wartości oddzielone przecinkami, zawarte w nawiasach klamrowych. Zbiór pusty jest reprezentowany przez set(). Zbiory są heterogeniczne, a kolekcja może być przypisana zmiennej jak poniżej.
>>> {3,6,"cat",4.5,False}
{False, 4.5, 3, 6, 'cat'}
>>> mySet = {3,6,"cat",4.5,False}
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>>
Nawet jeśli zbiory nie są uważane za sekwencyjne, to obsługują one kilka znanych operacji przedstawionych wcześniej. Są one przedstawione w Tabela 5, a poniżej kod obrazujący przykłady ich użycia.
Nazwa operatora | Operator | Wyjaśnienie |
---|---|---|
membership | in | Dołącza obiekt do zbioru |
length | len | Zwraca ilość obiektów w zbiorze |
| | aset | otherset | Zwraca nowy zbiór zawierający element obu zbiorów |
& | aset & otherset | Zwraca nowy zbiór zawierający element wspólne dla obu zbiorów |
- | aset - otherset | Zwraca nowy zbiór zawierający elementy z pierwszego zbioru i nie zawarte w drugim |
<= | aset <= otherset | Sprawdza czy wszystkie elementy z pierwszego zbioru są również w drugim |
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>> len(mySet)
5
>>> False in mySet
True
>>> "dog" in mySet
False
>>>
Zbiory wspierają szereg metod, które powinny być znane dla tych, którzy pracowali z nimi w dziedzinie matematyki. Tabela 6 zawiera ich podsumowanie, a pod nią znajdziesz przykłady użycia. Należy pamiętać, że funkcje union, intersection, issubset, oraz difference mają swoje operatory, które również mogą być używane.
Nazwa metody | Zastosowanie | Wyjaśnienie |
---|---|---|
union | aset.union(otherset) | Zwraca nowy zbiór zawierający element obu zbiorów |
intersection | aset.intersection(otherset) | Zwraca nowy zbiór zawierający element wspólne dla obu zbiorów |
difference | aset.difference(otherset) | Zwraca nowy zbiór zawierający elementy z pierwszego zbioru i nie zawarte w drugim |
issubset | aset.issubset(otherset) | Sprawdza czy wszystkie elementy z pierwszego zbioru są również w drugim |
add | aset.add(item) | Dołącza element item do zbioru |
remove | aset.remove(item) | Usuwa element item ze zbioru |
pop | aset.pop() | Usuwa dowolny element ze zbioru |
clear | aset.clear() | Usuwa wszystkie elementy ze zbioru |
>>> mySet
{False, 4.5, 3, 6, 'cat'}
>>> yourSet = {99,3,100}
>>> mySet.union(yourSet)
{False, 4.5, 3, 100, 6, 'cat', 99}
>>> mySet | yourSet
{False, 4.5, 3, 100, 6, 'cat', 99}
>>> mySet.intersection(yourSet)
{3}
>>> mySet & yourSet
{3}
>>> mySet.difference(yourSet)
{False, 4.5, 6, 'cat'}
>>> mySet - yourSet
{False, 4.5, 6, 'cat'}
>>> {3,100}.issubset(yourSet)
True
>>> {3,100}<=yourSet
True
>>> mySet.add("house")
>>> mySet
{False, 4.5, 3, 6, 'house', 'cat'}
>>> mySet.remove(4.5)
>>> mySet
{False, 3, 6, 'house', 'cat'}
>>> mySet.pop()
False
>>> mySet
{3, 6, 'house', 'cat'}
>>> mySet.clear()
>>> mySet
set()
>>>
Ostatnim typem kolekcji w Python jest nieuporządkowana struktura zwana słownikiem. Słowniki są zbiorem powiązanych elementów w pary nazwanych kluczem (key) i wartością (value). Para ta zwykle zapisywana jest w postaci klucza:wartość. Słownik zapisany jest jako pary oddzielone przecinkiem zawarte w nawiasach klamrowych. Na przykład:
>>> capitals = {'Iowa':'DesMoines','Wisconsin':'Madison'}
>>> capitals
{'Wisconsin': 'Madison', 'Iowa': 'DesMoines'}
>>>
Słownikiem można manipulować poprzez dostęp do wartości za pomocą klucza lub dodając inną parę klucz:wartość. Składnia dla dostępu wygląda podobnie jak w przypadku sekwencji, z tym wyjątkiem, że zamiast indeksu używa się klucza. Dodanie nowej wartości odbywa się podobnie.
Należy zapamiętać, że słownik utrzymany jest w sposób, który nie zachowuje porządku w odniesieniu do kluczy. Pierwsza dodana para ('Utah': 'SaltLakeCity') znalazła się na początku słownika natomiast druga na jego końcu ('California': 'Sacramento'). Umieszczenie klucza zależy od operacji “hashowania”, która zostanie wyjaśniona w detalach w rozdziale 4. Powyższy kod pokazuje również, że funkcja len działa w ten sam sposób jak dla poprzednich typów kolekcji.
Słowniki mają zarówno metody i operatory. Ich opisy zawarte są w Tabeli 7 i Tabeli 8, a kod pod nimi ukazuje je w akcji. Metody keys, values i items zwracają obiekt zawierający pożądaną wartość. Można użyć funkcji list aby skonwertować wynik do postaci listy. Przykład uwidacznia również dwojakość działania metody get. Jeśli klucz nie jest zawarty w słowniku get zwróci None. Natomiast podanie drugiego, opcjonalnego parametru spowoduje, iż zostanie on zwrócony w przypadku braku klucza.
Operator | Zastosowanie | Wyjaśnienie |
---|---|---|
[] | myDict[k] | Zwraca wartość powiązaną z k, w przeciwnym wypadku error |
in | key in adict | Zwraca True jeśli klucz znajduje się w słowniku, w przeciwnym wypadku False |
del | del adict[key] | Usuwa wpis ze słownika |
>>> phoneext={'david':1410,'brad':1137}
>>> phoneext
{'brad': 1137, 'david': 1410}
>>> phoneext.keys()
dict_keys(['brad', 'david'])
>>> list(phoneext.keys())
['brad', 'david']
>>> phoneext.values()
dict_values([1137, 1410])
>>> list(phoneext.values())
[1137, 1410]
>>> phoneext.items()
dict_items([('brad', 1137), ('david', 1410)])
>>> list(phoneext.items())
[('brad', 1137), ('david', 1410)]
>>> phoneext.get("kent")
>>> phoneext.get("kent","NO ENTRY")
'NO ENTRY'
>>>
Nazwa metody | Zastosowanie | Wyjaśnienie |
---|---|---|
keys | adict.keys() | Zwraca klucze zawarte w słowniku jako obiekt dict_keys |
values | adict.values() | Zwraca wartości zawarte w słowniku jako obiekt dict_values |
items | adict.items() | Zwraca pary klucz:wartość jako obiekt dict_items |
get | adict.get(k) | Zwraca wartość powiązaną z k, w przeciwnym wypadku None |
get | adict.get(k,alt) | Zwraca wartość powiązaną z k, w przeciwnym wypadku alt |
Informacja
Ten obszar roboczy został przeznaczony dla twojej wygody. Możesz użyć okna activecode w dowolny sposób.