class MyClass:
x = 55
name = "Allie Trent"
attr_list = ["Bones", "Food", "Frisbee"]Python Fundamentals
Python Fundamentals
Concepts and methods on the fundamentals of Python.
Modules & Methods
Modules contain a “library” of methods
Object Oriented Programming (OOP)
Classes
Consists of attributes and methods
Example: Car
Attributes: fuel, max speed, color
Method (function): refuel(), setSpeed()
Methods create attributes for classes
Creating a class
MyClass.name'Allie Trent'
Methods in a class
class Methods_Class:
x = "Hello World"
def my_method():
print("Contents of my_method")
def subtractor(num_one, num_two):
product = num_one - num_two
print(f"{num_two} - {num_one} = {product}")
def print_stuff(a, b):
print(a, b)print(Methods_Class)
print(Methods_Class.x)
print(Methods_Class.my_method)
print(Methods_Class.my_method())
print(Methods_Class.subtractor(20, 5))
print(Methods_Class.print_stuff(3, "Hello"))<class '__main__.Methods_Class'>
Hello World
<function Methods_Class.my_method at 0xffffab79b400>
Contents of my_method
None
5 - 20 = 15
None
3 Hello
None
__init__
Function defined at the start of a class
class Animals:
def __init__(self, size, noise, color, num_of_legs):
self.size = size
self.noise = noise
self.color = color
self.num_of_legs = num_of_legsdog = Animals("Large", "Woof", "Liver & White", 4)
dog<__main__.Animals at 0xffffab81e590>
dog.noise'Woof'
Using attributes in a method
class Animals:
def __init__(self, species, name, noise, color):
self.species = species
self.name = name
self.noise = noise
self.color = color
def describe(self):
print(f"{self.name} is {self.color} which makes a {self.noise} noise")dog = Animals("Dog", "Allie", "Woof", "Liver & White")
cat = Animals("Cat", "Misty", "Meow", "Black")dog.describe()Allie is Liver & White which makes a Woof noise
Changing variable names in a class object
class Ages:
def __init__(self, age):
self.age = age
def plus_year(self):
self.age += 1
def show_age(self):
print(f"Your age is {self.age}")me = Ages(27)me.plus_year()
me.show_age()Your age is 28
class Warrior:
def __init__(self, name, strength, health):
self.name = name
self.strength = strength
self.health = health
def report(self):
print(f"Hi {self.name}, your strength is {self.strength} and health is {self.health}")
def heal(self):
self.health += 1
def damage(self):
self.health -= 1
def workout(self):
self.strength += 1character = Warrior("Geocoug", 60, 100)[character.damage() for i in range(8)]
character.report()
[character.heal() for i in range(5)]
character.report()
character.workout()
character.report()Hi Geocoug, your strength is 60 and health is 92
Hi Geocoug, your strength is 60 and health is 97
Hi Geocoug, your strength is 61 and health is 97
Practical Example - PayFriend
Create an online bank where: - User can create a new account that includes: Account type (current, savings, etc), name of account holder, account balance, etc. - User can withdraw or deposit money, or check balance
class Banking:
def __init__(self, name, account, balance):
self.name = name
self.account = account
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def report(self):
print(f"{self.name}, the balance of {self.account} is ${self.balance}")my_account = Banking("Geocoug", "Savings", 1000)my_account.deposit(50)
my_account.report()
my_account.withdraw(500)
my_account.report()Geocoug, the balance of Savings is $1050
Geocoug, the balance of Savings is $550
Functional Programming
Lambda
Quicker way of creating functions
def some_func(x):
y = x + 2
lambda x: x + 2<function __main__.<lambda>(x)>
lambda_func = lambda x: x + 2
lambda_func(6)8
other_func = lambda name: f"Hello there, {name}"
other_func("Geocoug")'Hello there, Geocoug'
another_func = lambda x, y: x + y
another_func(3, 4)7
Map
Apply the same function/operation on all elements in a list
map(name of function, name of list)
# using map as a normal function
somelist = [1, 10, 20, 15]
def divider(x):
y = x / 5
return y
newlist = list(map(divider, somelist))
newlist[0.2, 2.0, 4.0, 3.0]
somelist = [1, 10, 20, 15]
newlist = list(map(lambda x: x / 5, somelist))
newlist[0.2, 2.0, 4.0, 3.0]
num_tuple = (1, 10, 20, 15)
new_tuple = tuple(map(lambda x: x / 5, num_tuple))
new_tuple(0.2, 2.0, 4.0, 3.0)
list_one = [1, 2, 3, 4]
list_two = [90, 80, 70, 60]
new_list = map(lambda x, y: x + y, list_one, list_two)
list(new_list)[91, 82, 73, 64]
Filter
my_list = [1, 14, 53, 72, 22, 99]
filtered_list = filter(lambda x: x >= 50, my_list)
list(filtered_list)[53, 72, 99]
Generators
Generators - yield instead of return. Return terminates local variables, yield ‘pauses’.
See - How do python generators work?
def a():
x = 5
yield x
a()<generator object a at 0xffffab9637d0>
def a():
x = 5
yield x
x += 1
yield x
example = a()
print(next(example))
print(next(example))
print(next(example))5
6
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) Cell In[30], line 9 7 print(next(example)) 8 print(next(example)) ----> 9 print(next(example)) StopIteration:
def generator_fn(x):
for i in range(x):
yield iimport sys
sys.getsizeof(example) # bytes104
g = generator_fn(100_000_000)dir(g)['__class__',
'__del__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__lt__',
'__name__',
'__ne__',
'__new__',
'__next__',
'__qualname__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'close',
'gi_code',
'gi_frame',
'gi_running',
'gi_yieldfrom',
'send',
'throw']
next(g)0
next(g)1
next(g)2
help(g)Help on generator object:
generator_fn = class generator(object)
| Methods defined here:
|
| __del__(...)
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| Implement next(self).
|
| __repr__(self, /)
| Return repr(self).
|
| close(...)
| close() -> raise GeneratorExit inside generator.
|
| send(...)
| send(arg) -> send 'arg' into generator,
| return next yielded value or raise StopIteration.
|
| throw(...)
| throw(value)
| throw(type[,value[,tb]])
|
| Raise exception in generator, return next yielded value or raise
| StopIteration.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| gi_code
|
| gi_frame
|
| gi_running
|
| gi_yieldfrom
| object being iterated by yield from, or None
Nested Generators
def inner():
print("We're inside")
value = yield 2
print("Received", value)
return 4
def outer():
yield 1
retval = yield from inner()
print("Returned", retval)
yield 5g = outer()next(g)1
next(g)We're inside
2
g.send(3)Received 3
Returned 4
5
Generator vs. List Comprehension
import timen = 100_000_000start = time.time()
x = [i * i for i in range(n)]
end = time.time()
print(type(x))
print(f"{end - start:.4f}")<class 'list'>
4.3685
start = time.time()
g = (i * i for i in range(n))
end = time.time()
print(type(g))
print(f"{end - start:.4f}")<class 'generator'>
0.0001