Commit b720e193 by Patryk Czarnik

przykłady dzien9

parent 0317802f
...@@ -42,3 +42,4 @@ try: ...@@ -42,3 +42,4 @@ try:
print(f'Nie istnieje waluta o kodzie {kod}') print(f'Nie istnieje waluta o kodzie {kod}')
except Exception as e: except Exception as e:
print('Błąd:', e) print('Błąd:', e)
exit(2)
with open('plik.txt', mode='rb') as plik:
bajty = plik.read()
print(type(bajty), 'rozmiar:', len(bajty))
print('Pierwszy bajt:', bajty[0]) # wartość liczbowa
print()
for b in bajty:
print(b, end=', ')
print()
print()
print(bajty)
print()
# zamień na tekst (odkoduj) zgodnie z konkretnym kodowaniem znaków
txt = bajty.decode('UTF-8')
print(txt)
# zgodnie z kodowaniem systemowym
txt = bajty.decode()
print(txt)
WEJSCIE = 'plik.txt'
WYJSCIE = 'kopia.txt'
SIZE = 50
with open(WEJSCIE, mode='rb') as wejscie,\
open(WYJSCIE, mode='wb') as wyjscie:
bajty = wejscie.read(SIZE)
print('porcja rozmiaru', len(bajty))
wyjscie.write(bajty)
print('Gotowe')
WEJSCIE = '/dev/random'
WYJSCIE = 'random.dat'
BUFSIZE = 1024
SIZE = 5000
with open(WEJSCIE, mode='rb') as wejscie,\
open(WYJSCIE, mode='wb') as wyjscie:
pozostalo = SIZE
while pozostalo > 0:
bajty = wejscie.read(min(pozostalo, BUFSIZE))
if not bajty: # koniec pliku przed wczytaniem całego SIZE
break
print('porcja rozmiaru', len(bajty))
pozostalo -= len(bajty)
wyjscie.write(bajty)
print('Gotowe')
# Tutaj argumenty uruchomienia programu podaje się w wierszu poleceń
import sys
# argumentem nr 0 jest nazwa programu
if len(sys.argv) < 3:
print('Nalezy podac wejscie, wyjscie i opcjonalnie ilosc bajtow')
exit(1)
BUFSIZE = 4096
WEJSCIE = sys.argv[1]
WYJSCIE = sys.argv[2]
SIZE = None
if len(sys.argv) >= 4:
SIZE = int(sys.argv[3])
with open(WEJSCIE, mode='rb') as wejscie,\
open(WYJSCIE, mode='wb') as wyjscie:
skopiowano = 0
while not SIZE or skopiowano < SIZE:
ileczytac = min(SIZE - skopiowano, BUFSIZE) if SIZE else BUFSIZE
bajty = wejscie.read(ileczytac)
if not bajty: # koniec pliku przed wczytaniem całego SIZE
break
print('porcja rozmiaru', len(bajty))
skopiowano += len(bajty)
wyjscie.write(bajty)
print(f'Skopiowano {skopiowano} bajtow')
Ala ma kota
Żaneta ma żółwie
Ola ma psa
Ela ma rybki
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include "err.h"
void syserr(const char *fmt, ...)
{
va_list fmt_args;
fprintf(stderr, "ERROR: ");
va_start(fmt_args, fmt);
vfprintf(stderr, fmt, fmt_args);
va_end (fmt_args);
fprintf(stderr," (%d; %s)\n", errno, strerror(errno));
exit(1);
}
void fatal(const char *fmt, ...)
{
va_list fmt_args;
fprintf(stderr, "ERROR: ");
va_start(fmt_args, fmt);
vfprintf(stderr, fmt, fmt_args);
va_end (fmt_args);
fprintf(stderr,"\n");
exit(1);
}
#ifndef _ERR_
#define _ERR_
/* Print system call error message and terminate.
* Uses errno to identify the error type. */
extern void syserr(const char *fmt, ...);
/* Print error message and terminate. */
extern void fatal(const char *fmt, ...);
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "err.h"
#include "towar.h"
/** Do rekordu Towar wpisuje podane wartości. */
void zainicjuj_towar(Towar *towar, const char *nazwa, int cena, int stan) {
strncpy(towar->nazwa, nazwa, DLUGOSC_NAZWY_TOWARU);
towar->cena = cena;
towar->stan = stan;
}
/** Wypisuje towar na konsolę. */
void wypisz_towar(const Towar *towar) {
printf("towar: %s, cena: %d, stan: %d\n", towar->nazwa, towar->cena, towar->stan);
}
void odczytaj_towar(int fd, Towar *towar) {
if(read(fd, towar, sizeof(Towar)) == -1)
syserr("read 1");
}
void zapisz_towar(int fd, const Towar *towar) {
if(write(fd, towar, sizeof(Towar)) == -1)
syserr("write 1");
}
/* Alokuje tablicę towarów i wspisuje wskaźnik do niej pod wskaznik_do_tablicy, a rozmiar pod zmienną rozmiar_tablicy.
* Wywołujący jest odpowiedzialny za zwolnienie tablicy. */
void odczytaj_plik_towary(const char *plik, Towar **wskaznik_do_tablicy, int *rozmiar_tablicy) {
int fd = open(plik, O_RDONLY, 0);
if(fd < 0) {
syserr("open w odczytaj_plik_towary, plik = %s", plik);
}
if(read(fd, rozmiar_tablicy, sizeof(int)) < 0) {
syserr("read rozmiar w odczytaj_plik_towary");
}
Towar *towary = (Towar*)malloc(*rozmiar_tablicy * sizeof(Towar));
if(towary == NULL) {
syserr("malloc w odczytaj_plik_towary, rozmiar = %d", *rozmiar_tablicy);
}
*wskaznik_do_tablicy = towary;
for(int i = 0; i < *rozmiar_tablicy; i++) {
if(read(fd, towary+i, sizeof(Towar)) < 0) {
syserr("read Towar w odczytaj_plik_towary, i = %d", i);
}
}
if(close(fd) == -1) {
syserr("close w odczytaj_plik_towary, fd = %d", fd);
}
}
void zapisz_plik_towary(const char *plik, Towar *towary, int rozmiar_tablicy) {
int fd = open(plik, O_WRONLY | O_CREAT, 0644);
if(fd < 0) {
syserr("open w zapisz_plik_towary, plik = %s", plik);
}
if(write(fd, &rozmiar_tablicy, sizeof(int)) < 0) {
syserr("write rozmiar w zapisz_plik_towary");
}
for(int i = 0; i < rozmiar_tablicy; i++) {
if(write(fd, towary+i, sizeof(Towar)) < 0) {
syserr("write Towar w odczytaj_plik_towary, i = %d", i);
}
}
if(close(fd) == -1) {
syserr("close w zapisz_plik_towary, fd = %d", fd);
}
}
#ifndef _TOWAR_H_
#define _TOWAR_H_
#define DLUGOSC_NAZWY_TOWARU 20
#define PLIK_TOWARY "towary.dat"
typedef struct towar {
char nazwa[DLUGOSC_NAZWY_TOWARU];
int cena;
int stan;
} Towar;
extern void zainicjuj_towar(Towar *towar, const char *nazwa, int cena, int stan);
extern void wypisz_towar(const Towar *towar);
extern void odczytaj_towar(int fd, Towar *towar);
extern void zapisz_towar(int fd, const Towar *towar);
extern void odczytaj_plik_towary(const char *plik, Towar **wskaznik_do_tablicy, int *rozmiar_tablicy);
extern void zapisz_plik_towary(const char *plik, Towar *towary, int rozmiar_tablicy);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "towar.h"
#include "err.h"
int main(int argc, char **argv) {
printf("Startujemy\n");
char* wejscie = argc >= 3 ? argv[1] : "towary.dat";
char* wyjscie = argc >= 3 ? argv[2] : "towary2.dat";
int ile_towarow;
Towar *towary;
odczytaj_plik_towary(wejscie, &towary, &ile_towarow);
printf("Odczytałem %d towarów\n", ile_towarow);
for(int i = 0; i < ile_towarow; i++) {
towary[i].stan += 3;
wypisz_towar(towary+i);
}
printf("Zapisuję...\n");
zapisz_plik_towary(wyjscie, towary, ile_towarow);
free(towary);
printf("Koniec\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include "towar.h"
#include "err.h"
int main(int argc, char **argv) {
printf("Startujemy\n");
char* wejscie = argc >= 2 ? argv[1] : "towary.dat";
int ile_towarow;
Towar *towary;
odczytaj_plik_towary(wejscie, &towary, &ile_towarow);
printf("Odczytałem %d towarów\n", ile_towarow);
for(int i = 0; i < ile_towarow; i++) {
wypisz_towar(towary+i);
}
free(towary);
printf("Koniec\n");
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include "towar.h"
#include "err.h"
void zapisz_towar_parametry(int fd, const char *nazwa, int cena, int stan) {
Towar towar;
zainicjuj_towar(&towar, nazwa, cena, stan);
zapisz_towar(fd, &towar);
}
int main(int argc, char **argv) {
if(argc < 2) {
fatal("Za malo argumentow, podaj nazwę pliku\n");
}
int fd = open(argv[1], O_WRONLY | O_CREAT, 0644);
if(fd == -1)
syserr("open");
int rozmiar = 6;
if(write(fd, &rozmiar, sizeof(int)) == -1)
syserr("write 0");
zapisz_towar_parametry(fd, "Pralka", 1200, 5);
zapisz_towar_parametry(fd, "Odkurzacz", 250, 20);
zapisz_towar_parametry(fd, "Telewizor", 2000,15);
zapisz_towar_parametry(fd, "Kuchenka", 1500, 10);
zapisz_towar_parametry(fd, "Zelazko", 300, 30);
zapisz_towar_parametry(fd, "Czajnik", 219, 10);
close(fd);
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include "towar.h"
#include "err.h"
// Zapisuje do pliku tylko jeden rekord Towar
int main(int argc, char **argv) {
if(argc < 2) {
fatal("Za malo argumentow, podaj nazwę pliku\n");
}
int fd = open(argv[1], O_WRONLY | O_CREAT, 0644);
if(fd == -1)
syserr("open");
Towar towar;
zainicjuj_towar(&towar, "Pralka", 1250, 10);
zapisz_towar(fd, &towar);
close(fd);
}
import struct
# Tutaj cały plik zawiera jeden rekord
with open('towar.dat', mode='rb') as plik:
bajty = plik.read()
print(f'Odczytalem {len(bajty)} bajtów')
print(bajty)
print()
format_rekordu = '20sii'
wynik = struct.unpack(format_rekordu, bajty)
print(wynik)
print(type(wynik))
print(type(wynik[0]), type(wynik[1]))
nazwa = wynik[0].decode('UTF-8')
print(nazwa)
import struct
# W tej wersji plik na początku ma jednego inta - liczba rekordów
# a następnie wiele rekordów.
# Program wczyta cały plik do pamięci, a potem w pętli odczyta rekordy z tablicy bajtów.
format_naglowka = 'i'
format_rekordu = '20sii'
dl_naglowka = struct.calcsize(format_naglowka)
dl_rekordu = struct.calcsize(format_rekordu)
print('Rozmiar nagłówka:', dl_naglowka)
print('Rozmiar rekordu:', dl_rekordu)
with open('towary.dat', mode='rb') as plik:
bajty = plik.read()
# Teraz nie można przekazać całej tablicy do unpack, bo jest za długa
# wynik = struct.unpack(format_naglowka, bajty)
# Można przekazać początkowy fragment
wynik = struct.unpack(format_naglowka, bajty[:4])
print(wynik)
# Lepiej będzie tu jednak użyć unpack_from, który czyta fragment od podanej pozycji
# i działa również wtedy, gdy tablica zawiera dalsze dane
ile, = struct.unpack_from(format_naglowka, bajty, 0)
print(f'W pliku jest {ile} rekordów')
pozycja = dl_naglowka
for i in range(ile):
nazwab, cena, sztuk = struct.unpack_from(format_rekordu, bajty, pozycja)
nazwa = nazwab.decode()
print(f'Towar nr {i}: {nazwa} za {cena}. W magazynie {sztuk} sztuk.')
pozycja += dl_rekordu
import struct
format_naglowka = 'i'
format_rekordu = '20sii'
kodowanie = 'UTF-8'
dl_naglowka = struct.calcsize(format_naglowka)
dl_rekordu = struct.calcsize(format_rekordu)
print('Rozmiar nagłówka:', dl_naglowka)
print('Rozmiar rekordu:', dl_rekordu)
with open('towary.dat', mode='rb') as plik:
(ilosc,) = struct.unpack(format_naglowka, plik.read(dl_naglowka))
print('Liczba rekordów:', ilosc)
for i in range(ilosc):
rekord = struct.unpack(format_rekordu, plik.read(dl_rekordu))
nazwa = rekord[0].decode(kodowanie).strip('\x00')
print(f'Rekord nr {i}: {nazwa} za {rekord[1]}, {rekord[2]} sztuk na magazynie.')
import struct
from collections import namedtuple
format_naglowka = 'i'
format_rekordu = '20sii'
kodowanie = 'UTF-8'
dl_naglowka = struct.calcsize(format_naglowka)
dl_rekordu = struct.calcsize(format_rekordu)
print('Rozmiar nagłówka:', dl_naglowka)
print('Rozmiar rekordu:', dl_rekordu)
Towar = namedtuple('Towar', ['nazwab', 'cena', 'stan'])
towary = []
with open('towary.dat', mode='rb') as plik:
(ilosc,) = struct.unpack(format_naglowka, plik.read(dl_naglowka))
print('Liczba rekordów:', ilosc)
for i in range(ilosc):
towar = Towar(*struct.unpack(format_rekordu, plik.read(dl_rekordu)))
#print(towar)
towary.append(towar)
for towar in towary:
nazwa = towar.nazwab.decode().strip("\x00")
print(f'{nazwa} za {towar.cena}, stan {towar.stan} sztuk')
import struct
from collections import namedtuple
format_naglowka = 'i'
format_rekordu = '20sii'
kodowanie = 'UTF-8'
dl_naglowka = struct.calcsize(format_naglowka)
dl_rekordu = struct.calcsize(format_rekordu)
print('Rozmiar nagłówka:', dl_naglowka)
print('Rozmiar rekordu:', dl_rekordu)
Towar = namedtuple('Towar', ['nazwab', 'cena', 'stan'])
towary = []
with open('towary2.dat', mode='rb') as plik:
(ilosc,) = struct.unpack(format_naglowka, plik.read(dl_naglowka))
print('Liczba rekordów:', ilosc)
for i in range(ilosc):
towar = Towar(*struct.unpack(format_rekordu, plik.read(dl_rekordu)))
#print(towar)
towary.append(towar)
ZMIANA = 100
towary = [towar._replace(cena = towar.cena + ZMIANA) for towar in towary]
with open('towary2.dat', mode='wb') as plik:
plik.write(struct.pack(format_naglowka, len(towary)))
for towar in towary:
print(towar)
plik.write(struct.pack(format_rekordu, *towar))
print('Gotowe')
def rodzynki(przepis):
def zmieniona_funkcja():
przepis()
print('I jeszcze dodaj rodzynki!')
return zmieniona_funkcja
def sernik_klasyczny():
print('Weź zmielony twaróg')
print('Dodaj cukier i aromaty')
print('Oddzielnie przygotuj ciasto')
print('Połóż masę serową na ciasto')
# Tu wywołam orygonalną funkcję - bez rodzynek
print('Normalny przepis:')
sernik_klasyczny()
print()
# Funkcja rodzynki bierze "normalną funkcję" i zwraca nową funkcję (inną wersję),
# która na końcu wypisuje jeszcze tekst o rodzynkach.
zmieniony_przepis = rodzynki(sernik_klasyczny)
print('Zmieniony przepis:')
zmieniony_przepis()
print()
# Właśnie taka funkcja jak "rodzynki", która zmienia inne funkcje, może byc używana jako dekorator.
@rodzynki
def sernik_brzoskwiniowy():
print('Weż masę serową')
print('Dodaj kawałki brzoswkiń')
# Teraz pod nazwą sernik_brzoskwiniowy od razu jest wersja z rodzynkami
print('Brzoskwiniowy:')
sernik_brzoskwiniowy()
# Funkcja poczatek_i_koniec jest "funkcją wyższego rzędu", tzn.
# jako parameter przyjmuje i jako wynik zwraca inną funkcję.
# Operuje na funkcjach, a nie na zwykłych wartościach.
# Funkcja poczatek_i_koniec jako parametr przyjmuje pewną funkcję bezargumentową.
# W wyniku zwraca zmienioną funkcję, która działa tak jak funkcja, ale dodatkowo na początku
# i na końcu swojego działania wypisuje POCZATEK i KONIEC.
def dopisz_poczatek_i_koniec(funkcja):
def zmieniona_funkcja():
print('POCZATEK')
funkcja()
print('KONIEC')
return zmieniona_funkcja
def powitaj():
print('Witamy serdecznie')
def pozdrow():
print('Na zdrowie!')
print('Normalne powitaj:')
powitaj()
print()
zmienione_powitaj = dopisz_poczatek_i_koniec(powitaj)
print('Zmienione powitaj:')
zmienione_powitaj()
print()
zmienione_pozdrow = dopisz_poczatek_i_koniec(pozdrow)
print('Zmienione pozdrów:')
zmienione_pozdrow()
zmienione_pozdrow()
print()
# Można też wywołać zmienioną funkcję bez wpisywania na zmienną:
dopisz_poczatek_i_koniec(powitaj)()
def dopisz_poczatek_i_koniec(funkcja):
def zmieniona_funkcja():
print('POCZATEK')
funkcja()
print('KONIEC')
return zmieniona_funkcja
# Gdy mamy funkcję wyższego rzędu, czyli taką, które bierze funkcję i w wyniku zwraca inną (zmienioną) funkcję,
# to można jej używać jako dekoratora przed definicjami zwykłych funkcji.
@dopisz_poczatek_i_koniec
def powitaj():
print('Witamy serdecznie')
# Dekorator robi coś takiego:
# powitaj = dopisz_poczatek_i_koniec(powitaj)
@dopisz_poczatek_i_koniec
def pozdrow():
print('Na zdrowie!')
# Teraz pod oryginalnymi nazwami powitaj i pozdrów mamy zmienione funkcje.
powitaj()
powitaj()
print()
pozdrow()
# W tej wersji dekorator zadziała tylko dla funkcji jednoargumentowych.
def pomiar_czasu(f):
from datetime import datetime
def wrapper(n):
poczatek = datetime.now()
wynik = f(n)
koniec = datetime.now()
print('czas działania:', koniec - poczatek)
return wynik
return wrapper
@pomiar_czasu
def petla(n):
suma = 0
for i in range(n):
suma += i
return suma
suma = petla(1000)
print(suma)
suma = petla(1000_000)
print(suma)
suma = petla(100_000_000)
print(suma)
def pomiar_czasu(f):
from datetime import datetime
def wrapper(*args, **kwargs):
poczatek = datetime.now()
try:
return f(*args, **kwargs)
finally:
koniec = datetime.now()
print('czas działania:', koniec - poczatek)
return wrapper
@pomiar_czasu
def petla(n):
suma = 0
for i in range(n):
suma += i
return suma
suma = petla(1000)
print(suma)
suma = petla(100_000_000)
print(suma)
def neg(f):
def wrapper(*args, **kwargs):
wynik = f(*args, **kwargs)
return -wynik
return wrapper
@neg
def silnia(n):
iloczyn = 1
for i in range(2, n+1):
iloczyn *= i
return iloczyn
print(silnia(5))
print(silnia(10))
def bold(f):
def wrapper(arg):
napis = f(arg)
return f'<b>{napis}</b>'
return wrapper
# Zmodyfikowana wersja funkcji, którą zwraca dekorator, może być zdefiniowana
# nie tylko konstrukcją def
def italic(f):
return lambda arg: f'<i>{f(arg)}</i>'
@bold
@italic
def foo(arg):
return f'To jest {arg}'
foo('Ala')
print(foo('Ola'))
def bold(f):
def wrapper(*args, **kwargs):
napis = f(*args, **kwargs)
return f'<b>{napis}</b>'
return wrapper
# Zmodyfikowana wersja funkcji, którą zwraca dekorator, może być zdefiniowana
# nie tylko konstrukcją def
def italic(f):
return lambda *args, **kwargs: f'<i>{f(*args, **kwargs)}</i>'
@bold
@italic
def foo(arg):
return f'To jest {arg}'
foo('Ala')
print(foo('Ola'))
@italic
@bold
def zaproszenie(jezyk, miasto, czas):
return f'Zapraszamy na kurs języka {jezyk}, który odbędzie się w {miasto} i będzie trwać {czas} dni.'
print(zaproszenie('Python', 'Warszawa', 20))
print(zaproszenie('SQL', 'Kraków', 8))
# Przykłady od Agaty ;)
import os
from datetime import datetime
from time import sleep
def debug(funkcja):
def wrapper(*args, **kwargs):
print(f'[debug] user:{os.getlogin()} '
f'time:({datetime.now()}) '
f'function:{funkcja.__name__}, '
f'args:{args}, kwargs:{kwargs}' )
wynik= funkcja(*args, **kwargs)
print('czas po wykonaniu funkcji:', datetime.now())
return wynik
return wrapper
def dodaj1000(funkcja_do_wywolania):
def opakowanie(*args,**kwargs):
tmp = funkcja_do_wywolania(*args,**kwargs)
return tmp+1000
return opakowanie
print()
@dodaj1000
@debug
def dodaj(a,b):
return a+b
@dodaj1000
@debug
def pomnoz(a,b=10):
return a*b
@debug
def abc(a, b, c):
print('Tu abc',a, b, c)
sleep(0.5)
print('papa...')
print(dodaj(11,22))
print(pomnoz(3,4))
abc('Ala', 'Basia', 'Celina')
# Podmiana funkcji na zupełnie inną
def haha(*args, **kwargs):
print('hahaha')
# Gdybyśmy chcieli, aby fake mógł być wywołany z dowolnymi parametrami, to:
# def fake(*args, **kwargs):
# print('hahaha')
# Prawdziwej funkcji w ogóle nie uruchamia,
# zamiast niej podstawia fake
def oszukaj(funkcja):
return haha
@oszukaj
def bardzo_wazna_rzecz():
print('To są bardzo poważne sprawy')
print('itd itp')
bardzo_wazna_rzecz() # hahaha
print()
#######
# dekorator blokuje przekazywanie parametru równego 0 - w tym przypadku zgłosi wyjątek
def nie_zero(funkcja):
def wrapper(liczba, *args, **kwargs):
if liczba == 0:
raise ValueError('Liczba nie może być zerem!')
funkcja(liczba, *args, **kwargs)
return wrapper
@nie_zero
def wplata(kwota):
print('Wpłacam wartość ', kwota)
@nie_zero
def wyplata(kwota):
print('Wypłacam wartość ', kwota)
@nie_zero
def wiecej_parametrow(liczba, napis, lista):
for i in range(liczba):
print(napis)
try:
wplata(100)
wyplata(50)
wplata(0)
except Exception as e:
print(e)
def powitaj():
print('Witaj serdecznie!')
def pozegnaj():
print('Do widzenia.')
print('Początek programu')
powitaj()
# Funkcję można wpisać do zmiennej
f = powitaj
# Teraz w zmiennej f mamy funkcję i możemy ją wywołać
f()
f = pozegnaj
f()
print()
# Funkcja może być elementem kolekcji (lista, słownik...)
funkcje = [powitaj, lambda: print('Mówię coś'), pozegnaj]
print(funkcje)
for funkcja in funkcje:
funkcja()
print("=" * 20)
# Teraz funkcje, które biorą dwa argumenty i zwracają wynik, jak działąnia matematyczne.
def dodaj(a, b):
return a+b
def pomnoz(x, y):
return x*y
def liczba_z_cyfr(a, b):
return 10*a + b
arg1 = 5
arg2 = 3
for funkcja in dodaj, pomnoz, liczba_z_cyfr:
wynik = funkcja(arg1, arg2)
print(f'Funkcja {funkcja.__name__} dla argumentów {arg1} i {arg2} dała wynik {wynik}')
# Funkcję w Pythonie można zdefiniować za pomocą def
# Wówczas ta funkcja jest wpisywana do zmienne globalnej o podanej nazwie
def kwadrat(x):
return x**2
def szescian(x):
return x**3
print(globals())
print(kwadrat(5))
print(szescian(5))
# Funkcję można też jednak zdefiniować za pomocą "wyrażenia lambda" (lambda expression)
kw = lambda x: x**2
print(kw(5))
# Wyrażeń lambda używa się najczęściej, gdy funkcję trzeba przekazać jako parametr do innej funkcji
# lub gdy dodajemy funkcje do kolekcji
funkcje = [kwadrat,
szescian,
lambda arg: 10*arg,
lambda x: x - 1
]
liczby = list(range(1, 6))
print(funkcje)
print(liczby)
for liczba in liczby:
print(liczba, end=': ')
for funkcja in funkcje:
# print(funkcja(liczba), end=', ')
print(f'{funkcja(liczba):3}, ', end='')
print()
from datetime import datetime
# Do poniższej funkcji inną funkcję przekazuje się jako argument.
# Przekazana funkcja zostanie wykonana, przy czy zostanie zmierzony czas działania
def zmierz_czas_1(funkcja):
start = datetime.now()
funkcja()
stop = datetime.now()
print(f'Funkcja {funkcja.__name__} wykonała się w czasie {stop - start}')
def petla_10milionowa():
for i in range(10_000_000):
pass
zmierz_czas_1(petla_10milionowa)
print(20*"=")
# Jeśli tak przekazaną funkcję chcemy uruchomić, ale z parametrami:
def zmierz_czas_2(funkcja, *args):
start = datetime.now()
funkcja(*args)
stop = datetime.now()
print(f'Funkcja {funkcja.__name__} z argumentami {args} wykonała się w czasie {stop - start}')
def fib(n):
if n <= 1: return n
return fib(n-1) + fib(n-2)
zmierz_czas_2(fib, 35)
zmierz_czas_2(fib, 36)
print(20*"=")
# Funkcja wykonuje przekazaną funkcję f tyle razy, ile wynosi ileRazy
# Tutaj przekazywane są wszystkie argumenty: pozycyjne *args oraz z nazwami **kwargs
def powtorz(f, ileRazy, *args, **kwargs):
for i in range(ileRazy):
f(*args, **kwargs)
def powitaj():
print('Witamy serdecznie')
powtorz(powitaj, 3)
print()
# następny krok: dodaj do funkcji powtórz takie elementy, aby można byo uruchamiać również funkcje z argumentami
powtorz(print, 5, 'Ala ma kota')
print()
powtorz(print, 4, 'Ala', 'Ela', 'Ola', sep=';')
from random import randint
liczby = [randint(1, 100) for i in range(20)]
print(liczby)
# Aby wypisać tylko liczby spełniające warunek, np. tylko podzielne przez 2,
# można:
for liczba in liczby:
if liczba % 2 == 0:
print(liczba, end=' ')
print()
print('#' * 40)
# Można też uzyskać listę parzystych za pomocą list comprehension ("wyrażenie listotwórcze")
parzyste = [x for x in liczby if x % 2 == 0]
print(parzyste)
# Istnieje też funkcja filter, która zwraca zetaw tych elementów listy (lub innej kolekcji),
# które spełniają podany warunek.
# Warunek podaje się w formie funkcji, która dostaje wartość i zwraca True/False.
# Na takie funkcje mówi się "predykat".
parzyste2 = filter(lambda x: x%2 == 0, liczby)
print(parzyste2)
for p in parzyste2:
print(p, end=', ')
print()
# Wyjaśnie dlaczego dodatkowa pętla:
# filter zwraca w wyniku "generator", czyli obiekt, który zwraca wartości dopiero, gdy jest o to proszony, np. w pętli for
# Można też od razu zrzutować to na listę
print(list(filter(lambda x: x%2 == 0, liczby)))
print()
# Z kolei gdy chcemy zastosować jakąśfunkcję ,np. podnoszenie do kwadratu, dla każdego elementu listy,
# to możemy:
# napisać klasyczną pętlę
for liczba in liczby:
print(liczba**2, end=', ')
print()
# możemy użyć list comprehension
kwadraty = [x**2 for x in liczby]
print(kwadraty)
# albo użyć map
kwadraty2 = map(lambda x: x**2, liczby)
print(kwadraty2)
for k in kwadraty2:
print(k, end=', ')
print()
print(list(map(lambda x: x**2, liczby)))
# połączenie obu technik
for liczba in liczby:
if liczba % 2 == 0:
print(liczba**2, end=' ')
print()
parzyste_kwadraty = [x**2 for x in liczby if x % 2 ==0]
print(parzyste_kwadraty)
pk2 = list(map(lambda x: x**2, filter(lambda x: x % 2 ==0, liczby)))
print(pk2)
# To staje się łądniejsze w zapisie, gdy mamy funkcję, której chcemy użyć
def jest_parzysta(liczba):
return liczba % 2 == 0
def kwadrat(x):
return x**2
pk3 = list(map(kwadrat, filter(jest_parzysta, liczby)))
print(pk3)
print()
miasta = ['Warszawa', 'Kraków', 'Gdańsk']
for m in map(str.upper, miasta):
print(m)
print()
print('Poznań'.upper())
print(str.upper('Łódź')) # Łódź jest parametrem self
dodaj = int.__add__
print(dodaj(13, 43))
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
op = input('Podaj rodzaj operacji: ')
if op == '+':
wynik = x + y
elif op == '-':
wynik = x - y
elif op == '*':
wynik = x * y
elif op == '^':
wynik = x ** y
elif op == '/':
if y == 0:
wynik = 'Dzielenie przez zero!'
else:
wynik = x / y
else:
wynik = 'Nieznana operacja'
print('Wynik:', wynik)
def dodaj(x, y):
return x + y
def odejmij(x, y):
return x - y
dzialania = {
'+': dodaj,
'-': odejmij,
'*': lambda x, y: x * y,
'/': lambda x, y: x / y,
}
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
op = input('Podaj rodzaj operacji: ')
funkcja = dzialania[op]
wynik = funkcja(x, y)
print('Wynik:', wynik)
dzialania = {
'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
'*': lambda x, y: x * y,
'/': lambda x, y: x / y,
'^': lambda x, y: x ** y,
}
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
op = input('Podaj rodzaj operacji: ')
if op not in dzialania:
print('Nieznana operacja', op)
else:
wynik = dzialania[op](x, y)
print('Wynik:', wynik)
# Jeśli odwołamy się do modułu operator, można nie pisać wyrażeń lambda, tylko bezpośrednio wskazać istniejące funkcje Pythona
import operator
dzialania = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'^': operator.pow,
}
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
op = input('Podaj rodzaj operacji: ')
if op not in dzialania:
print('Nieznana operacja', op)
else:
wynik = dzialania[op](x, y)
print('Wynik:', wynik)
# Gdy w funkcji zamiast return użyjemy operacji yield, to
# - w wyniku powstaje "generator", który obrazowo działa tak, że
# po zwróceniu wyniku, funkcja działa dalej i może zwrócić kolejne wyniki za pomocą kolejnych yield
def abc():
yield 'Ala'
yield 'Basia'
yield 'Celina'
generator = abc()
print(generator)
# Generator jest iterowalny i najczęściej korzysta z niego porzez pętlę for
for x in generator:
print(x)
print()
def cba():
print('> 0')
yield 'Celina'
print('> 1')
yield 'Basia'
print('> 2')
yield 'Ala'
print('> 3')
print('Starujemy')
for x in cba():
print(x)
print('*')
print('Koniec\n')
# wszystkie wyniki na raz: rzutowanie na listę:
imiona = list(abc())
print(imiona)
print()
# Jak to działa? Generator jest jednocześnie iteratorem, czyli można na nim wywoływać next,
# co daje kolejne elementy zwracane przez yield, aż do StopIteration
g = abc()
print(g.__next__())
# Istnieje globalna funkcja Pythona, która to robi i "ładniej" używać tej funkcji, niż wołać __next__
print(next(g))
print(next(g))
#print(next(g)) #ERR
# Nieskończony generator liczb parzystych
def parzyste():
liczba = 0
while True:
yield liczba
liczba += 2
# Samo wywołanie nie wykonuje tej pętli. Tworzony jest generator.
g = parzyste()
print(g)
# Dopiero umieszczenie w pętli for, albo wielokrotne wywoływanie next, albo konwersja na listę / zbióre / itp.
# spowoduje wykonanie tej pętli i dostarczanie kolejnych wartości.
for x in parzyste():
print(x)
def parzyste(limit):
liczba = 0
while liczba <= limit:
yield liczba
liczba += 2
for x in parzyste(1000):
print(x)
from typing import Generator
def parzyste(limit: int) -> Generator[int, None, None]:
liczba = 0
while liczba < limit:
yield liczba
liczba += 2
for x in parzyste(1000):
print(x)
# Gdy definiujemy funkcję, ale w jej treści zamiast return użyjemy yield,
# to funkcja zwraca w wyniku "generator", czyli obiekt, który dostarcza kolejnej wartości dopiero wtedy, gdy jest o to proszony.
def abc():
yield 'Ala'
yield 'Basia'
print('Jestem w funkcji abc między Basią a Celiną')
yield 'Celina'
print(abc)
generator = abc()
print(generator)
# generator zwróci wartości (które w nim są zwracane za pomocą yield) wtedy, gdy wywołamy funkcję next
pierwszy_wynik = next(generator)
print(pierwszy_wynik)
print('Zaraz zapytam o Basię...')
nastepny_wynik = next(generator)
print(nastepny_wynik)
print('Zaraz zapytam o Celinę...')
nastepny_wynik = next(generator)
print(nastepny_wynik)
# Gdy nie ma już elementów, to wtedy pojawia się wyjątek StopIteration
try:
nastepny_wynik = next(generator)
print(nastepny_wynik)
except StopIteration:
print('To już koniec')
print((40*'-'))
# Najczęściej z generatorów i iteratorów korzysta się tak, że umieszcza się po prawej stronie wyrażenia for
# i wtedy pętla for wykona się dla każdego elementu zwracanego przez ten generator.
for imie in abc():
print('Kolejna osoba to', imie)
print((40*'-'))
# Najczęściej yield umieszcza się w pętli, a nie pisze jeden pod drugim.
# Ten generator wygeneruje określoną liczbę liczb nieparzystych.
def nieparzyste(ile):
x = 1
for i in range(ile):
yield x
x += 2
for n in nieparzyste(10):
print(n, end=', ')
print()
print(sum(nieparzyste(7)))
def nasz_range(start, stop, step=1):
i = start
while i < stop:
yield i
i += step
print(list(nasz_range(100, 150, 5)))
# Jak wiemy, w Pythonie pętla for pozwala przeglądać listy, zbiory, linie z otwartego pliku, elementy range...
# O tym czy dany obiekt może być użyty "po prawej stronie w pętli for" decyduje to, czy ten obiekt jest "iterowalny" (iterable).
# Iterowalne są te obiekty, które posiadają metodę __iter__(), która z kolei zwraca iterator.
# Iterator to jest taki obiekt, na który można wielokrotnie wywoływać metodę __next__()
# a ta metoda zwraca wtedy kolejne elementy, które idą do pętli for.
# W tym przykładzie IteratorParzystych pełni rolę iteratora
# Parzyste to jest klasa iterowalna (tak jak iterowalna jest np. lista)
# W tym przykładzie iterator jest nieskończony.
# Gdy Python uruchamia pętlę for x in ZRODLO: , to postępuje tak:
# wywołuje ZRODLO.__iter__()
# dostaje w wyniku jakiś obiekt it
# i na tym obiekcie wielokrotnie wywołuje it.__next__()
# (aż dojdzie do wyjątku...)
class IteratorParzystych:
def __init__(self):
self.current = 0
def __next__(self):
try:
return self.current
finally:
self.current += 2
class Parzyste:
def __iter__(self):
return IteratorParzystych()
obiekt = Parzyste()
for x in obiekt:
print(x)
class IteratorParzystych:
def __init__(self, start, stop):
self.current = start
self.stop = stop
def __next__(self):
if self.current > self.stop:
# sygnał dla Pythona, że należy zakończyć iterację
raise StopIteration
try:
return self.current
finally:
self.current += 2
class Parzyste:
def __init__(self, limit):
self.limit = limit
def __iter__(self):
return IteratorParzystych(0, self.limit)
obiekt = Parzyste(100)
for x in obiekt:
print(x)
print('koniec pętli\n')
# druga iteracja działa, bo z tego samego obiektu Parzyste ponownie pobierany jest IteratorParzystych
for x in obiekt:
print(x)
print()
print()
obiekt2 = Parzyste(20)
# Technicznie działa to tak, że
# gdy napiszemy for element in obiekt2: ... Python robi tak:
# najpierw pobierany jest iterator
it = obiekt2.__iter__()
print(it)
# a następnie, dopóki nie nastapi wyjątek StopIteration, powtarzane jest pobieranie następnego elementu za pomocą next
try:
while True:
element = it.__next__()
print(element, end=', ')
except StopIteration:
print('\nKoniec\n')
# Jeśli faktycznie chcemy bezpośrednio wykonywać operacje na iteratorach, to "ładniej" jest robić to za pomocą globalnych funkcji Pythona
it = iter(obiekt2)
print(it)
try:
while True:
print(next(it), end='; ')
except StopIteration:
print('\nKoniec\n')
# Ale zdecydowanie częściej używa się pętli for.
# Czasami można uprościć uznając, że ten sam obiekt iterowalny jest jednocześnie swoim iteratorem.
class Parzyste:
def __init__(self, limit = 1000):
self.liczba = -2
self.limit = limit
def __iter__(self):
return self
def __next__(self):
self.liczba += 2
if self.liczba >= self.limit:
# gdy chcemy powiadomić Pythona, że iterator już nie da więcej elementów, że to już koniec
# wtedy wyrzucamy wyjątek StopIteration
raise StopIteration
return self.liczba
def reset(self):
self.liczba = -2
obiekt = Parzyste()
for i in obiekt:
print(i)
print()
obiekt = Parzyste(100)
for i in obiekt:
print(i)
print('----------')
for i in obiekt:
print(i)
# przy tym podejściu obiekt potrafi przeiterować elementy tylko raz. kolejna pętla na tym samym obiekcie nei wykona się ani razu
# tak działają pliki - po otwarciu linie można odczytać tylko raz (chyba, że potem zrobimy seek(0))
# chyba, że wprowadzimy dodatkową metodę resetującą, która ustawia licznik na 0
print('**********')
obiekt.reset()
for i in obiekt:
print(i)
class A:
pass
a = A()
print(a)
# print(a.imie)
# Do obiektu można dodać atrybut, nawet, gdy nie było o nim mowy w treści klasy.
a.imie = 'Ala'
a.wiek = 30
print(a.imie)
aa = A()
# print(aa.imie)
class Osoba:
def __init__(self, imie, nazwisko, wiek):
self.imie = imie
self.nazwisko = nazwisko
self.wiek = wiek
o = Osoba('Jan', 'Kowalski', 40)
o.numer_buta = 44
slownik = o.__dict__
print(slownik)
# slownik jest wciąż powiązany z tym obiektem
# zmiany w obiekcie są widoczne w słowniku są widoczne w obiekcie i viceversa
o.wiek += 1
print(slownik)
slownik['wiek'] += 10
slownik['telefon'] = '321321321'
print(o.wiek)
print(o.telefon)
print()
# Przykład zastosowania: wypisywanie wszystkich pól obiektu jako linii tekstu "a la CSV"
# Nie wiedząc, jakie pola ma obiekt, mogę napisać unowersalną funkcję
def wypisz(obiekt, sep=';'):
print(*obiekt.__dict__.values(), sep=sep)
wypisz(o)
class Klasa:
def __init__(self, a, b, c):
self.a = a
self._b = b # konwencja
self.__c = c # name mangling
k = Klasa('Ala', 'Basia', 'Celina')
print(k.__dict__)
print(k.a)
print(k._b)
# print(k.__c)
print(k._Klasa__c)
k._Klasa__c = 'Cezary'
print(k._Klasa__c)
# My uczyliśmy się tworzenia atrybutów w metodzie init
# Ale w Pythonie można też definiować atrybuty na poziomie klasy, jka np. w C++ czy Javie.
# Ale to działa dziwnie...
class Osoba:
imie = 'IMIĘ'
nazwisko = 'NAZWISKO'
def __str__(self):
return f'{self.imie} {self.nazwisko}'
class Student(Osoba):
# ta lista będzie współdzielona przez wszystkie obiekty
# analogia: zmienne statyczne w Javie czy C#
oceny = []
def dodaj_ocene(self, ocena):
# dwie pierwsze wersje dają efekt "wspólnej listy dla wszystkich studentów"
self.oceny.append(ocena)
# self.oceny += [ocena]
# trzecia wersja działa poprawnie, ale to mało wydajne...
# self.oceny = self.oceny + [ocena]
def srednia(self):
return sum(self.oceny) / len(self.oceny)
def __str__(self):
return super().__str__() + f' z ocenami {self.oceny}'
o = Osoba()
print(o.imie)
print(o)
print('etap1, atrybuty obiektu:', o.__dict__)
print('atrybuty klasy:', Osoba.__dict__)
o.imie = 'Jan'
o.nazwisko = 'Kowalski'
print(o.imie)
print(o)
print('etap2, atrybuty obiektu:', o.__dict__)
print('atrybuty klasy:', Osoba.__dict__)
print()
a = Student()
print(a)
a.imie = 'Adam'
a.nazwisko = 'Abacki'
print(a)
print()
b = Student()
print(b)
b.imie = 'Bartek'
b.nazwisko = 'Babecki'
print(b)
print()
print(a)
print(b)
# Do tej pory to działało dobrze
a.dodaj_ocene(5)
a.dodaj_ocene(5)
a.oceny.append(5)
print(a, a.srednia())
print()
b.dodaj_ocene(3)
print(a, a.srednia())
print('Oceny Adama:', a.oceny)
print('Oceny Bartka:', b.oceny)
# Morał: to jest TA SAMA lista
# Atrybut oceny jest tworzony w klasie!!!
# Różne obiekty mają do niego dostęp, ale to jest ten sam obiekt
# Ze stringami nie ma problemu, bo stringi sa "niemutowalne" i w obiektach możemy wpisac inne stringi - ale to będą nowe obiekty
# Ale lista jest "mutowalna" i obiekty mogą modyfikować wspólny obiekt - wspólną listą.
class Klasa:
# W Pythonie, podobnie jak w C++ czy Javie, można deklarować atrybuty w ciele klasy (a nie w init).
# Jednak w Pythonie działa to w sposób specyficzny, nieoczywisty.
# Te zmienne są przechowywane w klasie, a nie w obiekcie, a obiekty mają do nich dostęp.
# Jednak zapisanie atrybutu o tej samej nazwie w obiekcie (poprzez self) przesłania definicję z poziomu klasy.
x = 100
s = 'Ala ma kota'
lista = []
def __init__(self, y):
self.y = y
def __str__(self):
return f'x = {self.x} , y = {self.y}, s = {self.s}, lista: {self.lista}'
def dodajZwierze(self, zwierze):
self.s += f' oraz {zwierze}'
a = Klasa(1)
print('a:', a)
b = Klasa(2)
print('b:', b)
print()
print("x z różnych perspektyw:")
print(a.x)
print(b.x)
print(Klasa.x)
print()
# Tutaj operacja jest wykonywana na zmiennej klasy
# Obiekty - jeśli nie "przesłoniły" tej zmiennej, to widzą tę zmianę.
# x jest atrybutem klasowym, do którego dostęp jest możliwy także poprzez obiekty
Klasa.x += 3
print(a.x)
print(b.x)
print(Klasa.x)
print('a.__dict__:', a.__dict__)
print('Klasa.__dict__:', Klasa.__dict__)
print()
# Teraz obiekt a tworzy własny atrybut, który przesłoni dostep do x klasowego
# a.x += 5 jest traktowane jako a.x = a.x + 5 w tym przypadku a.x = Klasa.x + 5
a.x += 5
print(a.x)
print(b.x)
print(Klasa.x)
# od tej pory a ma swojego własnego x
# natomiast b.x oznacza odwołanie do Klasa.x
print('a.__dict__:', a.__dict__)
print('Klasa.__dict__:', Klasa.__dict__)
print()
Klasa.x += 1
print(a.x)
print(b.x)
print(Klasa.x)
print()
print(a.lista)
print(b.lista)
# operacja modyfikująca listę modyfikuje listę przechowywaną w klasie , zmiany będą widoczne dla wszystkich obiektów klasy
a.lista.append('Ala')
b.lista.append('Ola')
Klasa.lista.append('Ela')
print(a.lista)
print(b.lista)
print(Klasa.lista)
print()
print(a)
print(b)
print()
Klasa.s = 'Ola ma psa'
# a i b widzą tę zmianę
print(a)
print(b)
b.dodajZwierze('rybki')
# od teraz b używa swojej kopii napisu s
print(a)
print(b)
Klasa.s = 'Ela ma królika'
# Tylko a widzi zmianę, b już nie, bo używa swojej kopii napisu
print(a)
print(b)
# Przedefiniowując metodę setattr możemy zmienić zachowanie Pythona
# w zakresie ustawiana atrybutów.
# Możemy np. zabronić ustawiania niektórych atrybutów, albo stworzyć klasę niemutowalną.
class C:
def __init__(self, imie, nazwisko):
self.imie = imie
self.nazwisko = nazwisko
def __str__(self):
return f'Osoba {self.imie} {self.nazwisko}'
def __setattr__(self, key, value):
print(f'Próba ustawienia atrybutu {key} na wartość {value}')
if key in ['imie', 'nazwisko']:
print('OK, atrybut dopuszczalny')
super().__setattr__(key, value)
else:
print('Niepoprawny atrybut')
raise AttributeError(f'nie wolno ustawiać atrybutu {key}')
c = C('Ala', 'Kowalska')
c.imie = 'Alicja'
print('Udało się ustawić imię', c.imie)
try:
c.zwierze = 'kot'
print('Udało się ustawić zwierze', c.zwierze)
except AttributeError as e:
print(f'Nie udało się. Wyjątek typu {type(e)} o treści {e}')
print('Koniec')
class C:
def __init__(self, imie, nazwisko):
self.imie = imie
self.nazwisko = nazwisko
self._freezed = True
def __str__(self):
return f'Osoba {self.imie} {self.nazwisko}'
def __setattr__(self, key, value):
if hasattr(self, '_freezed') and self._freezed:
raise AttributeError(f'nie wolno już zmieniać obiektu')
super().__setattr__(key, value)
c = C('Ala', 'Kowalska')
print('Jest obiekt:', c)
try:
c.imie = 'Alicja'
print('Udało się ustawić normalnie imię', c.imie)
except Exception as e:
print('Nie udało się ustawić imienia normalnie')
# da się to objeść wbudowanym słownikiem
try:
c.__dict__['imie'] = 'Alicja'
print('Udało się ustawić słownikiem imię', c.imie)
except Exception as e:
print('Nie udało się ustawić imienia słownikiem')
print(c)
\ No newline at end of file
class C:
def __init__(self, imie, nazwisko):
self.imie = imie
self.nazwisko = nazwisko
self._freezed = True
def __str__(self):
return f'Osoba {self.imie} {self.nazwisko}'
def __setattr__(self, key, value):
if hasattr(self, '_freezed') and self._freezed:
raise AttributeError(f'nie wolno już zmieniać obiektu')
super().__setattr__(key, value)
def __getattribute__(self, item):
print('próba odczytu', item)
if item == '__dict__':
raise AttributeError('nie wolno ruszać dict!')
return super().__getattribute__(item)
c = C('Ala', 'Kowalska')
print('Jest obiekt:', c)
try:
c.imie = 'Alicja'
print('Udało się ustawić normalnie imię', c.imie)
except Exception as e:
print('Nie udało się ustawić imienia normalnie')
# teraz nie da się słownikiem
try:
c.__dict__['imie'] = 'Alicja'
print('Udało się ustawić słownikiem imię', c.imie)
except Exception as e:
print('Nie udało się ustawić imienia słownikiem')
print(c)
# ale pewnie da się obejść inaczej -> temat "introspekcja"
class Osoba:
def __init__(self, imie, nazwisko, wiek):
self.imie = imie
self.nazwisko = nazwisko
self.wiek = wiek
def przedstaw_sie(self):
print(f'Jestem Osobą. Nazywam się {self.imie} {self.nazwisko} i mam {self.wiek} lat.')
def pelnoletnia(self):
return self.wiek >= 18
def __str__(self):
return f'{self.imie} {self.nazwisko} ({self.wiek} lat)'
def __repr__(self):
return f'Osoba({repr(self.imie)}, {repr(self.nazwisko)}, {repr(self.wiek)})'
class BrakSrodkow(Exception):
def __init__(self, numer, kwota, saldo):
super().__init__(f'Brak środków na koncie nr {numer}. Próbowano wypłacić {kwota}, a na koncie jest {saldo}')
self.numer = numer
self.kwota = kwota
self.saldo = saldo
class Konto:
def __init__(self, numer, wlasciciel, saldo=0):
if saldo < 0:
raise ValueError('ujemne saldo')
self._numer = numer
self._wlasciciel = wlasciciel
self._saldo = saldo
def __str__(self):
return f'Konto nr {self._numer}, saldo = {self._saldo}, wł. {self._wlasciciel}'
def wplata(self, kwota):
if kwota <= 0:
raise ValueError('niedodatnia kwota we wplata')
self._saldo += kwota
def wyplata(self, kwota):
if kwota <= 0:
raise ValueError('niedodatnia kwota w wyplata')
if kwota > self._saldo:
raise BrakSrodkow(self._numer, kwota, self._saldo)
self._saldo -= kwota
def proba(lista, napis, liczba):
lista += ['Ola', 'Ela']
napis += ' ma kota'
liczba += 33
print('na koniec funkcji:\n', lista, napis, liczba, '\n')
def main():
lista = ['Ala', 'Ula']
napis = 'Ala'
liczba = 1000
print('na początku:\n', lista, napis, liczba, '\n')
proba(lista, napis, liczba)
print('na końcu:\n', lista, napis, liczba)
# Tylko efekt zmiany listy jest widoczny, a str i int nie
# str, int - to są klasy NIEMUTOWALNE (immutable)
# obiekty tych klas nie mogą zmieniać swojego wewnątrznego stanu
# a operacje takie jak +, replace zwracają w wyniku nowy obiekt
# += dla napisów do zmiennej wpisuje adres nowego obiektu
main()
from klasy import *
a = Konto(1, 'Ala', 1000)
b = Konto(2, 'Ola', 2000)
c = b
print('a:', a)
print('b:', b)
print('c:', c)
print()
b.wplata(48)
print('a:', a)
print('b:', b)
print('c:', c)
print()
b = a
print('a:', a)
print('b:', b)
print('c:', c)
print()
# Tracimy referencję do konta nr 2
c = b
print('a:', a)
print('b:', b)
print('c:', c)
print()
# Aby ostatecznie stracić referencję do obiektu, można też do zmiennej przypisać None
a = b = None
# W Pythonie można też jawnie usunąć zmienną
del c
# To usuwa zmienną, a nie obiekt. Obiekt na normalnych zasadach MOŻE być postprzątany przez garbage collecotra.
# Teraz odwołanie do zmiennej c kończy się błedem
print('a:', a)
print('b:', b)
#ERR print('c:', c)
from klasy import *
def funkcja(a, b, c, x):
print('Początek funkcji:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
x += 55
# modyfikujemy obiekt wewnątrz, zmieniamy jego stan, atrybut saldo
b.wplata(44)
# do zmiennej lokalnej wpisujemy referencję do innego obiektu
# tę zmianę widzi tylko funkcja, a main nie widzi
a = Konto(a._numer, a._wlasciciel, a._saldo)
a.wplata(24)
a._wlasciciel.imie = 'Alicja'
print('Koniec funkcji:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
def main():
ala = Osoba('Ala', 'Kowalska', 20)
ola = Osoba('Ola', 'Malinowska', 30)
a = Konto(1, ala, 1000)
b = Konto(2, ola, 2000)
c = b
x = 5000
print('Początek main:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
funkcja(a, b, c, x)
print('Koniec main:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
if __name__ == '__main__':
main()
from klasy import *
def funkcja(a, b, c, x):
print('Początek funkcji:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
x += 55
# modyfikujemy obiekt wewnątrz, zmieniamy jego stan, atrybut saldo
b.wplata(44)
# do zmiennej lokalnej wpisujemy referencję do innego obiektu
# tę zmianę widzi tylko funkcja, a main nie widzi
a = b
print('Koniec funkcji:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
def main():
ala = Osoba('Ala', 'Kowalska', 20)
ola = Osoba('Ola', 'Malinowska', 30)
a = Konto(1, ala, 1000)
b = Konto(2, ola, 2000)
c = b
x = 5000
print('Początek main:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
funkcja(a, b, c, x)
print('Koniec main:')
print('a:', a)
print('b:', b)
print('c:', c)
print('x:', x)
print()
if __name__ == '__main__':
main()
import random
def dopisz_i_wypisz(n, lista=[]):
# do przekazanej listy dopisuje losową wartość i wypisuje całą listę
# domyślnie lista jest pusta
# przy takim zapisie wszystkie ywołania funkcji, w któyrch nie podaje się drugiego arguemntu, będą korzystać z tego samego obiektu lista
for i in range(n):
lista.append(random.randint(1, 100))
print(lista)
dopisz_i_wypisz(1, [5, 10, 15])
dopisz_i_wypisz(3, [11, 12, 13, 14, 15])
dopisz_i_wypisz(5)
dopisz_i_wypisz(2)
dopisz_i_wypisz(1, [100, 200])
dopisz_i_wypisz(3)
print(30 * '=')
# rozwiązanie poprawne, aby za każdym razem powstała pusta lista:
def dopisz_i_wypisz2(n, lista=None):
# do przekazanej listy dopisuje losową wartość i wypisuje całą listę
# domyślnie lista jest pusta
if lista is None:
lista = []
for i in range(n):
lista.append(random.randint(1, 100))
print(lista)
dopisz_i_wypisz2(5)
dopisz_i_wypisz2(2)
dopisz_i_wypisz2(1, [100, 200])
dopisz_i_wypisz2(3)
\ No newline at end of file
class Student:
def __init__(self, imie, nazwisko, oceny=[]):
self.imie = imie
self.nazwisko = nazwisko
self.oceny = oceny
def dodaj_ocene(self, ocena):
self.oceny.append(ocena)
def srednia_ocen(self):
return sum(self.oceny) / len(self.oceny)
adam = Student('Adam', 'Abacki', [3,4,5])
print('adam:', adam.srednia_ocen())
basia = Student('Barbara', 'Rabarbar')
basia.dodaj_ocene(5)
basia.dodaj_ocene(5)
print('basia:', basia.srednia_ocen())
# Podczas tworzenia obiektu cezary zostaje użyta ta ama lista (ten sam obiekt),
# która została już użyta dla obiektu basia
cezary = Student('Cezary', 'Inny')
cezary.dodaj_ocene(2)
cezary.dodaj_ocene(3)
cezary.dodaj_ocene(2)
print('cezary:', cezary.srednia_ocen())
print('basia:', basia.srednia_ocen())
print()
print('oceny adama:', adam.oceny)
print('oceny basi:', basia.oceny)
print('oceny cezarego:', cezary.oceny)
l = [3,3,3]
dorota = Student('Dorota', 'X', l)
print('dorota:', dorota.srednia_ocen())
l.append(5)
print('dorota:', dorota.srednia_ocen())
dorota.dodaj_ocene(4)
print('dorota:', dorota.srednia_ocen())
print('l:', l)
# Wersja poprawiona - wewnątrz init tworzona jest zawsze nowa lista, być może wypełniona początkowymi elementami.
class Student:
def __init__(self, imie, nazwisko, oceny=()):
self.imie = imie
self.nazwisko = nazwisko
self.oceny = list(oceny)
def init_inna_wersja(self, imie, nazwisko, oceny=None):
self.imie = imie
self.nazwisko = nazwisko
if oceny:
self.oceny = list(oceny)
else:
self.oceny = []
def dodaj_ocene(self, ocena):
self.oceny.append(ocena)
def srednia_ocen(self):
return sum(self.oceny) / len(self.oceny)
adam = Student('Adam', 'Abacki', [3,4,5])
print('adam:', adam.srednia_ocen())
basia = Student('Barbara', 'Rabarbar')
basia.dodaj_ocene(5)
basia.dodaj_ocene(5)
print('basia:', basia.srednia_ocen())
cezary = Student('Cezary', 'Inny')
cezary.dodaj_ocene(2)
cezary.dodaj_ocene(3)
cezary.dodaj_ocene(2)
print('cezary:', cezary.srednia_ocen())
print('basia:', basia.srednia_ocen())
print()
print('oceny adama:', adam.oceny)
print('oceny basi:', basia.oceny)
print('oceny cezarego:', cezary.oceny)
l = [3,3,3]
dorota = Student('Dorota', 'X', l)
print('dorota:', dorota.srednia_ocen())
l.append(5)
print('dorota:', dorota.srednia_ocen())
dorota.dodaj_ocene(4)
print('dorota:', dorota.srednia_ocen())
print('l:', l)
import tkinter
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
def akcja():
imie = poleTekstowe.get()
label2.configure(text=f'Witaj {imie}!')
button1 = tkinter.Button(master=root, text='OK', font=('Arial', 24, 'bold'), command=akcja)
button1.pack()
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
root.mainloop()
# odczytanie aktualnej wartości pola: poleTekstowe.get()
# ustawienie nowej wartości w label-u : label2.configure(text='nowy tekst')
import tkinter
# w tej wersji program podzieliłem na funkcje, a wspólne zmienne zadeklarowałem jako global
def main():
global poleTekstowe, label2
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
button1 = tkinter.Button(master=root, text='OK', font=('Arial', 24, 'bold'), command=akcja)
button1.pack()
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
root.mainloop()
def akcja():
global poleTekstowe, label2
imie = poleTekstowe.get()
label2.configure(text=f'Witaj {imie}!')
if __name__ == '__main__':
main()
import tkinter
# w tej wersji oprócz kliknięcia guzika obsłużymy także naciśnięcie enter gdy jesteśmy w polu tekstowym
def main():
global poleTekstowe, label2
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
button1 = tkinter.Button(master=root, text='OK', font=('Arial', 24, 'bold'))
button1.pack()
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
# ustawiam obsługę zdarzenia "kliknięcie guzika"
button1.configure(command=akcja_guzikowa)
# aby dodać obsługę zdarzenia dla pola tekstowego, trzeba zastosować ogólną technikę "bind"
poleTekstowe.bind('<Return>', akcja_returnowa)
root.mainloop()
# akcja ustawiania jako command nie powinna przyjmować żadnych parametrów
def akcja_guzikowa():
global poleTekstowe, label2
imie = poleTekstowe.get()
label2.configure(text=f'Witaj {imie}!', fg='blue')
# akcja ustawiana za pomocą bind przyjmuje jeden parametr "event" - szczegóły zdarzenia
def akcja_returnowa(event):
global poleTekstowe, label2
imie = poleTekstowe.get()
label2.configure(text=f'Witaj {imie}!', fg='red')
if __name__ == '__main__':
main()
import tkinter
# w tej wersji oprócz kliknięcia guzika obsłużymy także naciśnięcie enter gdy jesteśmy w polu tekstowym
def main():
global poleTekstowe, label2
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
button1 = tkinter.Button(master=root, text='OK', font=('Arial', 24, 'bold'))
button1.pack()
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
# ustawiam obsługę zdarzenia "kliknięcie guzika"
button1.configure(command=akcja)
# aby dodać obsługę zdarzenia dla pola tekstowego, trzeba zastosować ogólną technikę "bind"
poleTekstowe.bind('<Return>', akcja)
root.mainloop()
# można zdefiniować tylko jedną funkcję z domyślnym parametrem - ona będzie działać w obu przypadkach
def akcja(event=None):
global poleTekstowe, label2
imie = poleTekstowe.get()
label2.configure(text=f'Witaj {imie}!')
if __name__ == '__main__':
main()
import tkinter
# w tej wersji oprócz kliknięcia guzika obsłużymy także naciśnięcie enter gdy jesteśmy w polu tekstowym
def main():
global poleTekstowe, label2
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
button1 = tkinter.Button(master=root, text='OK', font=('Arial', 24, 'bold'))
button1.pack()
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
# ustawiam obsługę zdarzenia "kliknięcie guzika"
button1.configure(command=lambda: label2.configure(text=f'Witaj {poleTekstowe.get()}!'))
# aby dodać obsługę zdarzenia dla pola tekstowego, trzeba zastosować ogólną technikę "bind"
poleTekstowe.bind('<Return>', lambda event: label2.configure(text=f'Witaj {poleTekstowe.get()}!'))
root.mainloop()
if __name__ == '__main__':
main()
import tkinter
# Ta wersja funkcji akcja jest uniwersalna: może zostać wywołana bez paramtru (jak robi button)
# oraz z parametrem (jak robi bind)
def akcja(event = None):
global poleTekstowe, label2
imie = poleTekstowe.get()
if imie.strip():
label2.configure(text=f'Witaj {imie}')
else:
label2.configure(text='')
def main():
global poleTekstowe, label2
root = tkinter.Tk()
root.title('Rozmowa')
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Jak masz na imię?', fg='black', font=('Arial', 24, 'bold'))
label1.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), bg='white')
poleTekstowe.pack()
button1 = tkinter.Button(master=root, text="OK", font=('Arial', 24, 'bold'), command=akcja)
button1.pack()
poleTekstowe.bind('<Return>', akcja)
label2 = tkinter.Label(master=root, text='', fg='blue', font=('Arial', 24, 'bold'))
label2.pack()
root.mainloop()
if __name__ == '__main__':
main()
import tkinter
root = tkinter.Tk()
root.mainloop()
# tkinter jest Pythonową nakładką na technologię TK (TCL-TK)
# tkinter jest częścią biblioteki standardowej Pythona
# Oprócz tego w Pythonie dostępne (po doinstalowaniu!) są także biblioteki
# pygtk - nakładka na technologię GTK (GTK to m.in. system okienkowy Gnome (Ubuntu), program Gimp...)
# pyqt - nakładka na QT (QT to m.in. system okienkowy KDE)
import tkinter as tk
# nazwę tego modułu często się skraca przy imporcie
print('Początek programu')
# Utworzenie obiektu "całe okno" - korzeń całej struktury komponentów
root = tk.Tk()
# Utworzenie komponentu typu Label, który "należy do" okna
label1 = tk.Label(master=root, text='Pierwszy napis')
# Dodanie do okna - komponent staje się widoczny
label1.pack()
# Jeśli potrzebuję późniejszego dostępu do tego komponentu, to zapisuję go na zmienną.
label2 = tk.Label(master=root, text='Drugi napis')
label2.pack()
# A jeśli dalszy los komponentu mnie nie interesuje, to mogę tak, bez zapisywanie na zmienną...
tk.Label(master=root, text='Trzeci napis').pack()
button1 = tk.Button(master=root, text="Klik Klik")
button1.pack()
button2 = tk.Button(master=root, text="Guzik 2")
button2.pack()
print('Zaraz wyświetlę okno')
# Wyświetlenie okna. Od tej pory aplikacja działa na zasadzie zasadzie obsługi zdarzeń.
root.mainloop()
print('Koniec programu')
import tkinter
root = tkinter.Tk()
root.geometry('800x600')
# Różne parametry (np. wygląd) można podać od razu podczas tworzenia komponentu.
label1 = tkinter.Label(master=root, text='Pierwszy napis',
fg='blue', font='Arial 40 bold')
label1.pack()
label2 = tkinter.Label(master=root, text='Drugi napis')
label2.pack()
tkinter.Label(master=root, text='Trzeci napis', font='Roboto 40').pack()
# Za pomocą configure w dowolnym momencie można zmienić parametry komponentu: wygląd, tekst itp.
# Z grubsza te same parametry, które ustawia się podczas towrzenia obiektu.
label2.configure(text='Nowy drugi napis', font='Times 33 italic', fg='red')
# specyfikację czcionki można też podać w formie tupli lub listy
button1 = tkinter.Button(master=root, text='Klik Klik', font=('Arial', 24, 'bold'))
button1.pack()
button2 = tkinter.Button(master=root, text='Guzik 2')
button2.pack()
# kolory można też podawać jak w CSS #RRGGBB (red green blue, każdy w zakresie od 00 do FF = 255)
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), fg='#880000', bg='#FFFFEE')
poleTekstowe.pack()
root.mainloop()
import tkinter
from tkinter import messagebox
def co_ma_sie_stac1():
messagebox.showinfo(title='Informacja',
message='Ojej naciśnięto pierwszy guzik')
def co_ma_sie_stac2():
'''Ta funkcja zostanie wywołana, gdy użytkownik naciśnie guzik 2'''
print('Kliknięto guzik 2')
root = tkinter.Tk()
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Pierwszy napis',
fg='blue', font='Arial 40 bold')
label1.pack()
label2 = tkinter.Label(master=root, text='Drugi napis')
label2.pack()
tkinter.Label(master=root, text='Trzeci napis', font='Roboto 40').pack()
label2.configure(text='Nowy drugi napis', font='Times 33 italic', fg='red')
button1 = tkinter.Button(master=root, text='Klik Klik', font=('Arial', 24, 'bold'), command=co_ma_sie_stac1)
button1.pack()
# Jako paramter command przekazujemy funkcję.
# Przkazujemy funkcję jako wartość - nie wywołujemy tej funkcji TERAZ, tylko ją przekazujemy.
# To tkinter wywoła tę funkcję, gdy użytkownik naciśnie guzik.
button2 = tkinter.Button(master=root, text='Guzik 2', command=co_ma_sie_stac2)
button2.pack()
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), fg='#880000', bg='#FFFFEE')
poleTekstowe.pack()
root.mainloop()
import tkinter
from tkinter import messagebox
licznik = 0
def co_ma_sie_stac1():
global licznik
licznik += 1
messagebox.showinfo(title='Informacja',
message=f'Naciśnięto pierwszy guzik po raz {licznik}')
root = tkinter.Tk()
root.geometry('800x600')
label1 = tkinter.Label(master=root, text='Pierwszy napis',
fg='blue', font='Arial 40 bold')
label1.pack()
label2 = tkinter.Label(master=root, text='Drugi napis')
label2.pack()
tkinter.Label(master=root, text='Trzeci napis', font='Roboto 40').pack()
button1 = tkinter.Button(master=root, text='Licznik', font=('Arial', 24, 'bold'), command=co_ma_sie_stac1)
button1.pack()
label2.configure(text='Jak masz na imię?', font='Times 33 italic', fg='red')
poleTekstowe = tkinter.Entry(root, font=('Consolas', 24), fg='#880000', bg='#FFFFEE')
poleTekstowe.pack()
button2 = tkinter.Button(master=root, text='Powitaj', font=('Arial', 24, 'bold'))
button2.pack()
label4 = tkinter.Label(master=root, font='Roboto 40', fg='green')
label4.pack()
def co_ma_sie_stac2():
imie = poleTekstowe.get()
label4.configure(text=f'Witaj {imie}')
button2.configure(command=co_ma_sie_stac2)
root.mainloop()
import tkinter
root = tkinter.Tk()
root.title('Nasza przykładowa apka')
root.geometry('800x600')
# atrybuty komponentów graficznych można ustawiać od razu podczas ich tworzenia:
label1 = tkinter.Label(master=root,
text='Ala ma kota',
font='Arial 40 bold',
fg='#0000FF',
bg='#AAFFFF')
label1.pack()
# atrybuty komponentów graficznych można też ustawiać
# wywołując metodę configure na już istniejącym obiekcie
label2 = tkinter.Label(master=root)
label2.configure(text='Ola ma psa', font=('Times New Roman', 37, 'italic'))
label2.configure(fg='red', bg='yellow')
label2.pack()
# Funkcję obsługującą zdarzenie można też stworzyć "w miejscu" za pomocą wyrażenia lambda.
button1 = tkinter.Button(master=root, text='Kliknij mnie',
font='Roboto 40 bold',
fg='blue', bg='#FFCCFF',
command=lambda: print('ojej, ktoś nacisnął guzik'))
button1.pack()
root.mainloop()
from tkinter import Tk, Label, Button
def co_ma_sie_stac():
global licznik, label2
licznik += 1
label2.configure(text=f'Licznik: {licznik}')
licznik = 0
root = Tk()
root.title('Nasza przykładowa apka')
root.geometry('800x600')
# atrybuty komponentów graficznych można ustawiać od razu podczas ich tworzenia:
label1 = Label(master=root,
text='Ala ma kota',
font='Arial 40 bold',
fg='#0000FF',
bg='#AAFFFF')
label1.pack()
# atrybuty komponentów graficznych można też ustawiać
# wywołując metodę configure na już istniejącym obiekcie
label2 = Label(master=root)
label2.configure(text='Licznik: 0', font=('Arial', 36, 'bold'))
label2.configure(fg='red', bg='white')
label2.pack()
# Funkcja co_ma_sie_stac zostanie odpalona gdy użytkownik naciśnie guzik
button1 = Button(master=root, text='Kliknij mnie',
font='Roboto 40 bold',
fg='blue', bg='#FFCCFF',
command=co_ma_sie_stac)
button1.pack()
root.mainloop()
import tkinter
import tkinter.ttk
import tkinter.messagebox
# główne okno
root = tkinter.Tk()
root.title('Nasza pierwsza apka')
root.geometry('800x600')
# komponenty okna
# pierwszy parametr root oznacza, że komponent należy do tego okna
# poza nim można przekazywać wiele innych parametrów (technicznie: **kwargs),
# za pomocą których ustala się styl i zawartość komponentów
tekst1 = tkinter.Label(root, text='Ala ma kota', font='Arial')
tekst1.pack()
tekst2 = tkinter.Label(root, text='Ola ma psa', font='Times 40 italic', foreground='red')
tekst2.pack()
tekst3 = tkinter.Label(root, text='Trzeci napis')
tekst3.pack()
# własności (wygląd, tekst itp.) można ustawiać także później, już po utworzeniu obiektów, za pomocą configure:
tekst3.configure(font=('Arial', 36, 'bold'), foreground='#008844')
font1 = ('Arial', 30)
pole = tkinter.Entry(root, font=font1, background='white')
pole.pack()
# pole tekstowe (Entry) nie przyjmuje parametru text
# nie zadziała:
# pole = tkinter.Entry(root, text='halo halo', font=font1, background='white')
pole2 = tkinter.Entry(root, font=font1, bg='white', fg='red')
pole2.pack()
# początkowy tekst, który ma być wyświetlony w polu można ustawić takim poleceniem:
pole2.insert(tkinter.END, 'początkowy tekst')
def co_robic():
tkinter.messagebox.showinfo('Ping', 'Ojej, naciśnięto guzik')
# Aby po wciśnięciu guzika nastapiła reakcja (żeby progra mcoś zrobił),
# to guzikowi przypisujemy komendę : command=
# tą komendą powinna być funkcja, która nie przyjmuje żadnego parametru
guzik = tkinter.Button(root, text='OK', font=font1, command=co_robic)
guzik.pack()
combo = tkinter.ttk.Combobox(root, values=['Ala', 'Ola', 'Ela'], font='Arial 28')
combo.pack()
#myphoto = tkinter.PhotoImage(file='obrazek.png')
#img_label = tkinter.Label(master=root, image=myphoto)
guzikBlue = tkinter.Button(root, text='Niebieskie', fg='blue')
guzikBlue.pack()
guzikRed = tkinter.Button(root, text='Czerwone', fg='red')
guzikRed.pack()
# w akcji obsługi zdarzeń możemy odczytywać i modyfikować wartości w komponentach
# - o ile tylko mamy dostęp do nich jako do zmiennych (tu są to zmienne globalne: pole, tekst3)
def ustaw_niebieskie():
tekst3.configure(fg='blue', text=pole.get())
def ustaw_czerwone():
tekst3.configure(fg='red', text=pole2.get())
# akcje obługi zdarzeń można podpiąć do guzików także później, już po ich utworzeniu:
guzikBlue.configure(command=ustaw_niebieskie)
guzikRed.configure(command=ustaw_czerwone)
root.mainloop()
import tkinter
import tkinter.ttk
import tkinter.messagebox
# główne okno
root = tkinter.Tk()
root.title('Nasza pierwsza apka')
root.geometry('800x600')
# komponenty okna
# pierwszy parametr root oznacza, że komponent należy do tego okna
# poza nim można przekazywać wiele innych parametrów (technicznie: **kwargs),
# za pomocą których ustala się styl i zawartość komponentów
tekst1 = tkinter.Label(root, text='Ala ma kota', font='Arial')
tekst1.pack()
tekst2 = tkinter.Label(root, text='Ola ma psa', font='Times 40 italic', foreground='red')
tekst2.pack()
tekst3 = tkinter.Label(root, text='Trzeci napis')
tekst3.pack()
# własności (wygląd, tekst itp.) można ustawiać także później, już po utworzeniu obiektów, za pomocą configure:
tekst3.configure(font=('Arial', 36, 'bold'), foreground='#008844')
font1 = ('Arial', 30)
pole = tkinter.Entry(root, font=font1, background='white')
pole.pack()
# pole tekstowe (Entry) nie przyjmuje parametru text
# nie zadziała:
# pole = tkinter.Entry(root, text='halo halo', font=font1, background='white')
pole2 = tkinter.Entry(root, font=font1, bg='white', fg='red')
pole2.pack()
# początkowy tekst, który ma być wyświetlony w polu można ustawić takim poleceniem:
pole2.insert(tkinter.END, 'początkowy tekst')
def co_robic():
tkinter.messagebox.showinfo('Ping', 'Ojej, naciśnięto guzik')
# Aby po wciśnięciu guzika nastapiła reakcja (żeby progra mcoś zrobił),
# to guzikowi przypisujemy komendę : command=
# tą komendą powinna być funkcja, która nie przyjmuje żadnego parametru
guzik = tkinter.Button(root, text='OK', font=font1, command=co_robic)
guzik.pack()
combo = tkinter.ttk.Combobox(root, values=['Ala', 'Ola', 'Ela'], font='Arial 28')
combo.pack()
guzikBlue = tkinter.Button(root, text='Niebieskie', fg='blue')
guzikBlue.pack()
guzikRed = tkinter.Button(root, text='Czerwone', fg='red')
guzikRed.pack()
# w akcji obsługi zdarzeń możemy odczytywać i modyfikować wartości w komponentach
# - o ile tylko mamy dostęp do nich jako do zmiennych (tu są to zmienne globalne: pole, tekst3)
def ustaw_niebieskie():
tekst3.configure(fg='blue', text=pole.get())
def ustaw_czerwone():
tekst3.configure(fg='red', text=pole2.get())
# akcje obługi zdarzeń można podpiąć do guzików także później, już po ich utworzeniu:
guzikBlue.configure(command=ustaw_niebieskie)
guzikRed.configure(command=ustaw_czerwone)
root.mainloop()
autor = 'Patryk'
# Coś na kształ eksportu...
domyslna_funkcja = geometry.figures.square_area
def add_matrices_version_1(m1, m2):
result = []
for row_i in range(len(m1)):
row = []
for col_i in range(len(m1[row_i])):
element = m1[row_i][col_i] + m2[row_i][col_i]
row.append(element)
result.append(row)
return result
def add_matrices_version_2(m1, m2):
result = []
for row_m1, row_m2 in zip(m1, m2):
row = []
for ele_m1, ele_m2 in zip(row_m1, row_m2):
row.append(ele_m1 + ele_m2)
result.append(row)
return result
def add_matrices(m1, m2):
return [[ele_m1 + ele_m2 for ele_m1, ele_m2 in zip(row_m1, row_m2)] for row_m1, row_m2 in zip(m1, m2)]
from math import sqrt
class Vector:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
def dlugosc(self):
return sqrt(self.x ** 2 + self.y ** 2)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __lt__(self, other):
return self.dlugosc() < other.dlugosc()
def __le__(self, other):
return self.dlugosc() <= other.dlugosc()
def __gt__(self, other):
return self.dlugosc() > other.dlugosc()
def __ge__(self, other):
return self.dlugosc() >= other.dlugosc()
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
# to daje możliwość mnożenia wektor * liczba
def __mul__(self, other):
return Vector(self.x * other, self.y * other)
# to daje możliwość mnożenia liczba * wektor
def __rmul__(self, other):
return self.__mul__(other)
def main():
a = Vector(x=10, y=20)
b = Vector(15, 5)
zerowy = Vector()
pionowy = Vector(y=10)
print(f'a = {a}')
print(f'b = {b}')
print()
suma = a + b
print(f'suma = {suma}')
roznica = a - b
print(f'rozn = {roznica}')
iloczyn1 = a * 3
print(f'iloczyn1 = {iloczyn1}')
iloczyn2 = 5 * b
print(f'iloczyn2 = {iloczyn2}')
print()
if __name__ == '__main__':
main()
# Opcja 1: z pakietu zaimportuj moduł, podaję ścieżkę bezwzględną
# from mathematica.geometry import measures
# from mathematica.podstawy import pomnoz
# Opcja 2: z pakietu zaimportuj moduł, podaję ścieżkę względną
from . import measures
# from .. import podstawy
from ..podstawy import pomnoz
def square_area(a, b):
return pomnoz(a, b)
def triangle_area(a, h):
return a * h * 0.5
def circle_area(r):
from math import pi
return pi * r**2
def square_diagonal(a):
return measures.cartesian_distanse(a, a)
# Opcja 1: z modułu importuję funkcję, podaję ścieżkę bezwzględną
# from mathematica.geometry.measures import cartesian_distanse
# Opcja 2: z pakietu zaimportuj moduł, podaję ścieżkę względną
from .measures import cartesian_distanse
def square_area(a, b):
return a * b
def triangle_area(a, h):
return a * h * 0.5
def circle_area(r):
from math import pi
return pi * r**2
def square_diagonal(a):
return cartesian_distanse(a, a)
def cartesian_distanse(x, y):
return (x**2 + y**2)**0.5
def dodaj(x, y):
return x + y
def pomnoz(x, y):
return x * y
# Z pakietu mathematica.algebra (ścieżka bezwzględna) import modułu matrices
# tak jakby /mathematica/algebra/matrices.py
from mathematica.algebra import matrices
def test_add_matrices():
a = [
[1, 2, 3],
[4, 5, 6],
]
b = [
[7, 8, 9],
[10, 11, 12],
]
result = matrices.add_matrices(a, b)
assert result == [
[8, 10, 12],
[14, 16, 18],
]
def test_sub_matrices():
a = [
[12, 11, 10],
[9, 8, 7],
]
b = [
[1, 2, 3],
[4, 5, 6],
]
result = matrices.sub_matrices(a, b)
assert result == [
[11, 9, 7],
[5, 3, 1],
]
# Można importować podając ścieżkę bezwzględną
# from mathematica.geometry import figures
# Ale jeśli jesteśmy w tym pakiecie (mathematica.test),
# to możemy importować podając ścieżkę względną
# To odpowiada ścieżce do plików: ../geometry/figures.py
# Trzeba wejść poziom wyżej, bo jesteśmy w pakiecie tests
from ..geometry import figures
def test_square_area():
assert figures.square_area(a=2, b=3) == 6
def test_triangle_area():
assert figures.triangle_area(a=2, h=4) == 4
from .algebra.matrices import add_matrices
m1 = [[1,1],
[2,2],
[3,4]]
m2 = [[0,1],
[1,0],
[10,10]]
wynik = add_matrices(m1, m2)
print(wynik)
print()
\ No newline at end of file
# To jest przykład "modułu", czyli pliku, który może być imporotwany przez inne pliki (moduły, programy)
print('Początek modułu. Teraz __name__ == ', __name__)
MIASTO='Katowice'
def pole_kwadratu(a):
return a*a
def wypisz_tekst(tekst, ile_razy):
for i in range(ile_razy):
print(tekst)
class Klasa:
def metoda(self):
print('To jest metoda')
if __name__ == '__main__':
print(' O, teraz modul został uruchomiony jako program')
wypisz_tekst(' __name__ == __main__', 2)
else:
print(' Teraz moduł jest importowany')
print('Koniec modułu')
print('Początek programu, teraz __name__ == ', __name__)
print('Zaraz będzie import...')
import modul
# Przy taki sposobie importowania trzeba używać nazwy modułu przed nazwami funkcji
wynik = modul.pole_kwadratu(5)
modul.wypisz_tekst(f'Ala ma {wynik} kotów.', 3)
obiekt = modul.Klasa()
obiekt.metoda()
print(modul.MIASTO)
print('Próba drugiego importu')
# Moduł jest importowany tylko jeden raz. Kolejny import już nic nie robi.
print('Koniec programu')
import modul as m
#ERR wynik = modul.pole_kwadratu(5)
# Przy taki sposobie importowania trzeba używać aliasu przed nazwami funkcji
wynik = m.pole_kwadratu(5)
m.wypisz_tekst(f'Ala ma {wynik} kotów.', 3)
obiekt = m.Klasa()
obiekt.metoda()
print(m.MIASTO)
from modul import wypisz_tekst, Klasa, MIASTO
# Przy takim sposobie importowania w kodzie używamy samych nazw funkcji
# a nie nie możemy już uzywać nazwy moduły (i dostawać się do innych funkcji)
# wynik = modul.pole_kwadratu(5)
# modul.wypisz_tekst(f'Ala i jej kot', 3)
wypisz_tekst(f'Ala mieszka w {MIASTO}', 3)
obiekt = Klasa()
obiekt.metoda()
print(MIASTO)
from modul import *
# Przy takim sposobie importowania w kodzie używamy samych nazw funkcji,
# zaimportowane są wszystkie globalne definicje z tamtego pliku.
# wynik = modul.pole_kwadatu(5)
wynik = pole_kwadratu(5)
wypisz_tekst(f'Ala mieszka w {MIASTO}', 3)
obiekt = Klasa()
obiekt.metoda()
print(MIASTO)
def jakas_funkcja(x):
# "import lokalny"
from modul import pole_kwadratu
print(pole_kwadratu(x))
# nie można skorzystać poza funkcją
# pole_kwadratu(8)
# nawet gdy funckje wywołuję wielokrotnie, albo wiele takich funkcji, to moduł importuje się raz
print('AAA')
jakas_funkcja(7)
print('BBB')
jakas_funkcja(6)
print('CCC')
from setuptools import setup, find_packages
setup(
name='mathematica',
version='1.0.0',
description='Math utils.',
packages=find_packages(exclude=['mathematica.tests']),
)
# Aby zbudować paczkę w formie zipa używamy:
# python setup.py sdist --format=zip
# - to daje wersję ze źródłami, którą łatwiej zainstalować
# lub ewentualnie
# python setup.py bdist
# - co daje wersję "binarną"/"skompilowaną", którą trudniej zainstalować - może być to nieprzenośne między systemami
# Po zbudowaniu paczki za pomocą sdist w docelowej lokalizacji można wykonać polecenie
# pip install mathematica-1.0.0.zip
# i pakiet oraz jego moduły staną się dostępne
import mathematica.algebra.matrices
import mathematica.podstawy
# Sposób importowania pokazany tutaj: import PAKIET.MODUL
# Konsekwencja: podczas wywoływania funkcji lub klas trzeba wpisywać pełną ścieżkę
wynik = mathematica.podstawy.pomnoz(2, 3)
print(wynik)
m1 = [[1,1],
[2,2],
[3,4]]
m2 = [[0,1],
[1,0],
[10,10]]
wynik = mathematica.algebra.matrices.add_matrices(m1, m2)
print(wynik)
import mathematica
print(mathematica.autor)
print(mathematica.domyslna_funkcja(7, 5))
from mathematica.algebra.matrices import *
from mathematica.podstawy import pomnoz
# Sposób importowania pokazany tutaj: from PAKIET.MODUL import FUNKCJA
wynik = pomnoz(2, 3)
print(wynik)
m1 = [[1,1],
[2,2],
[3,4]]
m2 = [[0,1],
[1,0],
[10,10]]
wynik = add_matrices(m1, m2)
print(wynik)
print()
from mathematica import autor
print(autor)
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment