Skip to content

Instantly share code, notes, and snippets.

@jlegutko
Last active January 22, 2018 23:50
Show Gist options
  • Select an option

  • Save jlegutko/7ec246f8ec987031c3f0956ac051039a to your computer and use it in GitHub Desktop.

Select an option

Save jlegutko/7ec246f8ec987031c3f0956ac051039a to your computer and use it in GitHub Desktop.

Materiały do powtórki

Zadanie 1. Określanie wyniku zależnie od typu wyrażenia

a)

>> 0 ** 2
>> 0

typ: int, wynik: 0

b)

>> 0.3 % 2
>> 0.3

typ: float, wynik: 0.3

c)

>> 0,3 % 2 
>> (0,1)

typ: tuple, wynik: (0, 1), bo najpierw 0 % 2, a następnie 3 % 2

d)

>> 0,3 + 0,2
>> (0, 3, 2)

typ: tuple, wynik: (0, 3, 2), wynikiem jest sumowanie obydwu list

e)

>> 2 << 1
>> 4

typ : int , wynik: 4, operator bitowy << traktuje podane liczby jako ciągi bitowe. Ostatecznie zwraca wynik typu int, przekonwertowany z zapisu binarnego. Przemnożenie 2 przez 2 ** 1.

1. Modyfikowalność

Modyfikowalne:

  • int, float, complex
  • list [1, 2]
  • set {1, 2}
  • dict { 'key': 'value' }

Operacje na floatach

# możemy wymusić konwersję typów
>>> float(12)
12.0
>>> int(-1.5), int(1.5)  # część ułamkowa jest obcinana
(-1, 1)

Operacje na intach

>>> 5 / 3  # powoduje konwersję do typu float
1.6666666666666667
>>> 5 / 1  # konwersja jest wykonywana zawsze
5.0
>>> 5 // 3  # dzielenie z zaokrąglaniem w dół (podłoga)
1
>>> 5 % 3  # modulo (reszta z dzielenia)
2

Moduł math

>>> math.sin(math.pi / 2)
1.0

>>> math.sqrt(5)
2.23606797749979
>>> 5 ** 0.5
2.23606797749979

>>> math.sqrt(-2)                            # Uwaga na liczby ujemne!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> -2 ** 0.5
-1.4142135623730951

Różne rodzaje zaokrągleń

# podłoga i obcinanie jako funkcje z modułu 'math'
>>> import math
>>> math.floor(-3.6)
-4
>>> math.trunc(-3.6) # wynik typu int (!)
-3

# zwykłe zaokrąglanie (round) to co innego
>>> round(-3.5), round(-3.4)
(-4, -3)

# jest jeszcze sufit (ceil) - zaokrąglanie w górę
>>> math.ceil(-3.5), math.ceil(-3.4)
(-3, -3)

Dokładna reprezentacja ułamków dziesiętnych

>>> import decimal
>>> a = decimal.Decimal('0.2')
>>> type(a)
<class 'decimal.Decimal'>

Dokładna reprezentacja ułamków zwykłych

>>> from fractions import Fraction
>>> Fraction(1, 3) + Fraction(28, 30)
Fraction(19, 15)

Niemodyfikowalne

  • string str()
  • tuple (1, 2)
  • frozenset `fozenset()
  • range range()

2. Tworzenie typów

2.1. Typy sekwencyjne

Typy sekwencyjne to:

  1. Lista — funkcja list() lub [ ]
  2. Krotka — funkcja tuple() lub ( )
  3. Przedział — funkcja range()
2.1.1. Lista

Modyfikowalna lista elementów. Jest uszeregowana w pamięci. Można stosować podobe operacje jak w napisach:

>> [0,1,2,3,4,5][3:]
[3, 4, 5]
>> [56] + ['a', 'b'] * 2
[56, 'a', 'b', 'a', 'b']
>> l = [1, 2, 'kot']

# dodawanie elementów
>> l.append(4)
>> l.extend(['nowa', 'lista'])  # wypróbuj też operator +=
>> l.extend('napis')
>> l
[1, 2, 'kot', 4, 'nowa', 'lista', 'n', 'a', 'p', 'i', 's']
>> l.insert(0, 123)
>> l
[123, 1, 2, 'kot', 4, 'nowa', 'lista', 'n', 'a', 'p', 'i', 's']

# odwracanie listy
>> l.reverse()
>> l
['s', 'i', 'p', 'a', 'n', 'lista', 'nowa', 4, 'kot', 2, 1, 123]

# usuwanie elementów
>> del l[:5]
>> l[4:] = []
>> l
['lista', 'nowa', 4, 'kot']
>> l.remove('nowa')
>> l
['lista', 4, 'kot']
>> l.pop(1)  # pop zwraca usuwany element
4
>> l
['lista', 'kot']

# wyszukiwanie elementów
>> 'kot' in l
True
>> 'pies' in l
False
>> l.index('kot')
1

# sortowanie listy
>> l
['lista', 'kot']
>> l.sort()
>> l
['kot', 'lista']
>> l.sort(reverse=True)
>> l
['lista', 'kot']
2.1.2. Krotki
>> 1, 2, 3   # z nawiasem lub bez
(1, 2, 3)
>> (1, 2, 3)
(1, 2, 3)

# Jak zapisać krotkę jednoelementową?
>> 1,
(1,)

# Częste zastosowanie krotek
>> a, b = 1, 2
>> a, b = b, a
>> a
2
>> b
1

# Krotki wspierają operacje znane z list, lecz są niemodyfikowalne
>> t = 1, 2, 3, 'kot'
>> t[3]
'kot'
>> t[1:]
(2, 3, 'kot')
>> t*3
(1, 2, 3, 'kot', 1, 2, 3, 'kot', 1, 2, 3, 'kot')

Krotki są niemodyfikowalne, tzn. nie można zmienić elementu:

>> t[0] = 'cokolwiek'
Traceback (most recent call last):
TypeError: 'tuple' object does not support item assignment

Rozpakowywanie list i krotek – pozwala przypisać elementy do zmiennych:

>> l = [1, 2, 3]
>> [a, b, c] = l
>> a
1
>> b
2
>> c
3

>> (x, y, z) = l
>> x
1

>> t = 'x', 'y', 'z'
>> [d, e, f] = g, h, i = t
>> f
'z'
>> h
'y'
2.1.3. Przedział

Funkcja range(start, stop[, step]). Można podać tylko stop, start, stop, lub wszystkie trzy. Generuje niemodyfikowalną listę.

2.2. Zbiory

Typy zbiorów:

  1. Zbiór modyfikowalny — funkcja set() lub { 1, 2 }
  2. Zbiór niemodyfikowalny — funkcja frozenset()

Zbiory działają tak samo jak zbiory matematyczne. Tylko unikalne elementy, powtórzenia są ignorowane.

>> s = { 1, 2, 3 }
>> 1 in s
True

Modyfikowanie zbioru: s.add(), s.remove(), s.update() (rozbija listę i dodaje każdy element osobno). Elementy zbioru muszą być niemodyifkowalne!

Działania na zbiorach:

>> s1 = set('abc')
>> s2 = set('acf')
>> s1 & s2
{'a', 'c'}
>> s1 | s2
{'a', 'c', 'b', 'f'}
>> s1 - s2
{'b'}
>> s1 >= s2
False
>> s1 |= s2
>> s1
{'a', 'c', 'b', 'f'}
>> s1 >= s2
True

2.3. Typy mapujące

Tylko typ słownikowy. Funkcja dict() lub { 'key': 'value' }.

Brak uszeregowania! Dostęp wyłącznie po kluczu, elementy nie są posortowane w pamięci.

Można złączyć dwie listy w słownik. Jedna lista to klucze, a druga to wartości: dict(zip(keys, values))

Pobieranie elementu: dictionary[key], albo dictionary.get(key). Druga opcja lepsza, bo w przypadku braku elementu nie wyrzuci błędu, tylko zwróci None.

Dostęp do zawartości tylko po kluczach! Klucze nie mogą być modyfikowalne (np. listy i zbiory).

>> d = { key: value }
>> key in d
True
>> value in d
False

Dostępne metody: d.keys() (zwraca klucze w liście), d.values() (lista z wartoścami), d.items() (lista krotek klucz-wartość).

Operatory bitowe:

  • bin(zmienna) - zamienia na notację bitową
  • Wyrażenie x << y zwraca x z bitami przesuniętymi w lewo o y miejsc (nowe bity po prawej stronie to zera). Jest to to samo, co pomnożenie x przez 2 ** y.
  • Wyrażenie x >> y zwraca x z bitami przesuniętymi w prawo o y miejsc. Jest to to samo, co dzielenie x przez 2 ** y.
  • Wyrażenie x & y to wykonywanie operatora logicznego and na bitach. Każdy bit wyjścia wynosi 1, jeśli odpowiadający bit z x oraz z y wynosi 1, w przeciwnym razie bit wyjścia będzie wynosił 0.
  • Wyrażenie x | yto wykonywanie operatora logicznego or na bitach.
  • Wyrażenie ~x zwraca dopełnienie liczby x - liczbę otrzymaną przez przełączenie każdego z bitów 1 na 0 i każde 0 na 1. Jest to to samo co -x - 1.
  • Wyrażenie x ^ y zwraca bit wyjścia, taki sam, jak odpowiadający mu bit w liczbie x, ale tylko w przypadku jeśli ten bit w ciągu bitów y jest równy 0. Jeśli ten bit w y jest równy 1 to bit wyjściowy będzie dopełnieniem bitu znajdującego się w x.

Instrukcje warunkowe:

operatory: ==, !=, <, >, <=, >=, and, or, in, is, not

Zadanie 2. Operacje na stringach

string - łańcuch znaków, napis (klasa str) - niemodyfikowalny ciąg znaków Unicode. Znaki specjalne: \n, \t, \temp. Gdy chcemy napisać '\t', można posłużyć się zapisem '\t' lub dodać 'r' przed stałą.

a = 'ala'
b = 'kot'

a)

>> a[2] in b 
>> False

Wyrażenie sprawdza czy w stringu b znajduje się element a[2] = 'a'

Operacje możliwe do wykonania na stringach:

  • Sprawdzanie długości łańcucha - funkcja len(string)
  • Wycinanie fragmentów (slicing)
>>> a = 'tekst testowy'
>>> a[3]       # czwarty znak (numerowane są od zera)
's'
>>> a[5:]      # od znaku szóstego
' testowy'
>>> a[:-3]     # do znaku czwartego od końca
'tekst test'
>>> a[:]       # kopia całego napisu
'tekst testowy'
>>> a[4::-1]   # od znaku piątego do początku (-1 odwraca kolejność)
'tsket'
>>> a[8:2:-2]  # od dziewiątego do czwartego, co drugi, wstecz
'stt'
>>> a[:2] + a[3:8] + 'k' + a[8:]
'test tekstowy'
  • Łączenie napisów
>>> a += ' nowy'
>>> a
'tekst testowy nowy'
>>> a *= 2
>>> a
'tekst testowy nowytekst testowy nowy'
  • Odczytywanie kodu znaku po znaku ord()
>> ord('a')
97
  • Odczytywanie znaku po kodzie znaku chr()
>> chr(98)
'b'
  • Sprawdzanie czy dana litera jest w napisie in, zwraca True lub False
>>> s = 'ala ma kota'
>>> 'l' in s        
True
  • Znajdowanie poszczególnych znaków bądź łańcuchów string.find()
>>> s.find('ma')     
4                    # łańcuch zaczyna się od pozycji 5

Jeśli w napisie nie ma danego znaku bądź łańcucha wynikiem funkcji będzie -1

  • Dodawanie znaku nowej linii
>>> s += '\n'
>>> s
'ala ma kota\n' 
  • Usuwanie znaku nowej linii string.rstrip()
>>> s.rstrip()       
'ala ma kota'
  • Podział łańcucha wg białych znaków string.split()
>>> s.split()         
['ala', 'ma', 'kota']

Funkcją split możemy także podzielić łańcuch wg znaku bądź innego łańcucha string.split('zmienna')

  • Zmiana liter na duże, zmiana liter na małe - string.upper(), string.lower()
  • Scalanie łańcuchów z danym separatorem 'separator'.join(string.split())
>>> '***'.join(s.split())  
'ala***ma***kota'
  • Sprawdzanie od jakiego znaku/łańcucha zaczyna się string string.startswith('zmienna'), może zwracać wartość True lub False
>>> s.startswith('ala')    
True

Standardy kodowania znaków

Łańcuchy znaków (klasa str) używają standardu Unicode. Jeżeli w konsoli mamy kodowanie UTF-8, to wprowadzane znaki będą wyświetlane poprawnie.

  • Funkcja zmieniająca standard tekstu string.encode('standard_kodowania')
u = s.encode('utf8')
b = s.encode('iso-8859-2')
  • Standard UTF-8, zwracany typ: ciąg bajtów
>>> type(u)
<class 'bytes'>  # ciąg bajtów
>>> u
b'\xc5\x82\xc3\xb3d\xc5\xba'
>>> len(u)   # 4 znaki, w tym 3 dwubajtowe i 1 jednobajtowy
7
  • Standard ISO-8859-2, zwracany typ: ciąg bajtów
  • Konwersja niejawna nie może nie może być wykonana, jeśli nie znamy kodowania źródłowego. Funkcją do sprawdzenia kodowania źródłowego jest string.decode('standard_kodowania')
>>> s + u
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bytes' object to str implicitly

>>> s + u.decode('utf8')
'łódźłódź'

Konwersja dowolnego typu do string można wykonać na dwa sposoby za pomocą funkcji 'built-in':

  • str()
    • funkcja print natomiast korzysta z 'str'
  • repr()
    • wypisywanie w interpreterze to odpowiednik 'repr' Często str() i repr() zwracają takie same wyniki, ale dla niektórych typów danych są różnice
>>> str(a), repr(a)                              
('234', '234')                                    
>>> str(b), repr(b)                               
('abc', "'abc'")

Formatowanie stringów. Może odbywać się na dwa sposoby:

  • z wykorzystaniem operatora '%'
>>> '%s ma %s' % ('ala', 'kota')
'ala ma kota'
>>> 'liczba: %10d' % 15
'liczba:         15'
>>> '%.2f' % math.pi
'3.14'
>>> print('To jest linia nr %d\na to jest %s linia' % (1, 'druga'))
To jest linia nr 1
a to jest druga linia
  • z wykorzystaniem funkcji format()
>>> '{} ma {}'.format('ala', 'kota')
'ala ma kota'
>>> '{0} ma {1}, więc {1} ma {0}'.format('ala', 'kota')
'ala ma kota, więc kota ma ala'

>>> '{0!r} ma {1!s}'.format('ala', 'kota')  # użyj 'repr' dla 'ala', a 'str' dla 'kota'
"'ala' ma kota"

b)

>> '%d%d' % (b,a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: %d format: a number is required, not str

Jeśli wyrażenie wyrzuca błąd, na kolokwium piszemy ogólnie że wyrzuciło wyjątek, nie trzeba dookreślać szczegółów. Poprawne wyrażenie wyglądałoby tak :

>> '%s%s' % (b,a)
>> 'kotala'

Zadanie 3. List comprehension

[x for x in a if x not in b]

Opis : wyrażenie zwróci wszystkie x, które występują w zbiorze a i jednocześnie nie wystepują w zbiorze b

[<wyrażenie> for <zmienna> in <obiektIterowalny> if <warunek>]

Element for może wystąpić raz lub więcej razy. Element if może nie wystąpić wcale lub wystąpić raz lub więcej razy.

# wszystkie pary liczb dla a należącego do krotki (1, 2, 3) i b należącego do krotki (1, 2)
>>> [(a, b) for a in (1, 2, 3) for b in (1, 2)]
[(1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2)]

>>> ['kot'+x for x in ('ara', 'eria', 'let')]
['kotara', 'koteria', 'kotlet']

# if pozwala na filtrowanie listy
# warunek musi wystąpić po wyrażeniu 'for' z nazwą zmiennej
# poniższe wyrażenie nie zadziała!
>>> [(x, y) for x in range(1,10) if x != y for y in range(1,10) if x % y == 0 if y != 1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
UnboundLocalError: local variable 'y' referenced before assignment

# Wyrażenia można zagnieżdżać:
# zwróć wszystkie liczby x, które podniesione do dowolnej potęgi od 1 do 10 dają 1024
>>> [x for x in range(100) if 1024 in [x**k for k in range(1, 11)]]
[2, 4, 32]

Zadanie 4. Działania na listach

>> a = b = (1,)
>> a += a
>> a
a = (1, 1)

Zadanie 5. Funkcje

a)

def a(y):
   y += 1
   print(y)

Wywołanie funkcji

>> x = 2
>> a(x) 
>> 3

b)

 def a(x = y):
    x += 1
    print(x)

Wywołanie funkcji


## Zadanie 1. 
>> a(y)
>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined

Opis: wyrzuci wyjątek, ponieważ wartość y niezdefiniowana

6. Pliki

>> f = open('file.txt', 'r')  # zamiast 'r' może być 'w' dla zapisu
>> f.read()
'pierwsza linia\ndruga linia\na na koniec: gżegżółka\n'
>> f.read(20)
'pierwsza linia\ndruga'
>> f.seek(0)  # przesunięcie kursora na początek pliku
>> f.close()

Metoda f.readlne() pozwala odczytać jedną linię z pliku. f.readlines() Umieszcza każdą linię w osobnym elemencie w liście.

Można także odczytywać plik w pętli:

for line in f:
    print(line)

Zapis do pliku wymaga otwarcia go w trybie 'w'.

>> f = open('file.txt', 'w')
>> f.write('Napis')
>> f.close()

>> f = open('file.txt', 'r')
>> f.read()
'Napis'
>> f.close()

7. Argumenty funkcji

Najpierw podajemy argumenty pozycyjne, następnie w dowolnej kolejności argumenty przekazywane przez słowa kluczowe i listę argumentów (*), a na koniec słownik argumentów.

Argumenty pozycyjne

>>> def print3(a, b, c):
...    print(a, b, c)
>>> print3(1, 2, 3)
1 2 3

Argumenty przekazywane przy pomocy słów kluczowych

>>> print3(a=1, b=2, c=3)
1 2 3

# kolejność argumentów nie ma teraz znaczenia
>>> print3(b=2, a=1, c=3)
1 2 3

# można łączyć argumenty pozycyjne i słowa kluczowe
>>> print3(1, c=3, b=2)
1 2 3

# Argumenty przekazywane przez slowa kluczowe muszą wystąpić na końcu 
i nie mogą się powtarzać ani przesłaniać argumentów pozycyjnych. 
>>> print3(1, b=2, 3)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

Argumenty przekazywane przez listę argumentów pozycyjnych

>>> args = [1, 2]
>>> args.append(3)
>>> print3(*args)
1 2 3
>>> print3(*[1, 2, 3])
1 2 3
>>> print3(*(1, 2, 3))
1 2 3
>>> print3(*range(1,4))
1 2 3
# Lista argumentów uzupełnia argumenty pozycyjne przekazane w konwencjonalny sposób 
i musi wystąpić po nich.
>>> print3(1, *[2, 3])
1 2 3
# Argumenty przekazywane przez słowa kluczowe mogą wystąpić po liście argumentów lub przed nią, 
lecz lista jest zawsze brana pod uwagę jako pierwsza.
>>> print4(1, d=2, *[3, 4])
1 3 4 2
>>> print4(1, *[2, 3], d=4)
1 2 3 4

Argumenty przekazane przez słownik

Słownik argumentów musi znaleźć się w wywołaniu za pozostałymi argumentami, ponieważ uzupełnia wszystkie poprzednie argumenty.

>>> args = {'a': 1, 'd': 4}
>>> args['b'] = 2
>>> args.update({'c':3})
>>> args
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> print4(**args)
1 2 3 4

# Uwaga na częsty błąd!
>>> print4(*args)
a c b d

Funkcja wywołująca dowolną przekazaną funkcję z podanymi argumentami

def call(function, args, kw_args):
    return function(*args, **kw_args)

Pobieranie argumentów przez funkcję

Najpierw definiujemy argumenty pozycyjne, następnie argumenty z wartościami domyślnymi, w dalszej kolejności nazwę krotki poprzedzoną '*', a na koniec nazwę słownika. Funkcja wykorzystująca zwykłe argumenty, wartości domyślne, krotkę i słownik (najtrudniejszy przypadek!)

>>> def all_in_one(a, b=2, *args, **kw_args):
...     print(a, b, args, kw_args)

>>> all_in_one(1)
1 2 () {}
>>> all_in_one(1, 22)
1 22 () {}
>>> all_in_one(b=22, *[1])
1 22 () {}
>>> all_in_one(1, x=5)
1 2 () {'x': 5}
>>> all_in_one(1, x=5, b=4)
1 4 () {'x': 5}
>>> all_in_one(*['a', 'b'], **{'x':58})
a b () {'x': 58}
>>> all_in_one(1, *['a', 'b'], **{'x':58})
1 a ('b',) {'x': 58}
>>> all_in_one(1, 2, *['a', 'b'], **{'x':58})
1 2 ('a', 'b') {'x': 58}
>>> all_in_one(1, 2, y=5, *['a', 'b'], **{'x':58})
1 2 ('a', 'b') {'y': 5, 'x': 58}

8. Wyrażenia lambda (tworzy nienazwaną funkcję, która wylicza jego wyrażenie i podaje wartość)

Konstrukcja

lambda <argumenty>: <wyrażenie>

```python
>>> l = lambda a: 2*a
>>> l('abc')
'abcabc'

>>> l = lambda a=3, b=4: a*b
>>> l(b='kot')
'kotkotkot'

>>> l = lambda *args, **kw_args: (args, kw_args)
>>> l(1, d=4, *[2], **{'c':3})
((1, 2), {'c': 3, 'd': 4})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment