Python – podstawy...

Post on 27-Feb-2019

275 views 1 download

Transcript of Python – podstawy...

Python – podstawy programowaniaKurs w ramach przedmiotu: Symulacja komputerowa systemów

dr inż. Krzysztof Czarnecki

Politechnika GdańskaKatedra Systemów Elektroniki Morskiej

20 listopada 2015

Plan

Słowo wstępu

Ogólnie o typowaniu

Instrukcje sterujące

Programowanie obiektowe – interfejs do obiektu

Moduły zewnętrzne

Wybrane operacje na plikach

Obsługa wyjątków

Wykres dyskretnej funkcji jednej zmiennej

Przetwarzanie wektorów, macierzy

Analiza widmowa sygnału

Generacja addytywnego szumu białego (AWGN)

Generacja sygnału świergotowego

Symulacja transmisji danych w paśmie podstawowym

Programowanie obiektowe w służbie SKS

Zakres kursu, popularność Pythona

• Niniejszy kurs obejmuje wybrane zagadnienia języka Python.

• Wspólnym mianownikiem wszystkich prezentowanych tu zagadnień jestimplementacja komputerowej symulacji systemów, zwłaszcza analizy i przetwarzaniasygnałów, oraz graficzna prezentacja zobrazowań.

• Elastyczność, wieloplatformowość, dość prosta składnia, ogromna liczbadodatkowych modułów oraz fakt, iż język Python jest udostępniany na wolnej licencjisprawia, że język ten jest jednym z najpopularniejszych języków programowania.

www.codeeval.com, spectrum.ieee.org

Instalacja interpretera języka Python

Instalacja w systemie Linux

I należy wydać następujące polecenie w terminalu:apt-get install python3 (Ubuntu, Mint)yum install python3 (Fedora)... (inne Linuksy)

Instalacja w systemie Windows

I należy ściągnąć najnowszą wersję (≥ 3.3.0) instalatora zestrony projektu:www.python.org/download/i postępować zgodnie z instrukcjami.

Wybór zintegrowanego środowiska programistycznegoIDE: ang. Integrated Development Environment

• Do oddzielenia bloków kodu stosuje się wcięcia tabulatora. Dlatego zaleca sięstosowanie zaawansowanych edytorów, które będą zapewniały, aby komunikatIndentationError: unexpected indent pojawiał się jak najrzadziej.

• Często stosowane IDE / edytory:I PyCharmI IDLE PythonI Emacs, VimI Notepad++I Eclipse

skrypt-1.py

1 # blok 1x = 1

3 print("x =", x)if True: # po dwukropku następuje blok ,,podrzędny ’’

5

# blok 27 y, z = 2, 3

print("x + y + z =", x+y+z)

Uruchomienie skryptu

Skrypt napisany w języku Python powinien rozpoczynać się od wskazaniapołożenia interpretera w systemie plików oraz wyboru kodowania tekstu.Informacje te przekazuje się w dwóch pierwszych liniach skryptujako komentarze:

skrypt-2.py

1 #!/usr/bin/python# -*- coding: utf -8 -*-

Skrypt można uruchomić za pośrednictwem powłoki (Linux, Unix):bash

python skrypt -2.py

lub po nadaniu praw do wykonywania, bezpośrednio (Linux, Unix):bash

1 chmod a+x skrypt -2.py./skrypt -2.py

IDE m.in. udostępniają intuicyjne interfejsy do uruchamiania skryptów.

(Linux, Windows, ...)

”Hello world!”

• W języku Python deklaracja zmiennej odbywa się automatycznie przy jej inicjacji.Co więcej nie trzeba troszczyć się o usuwanie niepotrzebnych zmiennych i obiektów,gdyż interpreter Pythona jest wyposażony w tzw. garbage collector.

• Wybrane popularne typy danych to int, float i string.

skrypt-3.py

x = "Hello world!" # inicjacja zmiennej typu string2 y = 2014 # inicjacja zmiennej typu intz = 2014.0 # inicjacja zmiennej typu float

4

print( x, type(x))6 print( y, type(y))print( z, type(z))

8

# konwersja typu , rzutowanie10 a = str (2014)b = float("2014.0")

12 c = int(z)

14 print( a, type(a))print( b, type(b))

16 print( c, type(c))

Instrukcja warunkowa

Instrukcja warunkowa:I musi składać się z jednej klauzuli if, po której następuje test logicznyI może zawierać dowolną liczbę klauzul elif, po których następują testy logiczneI może zawierać klauzulę else

skrypt-4.py

1 # instrukcja warunkowa ,,wbudowana ’’print("x exists" if "x" in vars() else "x doesnt exist")

3

# rozbudowana instrukcja warunkowa5 if not "x" in vars(): passelif type(x)==type(float()): print("x is float")

7 elif type(x)==type(int()): print("x is int")else:

9 print("unexpected type")del(x)

• Jeżeli blok kodu pod klauzulą zawiera tylko jedną instrukcjęto może ona być umieszczona bezpośrednio po dwukropku.• wbudowana funkcja vars() zwraca zbiór istniejących zmiennych.

• in służy do testowania czy obiekt znajduje się w zbiorze.• Instrukcja pusta może być wywołana poleceniem pass.• Można wymusić usunięcie obiektu poleceniem del.

• not to zaprzeczenie logiczne.

Wybrane tablicowe typy danych• Tablicowe typy danych collections są szczególnie istotne dla niniejszego kursu, zracji możliwości wyrażania sygnałów dyskretnych za ich pomocą. Trzy częstospotykane to napisy (string), listy i krotki (tuple). Odwołania do poszczególnychelementów takich zmiennych można dokonać przy pomocy nawiasów kwadratowych.

skrypt-5.py

A = "1234" # inicjacja napisu2 B = (1, 2, 3, 4) # inicjacja krotkiC = [1, 2, 3, 4] # inicjacja listy

4

print(A, B, type(B), C, type(C))6 print(A[2], B[1:3], C[-2])

• Krotki i listy mogą przechowywać obiekty dowolnego typu.• Ponadto, z wymienionych, tylko listy mają możliwość przypisania wartości doposzczególnych elementów niezależnie, czym różnią się od krotek i napisów.

skrypt-6.py

1 L = ["Adam", ("Ewa", 2014), 2014.0]print(L[0][0:3] , "i " + L[1][0]) # "Ada i Ewa"

3

L[2] = "Ola"5 L[1][1] = "Ela" # tu interpreter zgłosi błąd

TypeError: ’tuple’ object does not support item assignment

Pętla for

• Pętla for przeznaczona jest do iterowania po danych typu tablicowego.• Instrukcje continue oraz break można stosować podobnie jak w języku C.

skrypt-7.py

Vips = ["Asia", "Ania", "Helena", "Ela", "Ola", "Ala"]2 for imie in Vips:

if imie == "Ania": continue # pominięcie iteracji4 if imie == "Ela": break # przerwanie pętli

for litera in imie: print(litera) # pętla zagnieżdżona6 print()

• Przykład wykorzystania pętli generującej listę (inline) do utworzenia osi czasu:

skrypt-8.py

1 rate = 1000.0 # próbki na sekundęinterval = 0.8 # interwał w sekundach

3 number = int(rate * interval)

5 # Lista przechowująca dyskretne wartości czasuTimeline = [float(n) / rate for n in range(number)]

7 print(Timeline)

• Wbudowana funkcja range() zwraca listę kolejnych liczb naturalnych.

Licznik pętli• Co jeżeli potrzebny jest licznik w pętli?

skrypt-9.py

Vips = ["Asia", "Ania", "Helena", "Ela", "Ola", "Ala"]2

# tu pętle for da się zmieścić w 1 czytelnej linii kodu4 for nr, imie in enumerate(Vips):

print("element %d to vip %s" % (nr , imie))6

nr = 0 # tu niezbędne są 4 linie8 while(nr<len(Vips)):

print("element %d to vip %s" % (nr , Vips[nr]))10 nr += 1

• Wbudowana funkcja enumerate() zwraca listę (dokładniej generator) krotek, którychpierwszy element to indeks, a drugi przyjmuje zawartość oryginalnego elementu listy.• Wbudowana funkcja len() zwraca długość kolekcji.

• Przy pierwszej pętli mamy niejawnie do czynienia z wielokrotnym przypisaniem.skrypt-9.py

1 nr, imie = 0, "Asia" # wielokrotne przypisanienr, imie = (1, "Ania") # rozpakowanie krotki

3 nr, imie = [2, "Helena"] # rozpakowanie listy

• Uwaga na ValueError: too many values to unpackValueError: need more than 2 values to unpack

True i False

• W Pythone dostępne są typy binarne określone słowami kluczowymi True i False. Sąwykorzystywane m.in. w testach logicznych przez instrukcje warunkowe oraz pętle.• Fałsz logiczny poza zmienną False wyrażają także m.in.:

I Zaprzeczenie logiczne prawdy: not TrueI Wyrażenie None, reprezentujące brak wartości.I Zmienna typu float przyjmująca wartość 0.0.I Zmienna typu int przyjmująca wartość 0.I Puste krotka, lista lub napis: ( ), [], ””

skrypt-10.py

1 Vips = ["Asia", "Ania", "Helena", "Ela", "Ola"]print(Vips)

3

while(Vips):5 print(Vips [0])

del(Vips [0])7 print(Vips)

• Do konstruowania testów logicznych służą m.in. następujące operatory:and, or, not, in.

• Uwaga na IndexError: list assignment index out of range

Obiekty

• Język Python wspiera wszystkie najważniejsze paradygmaty programowania, w tymrównież paradygmat programowania obiektowego, w którym do opisu programustosuje się abstrakcyjne obiekty wyposażone w specjalny interfejs.

• Do poszczególnych atrybutów obiektu (pól, metod, innych zagregowanych obiektów)można odwołać się za pomocą operatora kropki.

skrypt-11.py

Vips = ["Asia", "Ania", "Helena", "Ela", "Ola"]2 print(Vips)

4 # metoda append () powoduje dołączenie# do końca listy kolejnego elementu (napisu)

6 Vips.append("Ala")print(Vips)

• Do wylistowania wszystkich atrybutów obiektu służy wbudowana funkcja dir().

skrypt-11.py

print(dir(Vips))

• Również zmienne typu int, float oraz string są obiektamiw rozumieniu paradygmatu programowania obiektowego.

Lista jako „obiekt”

skrypt-12.py

Vips = ["Asia", "Ania", "Helena", "Ela", "Ola"]2 More_Vips = ["Ala", "Ula"]

4 # Metoda extend () powoduje rozszerzenie listy o inną listę.Vips.extend(More_Vips)

6 print(Vips)

8 # Metoda pop(n) powoduje pobranie i zwrócenie elementu# o numerze n z listy. Element jest usuwany z listy!

10 imie = Vips.pop (2)print(imie , Vips)

12

# Bez podawania jawnie argumentu metody pop()14 # domyślnie zostanie pobrany ostatni element listy.imie = Vips.pop()

16 print(imie , Vips)

18 # Metoda index zwraca numer pierwszego elementu ,# którego wartość jest równa argumentowi.

20 print(Vips.index("Ela"))

Metoda, funkcja, procedura...

• Funkcje definiowane jako wewnętrzne procedury obiektów nazywa się metodami.• Metody wywołuje się na obiektach, tak jak pokazano to na poprzednim slajdzie.• Funkcje, w tym także metody, definiuje się zwykle za pomocą słowa kluczowego def.

skrypt-13.py

1 def my_cmx(x, y): return x+1j*y

3 print(my_cmx (1.5, 3.5))

• Funkcje można definiować z domyślnymi wartościami argumentów. Należy przy tympamiętać, aby argumenty z przypisanymi domyślnymi wartościami były umieszczane nakońcu sygnatury (poniżej y=0 występuje po x).

skrypt-13.py

1 def my_cmx(x, y=0):if not isinstance(x, (int , float)): return None

3 if not isinstance(y, (int , float)): return Nonez = complex(x, y)

5 return z

7 print(my_cmx (1.5))print(my_cmx(y=2, x=1))

• Wbudowaną funkcję isinstance() użyto, aby sprawdzić czy przekazane argumentymają charakter numeryczny.

Moduły rozszerzeniowe• Język Python jest językiem ogólnego przeznaczenia, którego funkcjonalność możnarozszerzać przy pomocy dodatkowych modułów.• Dodatkowe moduły można dołączać za pomocą słowa kluczowego import.• Interfejs do zaimportowanego modułu jest spójny z interfejsem klasycznego obiektu.

skrypt-14.py

1 import sys # importowanie całego modułu sys

3 print(dir(sys)) # lista wszystkich elementów modułu sysprint(sys.argv) # linia wywołująca ten skrypt

• Moduły wspierające obliczenia, takie jak math, są szczególnie istotne dla tego kursu.skrypt-15.py

rate , interval , freq = 1000.0 , 1.2, 100.0 # Sa/s, s, Hz2 number = int(rate * interval)Timeline = [float(n) / rate for n in range(number)]

4

# import alternatywny za pomocą struktury ,,from import ’’6 from math import pi, sin , cosdef my_cmx(t, f, a=1):

8 arg = 2.0*pi*t*freturn complex(a*cos(arg), a*sin(arg))

10

# Wygenerowanie zespolonej sinusoidy:12 Complexoida = [my_cmx(t, freq) for t in Timeline]

Wybrane operacje na plikach

• Obsługa plików może przebiegać standardowo: otwarcie pliku, zapis lub odczyt orazzamknięcie pliku.

skrypt-16.py

1 Vector = range (16) # wygenerowanie danychfds = open("data.txt", "w") #otwarcie pliku do zapisu

3 for e in Vector:fds.write("%d\t %f\n" % (e, float(e))) # zapis do pliku

5 fds.close() # zamknięcie pliku

• Język python oferuje wygodną w użyciu strukturę with as, którą można wykorzystaćm.in. do obsługi plików.

skrypt-16.py

# otwarcie pliku do odczytu:2 with open("data.txt", "r") as fds:

# wczytanie danych do listy:4 Lines = fds.readlines ()

6 # wyświetlenie danych z pliku:for line in Lines: print(line , end="",flush=True)

• Plik został zamknięty automatyczniepo opuszczeniu bloku kodu w strukturze with as.

Wygenerowanie i zapisanie sygnału do pliku

• Moduł cmath jest dedykowany do wsparcia obliczeń z liczbami zespolonymi.• Wbudowana funkcja zip() łączy ze sobą dwa obiekty typu tablicowego na zasadzie„zamka błyskawicznego”, w ten sposób powstaje nowa lista, której elementami sąkrotki przechowujące odpowiadające sobie elementy z łączonych tablic. Jeżeli tablicemają różne rozmiary, to nieprzystające elementy z dłuższej tablicy są ignorowane. Takimechanizm wykorzystano w listingu poniżej:

skrypt-17.py

rate , interval , freq = 1000.0 , 1.2, 100.0 # Sa/s, s, Hz2 number = int(rate * interval)Timeline = [float(n) / rate for n in range(number)]

4

# Wygenerowanie zespolonej sinusoidy:6 from cmath import pi, rectComplexoida = [rect (1.0, 2*pi*t*freq) for t in Timeline]

8

# Zapis sygnału do pliku wraz z osią czasu:10 with open("signal.txt", "w") as fds:

for t,s in zip(Timeline , Complexoida):12 fds.write("%f\t%f\t%f\n" % (t,s.real ,s.imag))

Obsługa wyjątków

skrypt-18.py

1 try:# w pythonie 3 interpreter powinien zgłosić błąd

3 eval("print ’napis’")except SyntaxError:

5 print("błąd składni ...")

7 # nie zaleca się takiego sposobu programowania ,# gdyż właściwie uniemożliwia on debugowanie.

9 except:pass

11

def fun():13 try:

return x**215 except NameError:

print("brak x...")17 return

finally:19 print("finally ...")

21 fun()

Wykres y = f (x) - Pylab

• Modułem przeznaczonym do wizualizacji jest m.in. mathplotlib.bash

apt -get install python -matplotlib

skrypt-19.py

rate , interval , freq = 1000.0 , 0.05, 50.0 # Sa/s, s, Hz2 number = int(rate * interval)Timeline = [float(n) / rate for n in range(number)]

4

# Wygenerowanie zespolonej sinusoidy:6 from cmath import pi, rectComplexoida = [rect (1.0, 2*pi*t*freq) for t in Timeline]

8

# listy nie wspierają operacji macierzowych10 def get_real(Tab): return [s.real for s in Tab]def get_imag(Tab): return [s.imag for s in Tab]

12

import pylab as pl # kolejny alternatywny sposób importu14 pl.plot(Timeline , get_real(Complexoida))pl.plot(Timeline , get_imag(Complexoida))

16 pl.show()

Wykres y = f (x) - Pylab

Operacje wektorowe – Numpy

• Moduł numpy wspiera m.in. obliczenia numeryczne, w tym oparte na przetwarzaniuliczb zespolonych i całych macierzy.

bash

1 apt -get install python -numpy

skrypt-20.py

from cmath import pi, rect2 import pylab as pl , numpy as np

4 rate , interval , freq = 1000.0 , 0.05, 50.0 # Sa/s, s, Hznumber = int(rate * interval)

6 Timeline = [float(n) / rate for n in range(number)]Complexoida = [rect (1.0, 2*pi*t*freq) for t in Timeline]

8

# konwersja listy do typu numpy.array10 Complexoida = np.array(Complexoida)

12 # numpy.array wspiera operacje na całych macierzachpl.plot(Timeline , Complexoida.real)

14 pl.plot(Timeline , Complexoida.imag)pl.show()

Operacje wektorowe – Numpy

• Wbudowana funkcja map() może być szczególnie przydatna w przetwarzaniu list.• Pierwszym argumentem tej metody jest referencja do procedury przetwarzającejposzczególne elementy listy, natomiast drugim obiekt typu tablicowego.• Moduł numpy ma wbudowane mechanizmy przetwarzania całych macierzy, więc wwielu sytuacjach nie ma potrzeby stosowania funkcji map() lub pętli.

skrypt-21.py

import numpy as np , pylab as pl2

rate , interval , freq = 1000.0 , 0.05, 50.0 # Sa/s, s, Hz4 Timeline = np.arange (0.0, interval , 1.0/ rate)

6 # mnożenie macierzy przez wielkość skalarną: j 2 pi freq# i mapowanie jej wartości na funkcję numpy.exp():

8 Complexoida = map(np.exp , 2j*np.pi*freq*Timeline)Complexoida = np.array(Complexoida)

10

# ekwiwalentny zapis mógłby wyglądać następująco:12 Complexoida = np.exp(2j*np.pi*freq*Timeline)# numpy.exp() zwraca tu obiekt typu numpy.array

14

pl.plot(Timeline , Complexoida.real)16 pl.plot(Timeline , Complexoida.imag)pl.show()

Operacje wektorowe – Numpy

• Wbudowana funkcja abs() może działać różnie, przyjmując argumenty różnychtypów 1. Gdy jako argument zostanie podany obiekt typu numpy.array, w wynikuotrzymamy obiekt również tego typu.

skrypt-22.py

import numpy as np , pylab as pl2

rate , interval , freq = 1000.0 , 0.05, 50.0 # Sa/s, s, Hz4 Timeline = np.arange (0.0, interval , 1.0/ rate)Complexoida = np.exp(2j*np.pi*freq*Timeline)

6

# przykładowe przetwarzanie macierzy8 Complexoida.real = abs(Complexoida.real/( Timeline +0.01))Complexoida.imag = Complexoida.imag*( Timeline *2000.0)

10

pl.plot(Timeline , Complexoida.real , "g")12 pl.plot(Timeline , Complexoida.imag , "b")pl.plot(Timeline , abs(Complexoida), "r")

14 pl.grid()pl.show()

• Z klasycznej listy nie można obliczyć wartości bezwzględnej:TypeError: bad operand type for abs(): ’list’

1Funkcja abs wykorzystuje mechanizm metod specjalnych, które będą zaprezentowane w dalszej części.

Wykres y = f (x) - Pylab

Operacje macierzowe – Numpy

• Poniżej przedstawiono wybrane operacje na macierzach reprezentowanych obiektamitypu numpy.array.

skrypt-23.py

import numpy as np2

A = np.array([range (3**2) ])4 B = np.array([range (3*3)])C = A.reshape (9,1)

6 D = A.reshape (3,3)+1jprint("A =", A, "\nB =", B, "\nC =", C, "\nD =\n", D)

8

# Mnożenie macierzy. Uwaga na ValueError!10 print("\nA*B =\n", A*B) # Mnożenie macieży ement -elementprint("dot(A,C) =\n", np.dot(A,C)) # Mnożenie macierzy

12 print("dot(C,A) =\n", np.dot(C,A)) # Mnożenie macierzy

14 # Odwracanie macierzyprint("np.linalg.inv(D) =\n", np.linalg.inv(D))

16

# Transpozycja , sprzężenie i zmiana wymiarów macierzy18 print("A.transpose () =\n", A.transpose ())print("A.reshape (3,3) =\n", A.reshape (3,3))

20 print("D.conj().transpose () =\n", D.conj().transpose ())

Analiza widmowa sygnałuskrypt-24.py

from numpy import pi, exp , arange2 rate , interval = 1000.0 , 0.1 # Sa/s, sTimeline = arange (0.0, interval , 1.0/ rate)

4

# generacja sygnału6 f1, f2 , a1 , a2 = 100.0 , 200.0, 1.0, 0.1w1, w2 = 2.0*pi*f1 , 2.0*pi*f2 # rad/s

8 Signal = a1*exp(1j*w1*Timeline)+a2*exp(1j*w2*Timeline)

10 #analiza widmowafrom numpy import log10 , blackman

12 from numpy.fft import fft , fftshiftSpectrum = fftshift(fft(Signal*blackman(len(Signal))))

14 Spectrum = Spectrum/max(abs(Spectrum)) # normalizacjaFreqline = arange(-rate/2, rate/2, rate/len(Spectrum))

16

# ekspozycja w skali logarytmicznej18 import pylab as plpl.plot(Freqline , 20* log10(abs(Spectrum)),".-")

20 pl.xlabel("F (Hz)")pl.ylabel("E (dBc)")

22 pl.grid()pl.show()

Widmo amplitudowe w skali logarytmicznej

Generacja addytywnego szumu białego –– symulacja kanału AWGN

skrypt-25.py

# obliczenie parametru sigma2 from numpy import log10 , sqrt , meansnr = -20 # Założony SNR w dB

4 length = len(Signal)average = mean(Signal)

6 power = sum(abs(Signal -average)**2) / lengthsigma = sqrt(power *10**( - snr /10) /2) # poprawione względem

wykladu 18 X 20158

# losowanie próbek szumu10 from numpy.random import normalNoise = normal(loc=0.0, scale=sigma , size=(length ,2))

12 NSignal = [s+complex (*n) for s,n in zip(Signal ,Noise)]

14 print("Assumed SNR:", snr)signal_enery = sum(abs(Signal)**2)

16 noise_enery = sum(k**2 for n in Noise for k in n)print("Obtained SNR:", 10* log10(signal_enery/noise_enery))

Assumed SNR: 20Obtained SNR: 20.031579662

Widmo amplitudowe w skali logarytmicznej –– analiza fragmentu sygnału długości 0.1 sekundy

Widmo amplitudowe w skali logarytmicznej –– analiza fragmentu sygnału długości 2.2 sekundy

Generacja sygnału świergotowego (chirp)

skrypt-26.py

1 from numpy import pi, exp , arangerate , interval = 1000.0 , 1.1 # Sa/s, s

3 Timeline = arange (0.0, interval , 1.0/ rate)

5 # generacja sygnału chirpf, a, c = 10.0, 2.0, 120.0

7 w = 2.0*pi*f # rad/sSignal = Timeline*exp(1j*(w*Timeline + pi*c*Timeline **2))

skrypt-26.py

import pylab as pl2 pl.figure("Sygnał Świergotowy")pl.subplot (211)

4 pl.plot(Timeline , Signal.real ,"b-")pl.xlabel("T (s)")

6 pl.ylabel("Real (V)")pl.grid()

8 # ...

Sygnał świergotowy

Widmo amplitudowe sygnału świergotowego

Spektrogram sygnału świergotowego (chirp)

skrypt-26.py

1 # ...pl.figure("Widmo Amplitudowe")

3 pl.plot(Freqline , 20* log10(abs(Spectrum)),"b.-")pl.xlabel("F (Hz)")

5 pl.ylabel("E (dBc)")pl.grid()

skrypt-26.py

pl.figure("Spectrogram")2 pl.specgram(Signal , NFFT =128, Fs=rate , noverlap =127)pl.ylim([0, 150])

4 pl.xlim([0, 1])pl.xlabel("T (s)")

6 pl.ylabel("F (Hz)")pl.grid()

8 pl.show()

Spektrogram sygnału świergotowego

Symulacja transmisji danych w paśmie podstawowymskrypt-28.py

1 # Wiadomość do przesłania.Data = "To jest przesyłana informacja w kodzie ASCII."

3

# Ignorowanie wszystkich znaków nie należących do kodu ASCII.5 Data = Data.encode("ascii",’ignore ’)

7 # Przetwarzanie litera po literze.for letter in Data:

9

# Zapewnienie jednakowej długości ramek (8 bitów).11 Tab = list(bin(letter)) # konwersja ’char to bin as list’

Frame = (10-len(Tab))*[0]13 for b in Tab [2:]: Frame.append(int(b)) # pierwsze dwie

# pozycje reprezentacji binarnej np. 0b10011 są ignorowane15

# Formowanie strumienia danych binarnych17 try: Stream += Frame # unipolarnych (0,1)

except NameError: Stream = Frame19

print("Nadano: ", Data)

• Dalej następuje mapowanie symboli – w tej konkretnej sytuacji konwersja koduunipolarnego (0,1) do bipolarnego (1, -1)

Symulacja transmisji danych w paśmie podstawowym- dekodowanie

skrypt-28.py

1 # Dekodowanie.RecStream = Stream

3

# analiza bit po bicie5 while RecStream:

7 frame = ""while len(frame) <8: # wydzielanie 8-bitowych ramek

9 frame += str(RecStream.pop(0))

11 char = chr(int(frame , 2)) # konwersja ’bin to int to char’

13 # utworzenie łańcucha znaków:try: RecData += char

15 except NameError: RecData = char

17 print("Odebrano: ", RecData)

Symulacja transmisji danych w paśmie podstawowym- filtr formujący

czas, t

czas, t

wstawianie zerowych próbek

odpowiedź impulsowa filtru

opóźnienie, τ

-

splot = filtracja

czas, t

Symulacja transmisji danych w paśmie podstawowym- filtr formujący

Symulacja transmisji danych w paśmie podstawowym- symulacja kanału AWGN

Symulacja transmisji danych w paśmie podstawowym- filtr dopasowany

odpowiedź impulsowa filtru

opóźnienie, τ

-

splot = filtracja

czas, t

czas, t���@

@@�

��@

@@

@@@���

���@

@@

Symulacja transmisji danych w paśmie podstawowym- filtracja i synchronizacja po stronie odbiorczej

Symulacja transmisji danych w paśmie podstawowym- analiza widmowa nadawanego sygnału

Symulacja transmisji danych w paśmie podstawowym- analiza widmowa dłuższej wiadomości

Symulacja transmisji danych w paśmie podstawowym- charakterystyka amplitudowa filtru

Symulacja transmisji danych w paśmie podstawowym

Nadano: b’informacja’Uzyskany SNR: 3.27185103433 dBOdebrano (bez filtracji): hntovmqghaOdebrano (po filtracji): informacjaSNR Po filtracji: 9.93855656284 dB

Klasa jako definicja typu obiektuskrypt-31.py

1 class Box: # instrukcja class rozpoczyna definicję klasy

3 def __init__(self): # metoda implementująca konstruktor# argument self jest obowiązkowy

5 # oznacza odwołanie do instancji tej klasyprint("New box")

7 self.content = [] # zmienna wewnątrz klasy , poleself.name = "box"

9

def print_name(self): # metoda wyświetla imię11 print(self.name)

13

box1 = Box() # utworzenie obiektu według opisu klasy15 print(type(box1))print(type(Box))

17 print(dir(box1))

19 box1.print_name ()print(box1.name)

21

print_box1_name = box1.print_name23 print_box1_name ()

Dziedziczenieskrypt-32.py

class Box: # konstruktor z dodatkowym argumentem:2 def __init__(self , name):

print("New box: %s" % name)4 self.name = name

self.content = []6

def print_name(self): print(self.name)8

class BetterBox(Box): # nowa klasa dziedziczy po klasie Box10 def add(self , item):

self.content.append(item)12 def print_content(self):

print(self.content)14

box2 = BetterBox("czarna")16 box3 = BetterBox("czerwona")box3.print_name () # print_name z klasy Box

18

box2.print_content ()20 box2.add(box3) # content zdefniowano jako lista więc możnabox2.add("czapka") # tu dodać, w zasadzie , dowolny obiekt

22 box2.print_content ()

Dziedziczenie po wielu klasachskrypt-33.py

1 class Contener: # pierwsza klasa nadrzędnadef __init__(self):

3 self.content = []def add(self , item):

5 self.content.append(item)def print_content(self):

7 print(self.content)

9 class Caller: # druga klasa nadrzędnadef __init__(self , name):

11 self.name = namedef print_name(self):

13 print(self.name)

15 class Box(Contener , Caller):def __init__(self , name):

17 Contener.__init__(self)Caller.__init__(self , name)

19 print("New box: ", end=""); self.print_name ()

21 box = Box("szary")box.add("szalik")

23 box.print_content ()print(type(box), isinstance(box ,Caller), isinstance(box ,int))

Diagram klas

Contener

◦ add()

◦ print content()

= content

Caller

◦ print name()

- name

Box@

@@@I

�����

Dziedziczenie po wielu klasach- rozwiązywanie kolizji

skrypt-34.py

1 class Box_A: # pierwsza klasa nadrzędnadef add(self , item):

3 print("Add A")self.content.append(item)

5

class Box_B: # druga klasa nadrzędna7 def add(self , item):

print("Add B")9 self.content.append(item)

11 class Box(Box_A , Box_B):def __init__(self):

13 self.content = []

15 box = Box()box.add("item") # jeżeli następuje kolizja

spowodowana wykorzystaniem takich samychnazw , to dziedziczenie pól lub metod następuje z tej klasy przekazanej jako argumentbardziej po lewej stronie

Dziedziczenie - funkcja super

skrypt-35.py

class Box(object): # dziedziczenie po object nie jest2 # wymagane w pythonie3 , aby kod był

# zgodny z ’nowym stylem ’ pythona4

def __init__(self):6 self.content = []

8 def add(self , item):print("Add in Box")

10 self.content.append(item)

12 class BetterBox(Box):def add(self , item):

14 print("Add in BetterBox")super().add(item)

16

bbox = BetterBox ()18 bbox.add("rękawiczki")print(bbox.content)

Złe (??) użycie polaskrypt-36.py

class Contener:2 def add(self , item): self.content.append(item)

def print_content(self):4 print(self.name , ":", self.content)

6 class BadBox(Contener):content = [] # pole będzie wspólne dla wszystkich

8 # instancji BadBox (objektów klasy BadBox)def __init__(self , name): self.name = name

10

bbox1 ,bbox2 = BadBox("czerwony"),BadBox("niebieski")12

bbox1.add("czerwone rękawiczki")14 bbox1.add("czerwona czapka")bbox2.add("niebieski szalik")

16

bbox1.print_content ()18 bbox2.print_content ()

20 class GoodBox(Contener): # deklaracja klasy może wystąpićdef __init__(self ,name): # właściwie w dowolnej części

22 self.content = [] # skryptuself.name = name

Polimorfizm na przykładzie skrzynekskrypt-37.py

class Box:2 def __init__(self): self.content = []

def add(self , item): self.content.append(item)4 def print_content(self): print(self.content)

6 class DoubleBox:def __init__(self):

8 self.content_1 ,self.content_2 = [],[]def print_content(self):

10 print(self.content_1 + self.content_2)def add(self , item , nr=1):

12 if nr==1: self.content_1.append(item)elif nr==2: self.content_2.append(item)

14

# lista różnych typów skrzynek:16 Boxes = [Box(), DoubleBox (), Box()]Items = ["szalik", "czapka", "mazak", "klawiatura", "kubek"]

18

from random import randint20 for item in Items: # polimorfizm , gdy dodajemy do skrzynki

Boxes[randint (0,2)].add(item)22

for box in Boxes: box.print_content () # oraz przy wyświetlaniu

Funkcje specjalne w Pythonie - len()

skrypt-38.py

class Box:2 def __init__(self):

self.content = []4

def add(self , item):6 self.content.append(item)

8 # ta metoda zostanie wywołana , gdy# interpreter wykona funkcję len():

10 def __len__(self):print("Checking len...")

12 return len(self.content)

14 box = Box()print(len(box))

16

box.add("Asia")18 box.add("Ula")box.add("Ola")

20 print(len(box))

Funkcje specjalne w Pythonie - konstruktor i dekonstruktor

skrypt-39.py

1 class Box:

3 # konstruktor to również metoda specjalna:def __init__(self):

5 self.content = []print("Nowa skrzynka ...")

7

# dekonstruktor jest wywoływany zawsze ,9 # gdy obiekt jest usuwany z pamięci

def __del__(self):11 print("Niszczenie skrzynki ...")

13 box1 = Box()del(box1)

15 box2 = Box()print("Komunikat ...")

Porównywanie obiektów

• Do implementacji sposobu porównywania dwóch obiektów służy następująca grupafunkcji specjalnych: cmp (self, inny), lt (self, inny), le (self, inny), eq (self,inny), ne (self, inny), gt (self, inny), ge (self, inny).• Można zdefiniować sposoby konwersji obiektu do znanego typu przy pomocy takichfunkcji specjalnych: int (self), str (self), float (self), complex (self)...• Słowo kluczowe is służy do sprawdzenia czy dwie referencje odwołują się do tegosamego obiektu.

skrypt-40.py

1 class Box:

3 def __init__(self):self.content = []

5

def add(self , item):7 self.content.append(item)

9 def __eq__(self , obj):if not hasattr(obj , "content"):

11 return Falseelif len(self.content) == len(obj.content):

13 return Trueelse:

15 return False

Porównywanie obiektów

skrypt-40.py

box1 , box2 = Box(), Box()2 box3 = box2

4 box1.add("telefon")

6 if box1 is box3: print("box1 i box3 to ten sam box")else: print("box1 i box3 to inne boxy")

8

if box2 is box3: print("box2 i box3 to ten sam box")10 else: print("box2 i box3 to inne boxy")

12 if box1 == box3: print("box1 i box2 mają po tyle samoprzedmiotów")

else: print("box1 i box2 nie mają po tyle samo przedmiotów")14

box3.add("plakat")16

if box1 == box3: print("box1 i box2 mają po tyle samoprzedmiotów")

18 else: print("box1 i box2 nie mają po tyle samo przedmiotów")

Symulacja wielomodułowego urządzenia

skrypt-41.py

1 class Dev: # klasa bazowa wszystkich modułówdef __init__(self , name):

3 self._name = str(name)print("New dev , called", self._name)

5

self._output = None7 self._input = None

self._buffer = []9

def __len__(self):11 return len(self._buffer)

13 def connect(self , dev):if not isinstance(dev , Dev):

15 print(self._name , "Wrong type , cannot connect ...")else:

17 self._output = devdev._input = self

19 print(self._name , "->", dev._name , "conected ...")

21 def run(self): pass

Symulacja wielomodułowego urządzenia

skrypt-41.py

1 from random import randomclass Generator(Dev): # przykład klasy generatora

3 def run(self): self._buffer.append(random () -0.5)

5 class Converter(Dev): # przykład klasy konwerteradef run(self):

7 while len(self._input) >1:x = self._input._buffer.pop()

9 y = self._input._buffer.pop()self._buffer.append(complex(x ,y))

11

gen = Generator("gen")13 conv = Converter("conv")gen.connect(conv)

15

# symulacja pracy modułów17 for n in range (5): gen.run()conv.run()

19

print(gen._buffer)21 print(conv._buffer)

Dodatkowe informacje

Strona domowa autora tej prezentacji:http://eti.pg.edu.pl/af0526ca00 krzysztof.czarneckihttp://pta.eti.pg.gda.pl/people/krzycz/

Dodatkowe skrypty wykorzystane w tej prezentacji:http://pta.eti.pg.gda.pl/people/krzycz/dydaktyka/sks-2014/

Zachęcam do zapoznania się z innymi materiałami dydaktycznymi:http://pta.eti.pg.gda.pl/people/krzycz/dydaktyka/

Data utworzenia tej prezentacji: 20 listopada 2015