python – podstawy...
TRANSCRIPT
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