Kopiowanie

Kod nr 1

old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]
new_list = old_list

new_list[2][2] = 9

print('Old List:', old_list)
print('ID of Old List:', id(old_list))

print('New List:', new_list)
print('ID of New List:', id(new_list))

Kod nr 2

import copy

old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
new_list = copy.copy(old_list)

old_list.append([4, 4, 4])

print("Old list:", old_list)
print("New list:", new_list)

Kod nr 3

import copy

old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]
new_list = copy.copy(old_list)

new_list[2][2] = 9

print('Old List:', old_list)
print('ID of Old List:', id(old_list))

print('New List:', new_list)
print('ID of New List:', id(new_list))

Kod nr 4

import copy

old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 'a']]
new_list = copy.deepcopy(old_list)

new_list[2][2] = 9

print('Old List:', old_list)
print('ID of Old List:', id(old_list))

print('New List:', new_list)
print('ID of New List:', id(new_list))

Kod 4b

import copy

class Person:

    def __init__(self, age, name):
        self.age = age
        self.name = name


p1 = Person(20, "Jan")
p2 = copy.copy(p1)
print(id(p1))
print(id(p1.name))
print(id(p2))
print(id(p2.name))
p1.name = "Anna"
print(id(p1.name))
print(id(p2.name))

Kod nr 4c

import copy

class Person:

    def __init__(self, age, name, children):
        self.age = age
        self.name = name
        self.children = children


p1 = Person(20, "Jan", ["Anna","Krzysztof"])
p2 = copy.copy(p1)
print(id(p1))
print(id(p1.children))
print(id(p2))
print(id(p2.children))
p1.children[1] = "Tomasz"
print(id(p1.children))
print(id(p2.children))

Kod nr 4d

import copy

class Person:

    def __init__(self, age, name, children):
        self.age = age
        self.name = name
        self.children = children


p1 = Person(20, "Jan", ["Anna","Krzysztof"])
p2 = copy.deepcopy(p1)
print(id(p1))
print(id(p1.children))
print(id(p2))
print(id(p2.children))
p1.children[1] = "Tomasz"
print(id(p1.children))
print(id(p2.children))

Kod nr 4e

import copy

class Person:

    def __init__(self, age, name, children):
        self.age = age
        self.name = name
        self.children = children

    def __copy__(self):
        return Person(self.age, self.name, self.children.copy())

    def __deepcopy__(self, memodict = {}):
        return Person(self.age, self.name[:-1][:-1], self.children.copy())


p1 = Person(20, "Jan", ["Anna","Krzysztof"])
p2 = copy.copy(p1)
print(id(p1) == id(p2))
print(id(p1.age) == id(p2.age))
print(id(p1.name) == id(p2.name))
print(id(p1.children) == id(p2.children))
p3 = copy.deepcopy(p1)
print(id(p1) == id(p3))
print(id(p1.age) == id(p3.age))
print(id(p1.name) == id(p3.name))
print(id(p1.children) == id(p3.children))

https://www.pythonforthelab.com/blog/deep-and-shallow-copies-of-objects/

Obsługa błędów

Dokumentacja https://docs.python.org/3/tutorial/errors.html

Kodn nr 5

10 * (1/0)
4 + spam*3
'2' + 2

Kod nr 6

while True:
    try:
        x = int(input("Please enter a number: "))
        break
    except ValueError:
        print("Oops!  That was no valid number.  Try again...")


print("number", x)

Kod nr 7

try:
    raise Exception('spam', 'eggs')
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    print(inst)          # __str__ allows args to be printed directly,
                         # but may be overridden in exception subclasses
    x, y = inst.args     # unpack args
    print('x =', x)
    print('y =', y)

Kod nr 8

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")

Kod nr 9

def this_fails():
    x = 1/0

try:
    this_fails()
except ZeroDivisionError as err:
    print('Handling run-time error:', err)

Kod nr 10

try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
    raise

Kod nr 11

try:
    raise KeyboardInterrupt
finally:
    print('Goodbye, world!')

Kod nr 12

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")


divide(2, 1)
divide(2, 0)
divide("2", "1")

Ćwiczenie. Stwórz klasę Calculator i dodaj w niej kilka metod (bez __) symulujących operacje arytmetyczne. Zabezpiecz działanie przed wykrzucaniem błędów.

Dekoratory

Dekoratory to pewien “sposób” na wykonywanie funkcji na funkcjach.

kod nr 13

def shout(text):
    return text.upper()


print(shout('Hello'))
yell = shout
print(yell('Hello'))

kod nr 14

def up(text):
    return text.upper()


def down(text):
    return text.lower()


def greet(func):
    test = func("abcXYZ")
    print(test)


greet(up)
greet(down)

kod nr 15

def create_adder(x):
    def adder(y):
        return x + y

    return adder


add_15 = create_adder(15)

print(add_15(10))

kod nr 16

def hello_decorator(func):
    def inner1():
        print("Hello, this is before function execution")
        func()
        print("This is after function execution")
    return inner1


def function_to_be_used():
    print("This is inside the function !!")


function_to_be_used = hello_decorator(function_to_be_used)
function_to_be_used()

kod nr 17

def hello_decorator(func):
    def inner1(*args, **kwargs):
        print("before Execution")
        returned_value = func(*args, **kwargs)
        print("after Execution")
        return returned_value

    return inner1


@hello_decorator
def sum_two_numbers(a, b):
    print("Inside the function")
    return a + b


a, b = 1, 2
print("Sum =", sum_two_numbers(a, b))

kod nr 18

def decor1(func):
    def inner():
        x = func()
        return x * x

    return inner


def decor(func):
    def inner():
        x = func()
        return 2 * x

    return inner


@decor1
@decor
def num():
    return 10


print(num())

Kod nr 18 jest równoważny decor1(decor(num))

Dekoratory z parametrem

kod nr 19

@decorator(params)
def func_name():
    ''' Function implementation'''

jest równoważny

kod nr 20

def func_name():
    ''' Function implementation'''

func_name = (decorator(params))(func_name)

kod nr 21

def decorator_fun(func):
    print("Inside decorator")

    def inner(*args, **kwargs):
        print("Inside inner function")
        print("Decorated the function")
        func()

    return inner


@decorator_fun
def func_to():
    print("Inside actual function")


func_to()

kod nr 22

def decorator_fun(func):
    print("Inside decorator")

    def inner(*args, **kwargs):
        print("Inside inner function")
        print("Decorated the function")

        func()

    return inner


def func_to():
    print("Inside actual function")


decorator_fun(func_to)()

Praktyczne zastosowanie

kod nr 23

import functools
import time

def timer(func):
    @functools.wraps(func)
    def wrapper_timer(*args, **kwargs):
        start_time = time.perf_counter()    # 1
        value = func(*args, **kwargs)
        end_time = time.perf_counter()      # 2
        run_time = end_time - start_time    # 3
        print(f"Finished {func.__name__!r} in {run_time:.4f} secs")
        return value
    return wrapper_timer

@timer
def waste_some_time(num_times):
    for _ in range(num_times):
        sum([i**2 for i in range(10000)])


waste_some_time(5)

kod nr 24

import functools


def debug(func):
    @functools.wraps(func)
    def wrapper_debug(*args, **kwargs):
        args_repr = [repr(a) for a in args]  # 1
        kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]  # 2
        signature = ", ".join(args_repr + kwargs_repr)  # 3
        print(f"Calling {func.__name__}({signature})")
        value = func(*args, **kwargs)
        print(f"{func.__name__!r} returned {value!r}")  # 4
        return value

    return wrapper_debug


@debug
def silnia(n):
    if n == 0 or n == 1:
        return 1
    return n * silnia(n - 1)


print(silnia(7))

kod nr 25

import functools
import math


def debug(func):
    @functools.wraps(func)
    def wrapper_debug(*args, **kwargs):
        args_repr = [repr(a) for a in args]  # 1
        kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]  # 2
        signature = ", ".join(args_repr + kwargs_repr)  # 3
        print(f"Calling {func.__name__}({signature})")
        value = func(*args, **kwargs)
        print(f"{func.__name__!r} returned {value!r}")  # 4
        return value

    return wrapper_debug


math.factorial = debug(math.factorial)


def approximate_e(terms=18):
    return sum(1 / math.factorial(n) for n in range(terms))


print(approximate_e(10))

Właściwości

Kod nr 26

class Point:
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def get_x(self):
        return self.__x

    def set_x(self, value):
        self.__x = value

    def get_y(self):
        return self.__y

    def set_y(self, value):
        self.__y = value


point = Point(12, 5)
print(point.get_x())
print(point.get_y())
point.set_x(42)
print(point.get_x())
# print(point.__x)

Kod nr 27

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


point = Point(12, 5)
print(point.x)

Kod nr 28

class Circle:
    def __init__(self, radius):
        self.__radius = radius

    def _get_radius(self):
        print("Get radius")
        return self.__radius

    def _set_radius(self, value):
        print("Set radius")
        self.__radius = value

    def _del_radius(self):
        print("Delete radius")
        del self.__radius

    radius = property(
        fget=_get_radius,
        fset=_set_radius,
        fdel=_del_radius,
        doc="The radius property."
    )


circle = Circle(42.0)
print(circle.radius)
circle.radius = 100.0
print(circle.radius)
del circle.radius
# print(circle.radius)
help(circle)

Kod nr 29

class Point:
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def get_x(self):
        return self.__x

    def set_x(self, value):
        self.__x = value

    def get_y(self):
        return self.__y

    def set_y(self, value):
        self.__y = value

    x = property(get_x, set_x)


point = Point(12, 5)
print(point.get_x())
print(point.x)
point.x = 22
print(point.get_x())

Kod nr 30

class Circle:
    def __init__(self, radius):
        self.__radius = radius

    @property
    def radius(self):
        """The radius property."""
        print("Get radius")
        return self.__radius

    @radius.setter
    def radius(self, value):
        print("Set radius")
        self.__radius = value

    @radius.deleter
    def radius(self):
        print("Delete radius")
        del self.__radius


circle = Circle(42.0)
print(circle.radius)
circle.radius = 100.0
print(circle.radius)
del circle.radius
# print(circle.radius)
help(circle)

Kod nr 31

class Point:
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    @property
    def x(self):
        return self.__x

    @property
    def y(self):
        return self.__y


point = Point(12, 5)
print(point.x)
# point.x = 3

Kod nr 32

class WriteCoordinateError(Exception):
    pass

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        raise WriteCoordinateError("x coordinate is read-only")

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        raise WriteCoordinateError("y coordinate is read-only")


point = Point(12, 5)
print(point.x)
point.x = 3

Kod nr 33

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = float(value)

    @property
    def diameter(self):
        return self.radius * 2

    @diameter.setter
    def diameter(self, value):
        self.radius = value / 2
        
        
circle = Circle(42)
print(circle.radius)
print(circle.diameter)
circle.diameter = 100
print(circle.radius)
print(circle.diameter)

Kod nr 34

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def radius(self):
        raise AttributeError("Radius is write-only")

    @radius.setter
    def radius(self, value):
        self._radius = float(value)



circle = Circle(42)
# print(circle.radius)
circle.radius = 100