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ą.




Podstawowe operatory arytmetyczne (intro_1)

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.

Tabela 1: Operatory relacyjne i logiczne
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



Podstawowe Operatory Relacyjne i Logiczne (intro_2)

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.

../_images/assignment1.png

Figure 3: Variables Hold References to Data Objects

../_images/assignment2.png

Figure 4: Assignment Changes the Reference

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.

Tabela 2: Operacje na sekwencjach w Python
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:




Repetition of References (intro_3)

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.

Tabela 3: Przykłady listy metod w Python
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



Examples of List Methods (intro_5)

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.

Tabela 4: Metody klasy String w Python
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.

Tabela 5: Operacje klasy Set w Python
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.

Tabela 6: Metody klasy Set w Python
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.




Using a Dictionary (intro_7)

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.

Tabela 7: Operacje klasy Słowników w Python
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'
>>>
Tabela 8: Metody klasy Słowników w Python
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.




(scratch_01_01)

Następna część - Funkcja Input i Output