Finished python basics, half of advanced

This commit is contained in:
2022-09-15 21:27:49 -04:00
parent af0adc035c
commit 6116fab394
15 changed files with 526 additions and 13 deletions

View File

@@ -1,8 +1,26 @@
const pythonSidebar = [
{
text: 'Test',
text: 'Python Basics',
items: [
{text: 'Introduction', link: '/'},
{text: 'Introduction', link: '/python/'},
{text: 'Types', link: '/python/basics/types'},
{text: 'Classes', link: '/python/basics/classes'},
{text: 'Functions', link: '/python/basics/functions'},
{text: 'Control Flow', link: '/python/basics/controlflow'},
{text: 'Decorators', link: '/python/basics/decorators'},
{text: 'Exceptions', link: '/python/basics/exceptions'},
{text: 'Enums', link: '/python/basics/enums'},
{text: 'Generators', link: '/python/basics/generators'},
{text: 'Virtual Environment', link: '/python/basics/venv'}
]
},
{
text: 'Advanced',
items: [
{text: 'Collections', link: '/python/advanced/collections'},
{text: 'Dates', link: '/python/advanced/dates'},
{text: 'Debugging', link: '/python/advanced/debugging'},
]
}
]
@@ -11,15 +29,11 @@ export default {
title: 'Docs.Dietrick.Dev',
descript: 'A collection of notes and snippets',
themeConfig: {
socialLinks: [
{ icon: 'github', link: 'https://gitlab.com/djdietrick/docs'}
],
sidebar: {
'/python/': [
{
text: 'Test',
items: [
{text: 'Introduction', link: '/'},
]
}
],
'/python/': pythonSidebar,
'/': [
{
text: 'Home',

View File

@@ -1 +1,3 @@
# Languages
[Python](/python/)

View File

@@ -0,0 +1,45 @@
# Collections
There are a number of interesting and useful collections in Python.
## Counter
```python
from collections import Counter
mylist = [1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3]
print(Counter(mylist))
print(Counter("Hello world"))
sentence = "Hello, this is a sentence"
c = Counter(sentence.lower().split())
print(c.most_common(2)) # 2 most common words
sum(c.values()) # total of all counts
c.clear() # reset all counts
list(c) # list unique elements
set(c) # convert to a set
dict(c) # convert to a regular dictionary
c.items() # convert to a list of (elem, cnt) pairs
c += Counter() # remove zero and negative counts
```
## Default Dictionary
```python
from collections import defaultdict
d = defaultdict(lambda: 0) # Default all new values to 100
d['correct'] = 100
print(d['correct']) # 100
print(d['WRONG']) # 0
```
## Named Tuple
```python
from collections import namedtuple
Dog = namedtuple('Dog', ['age','breed','name'])
sammy = Dog(age=5,breed='Husky',name='Sammy')
print(sammy) # Dog(age=5, breed='Husky', name='Sammy')
print(sammy.name) # Sammy
print(sammy[2]) # Sammy
```

View File

@@ -0,0 +1,35 @@
# Dates
```python
import datetime
t = datetime.time(4, 20, 1)
# Let's show the different components
print(t) # 04:20:01
print('hour :', t.hour) # 4
print('minute:', t.minute) # 20
print('second:', t.second) # 1
print('microsecond:', t.microsecond) # 0
print('tzinfo:', t.tzinfo) # None
today = datetime.date.today()
print(today) # YYYY-MM-DD
print('ctime:', today.ctime())
print('tuple:', today.timetuple())
print('ordinal:', today.toordinal())
print('Year :', today.year)
print('Month:', today.month)
print('Day :', today.day)
d1 = datetime.date(2015, 3, 11)
print('d1:', d1) # 2015-03-11
d2 = d1.replace(year=1990)
print('d2:', d2) # 1990-03-11
result = d1 - d2
print(result.days) # 9131
print(result.seconds) # 0
print(result.total_seconds) # difference in seconds
```

View File

@@ -0,0 +1,17 @@
# Debugging
Debugging is achieved by using the `pdb` package and setting a breakpoint with `pdb.set_trace()`. From that point, you get a python shell with access to all of the objects currently in scope.
To navigate through the code, you can use `n` to go to the next line, or `s` to step in to a function call. When ready to continue the processing, use `c`.
```python
import pdb
x = [1,2,3]
y = 2
z = 3
res1 = y + z
pdb.set_trace()
res2 = x + y
```

View File

@@ -0,0 +1,104 @@
# Classes
## Basics
Classes are defined by the `class` keyword and are followed by `():`. The constructor is defined by the `__init__` function, where you can pass in parameters and save them on the class instance. The destructor is defined by the `__del__` function.
You can also define class object variable outside of the constructor, and this will apply to all instances of the class. This is mutable but then only applies to that instance of the class.
You define class methods the same way as you do normal [functions](./functions). Pass in the `self` keyword to access instance variables.
```python
class Foo():
bar = 'bar' # Class object variable
# Constructor
def __init__(self, name):
self.name = name # Instance variable
# Destructor
def __del__(self):
print("{} died :(".format(self.name))
def func(self):
print(self.prop)
```
## Overriding methods
You can override default methods within your classes to perform different behavior based on the class instance. This can be done with base python methods such as `__str__` or `__len__`, as well as any other inheritted functions.
```python
class Foo():
# This would appear if you performed print(foo) where foo is an instance of Foo
def __str__(self):
return f"Hello, my name is {self.name}"
def __len__(self):
return 5
```
## Inheritance
To inherit from a class in python, you simply provide that class within the parenthesis when defining your child class.
To create abstract classes, python provides a `NotImplementedError` exception that will throw if the function is attempted to be called by a class that does not define it.
```python
class Animal():
def __init__(self, name):
self.name = name
def who_am_i(self):
print("I am an animal")
def eat(self):
print("I am eating")
# Makes Animal an abstract class
def speak(self):
raise NotImplementedError("Subclass must implement this abstract method")
class Dog(Animal):
# Class object attribute, the same for all instances
species = 'mammal'
def __init__(self, breed, name):
Animal.__init__(self,name)
self.breed = breed
self.name = name
def __str__(self):
return self.name
def bark(self):
print("Woof! My name is {}".format(self.name))
# Overridden function from base class
def who_am_i(self):
print("I am a dog!")
# Implementing the abstact function
def speak(self):
return self.name + " says woof!"
class Cat(Animal):
def __init__(self, name):
Animal.__init__(self,name)
def speak(self):
return self.name + " says meow!"
my_dog = Dog(breed='Lab', name='Frankie')
print(my_dog.breed) # Lab
print(my_dog) # Frankie, because we overrode the __str__ operator
my_dog.eat() # Calling method on base Animal class
my_dog.who_am_i() # Calling instance on Dog class
my_cat = Cat('Sampson')
for pet in [my_dog, my_cat]:
print(type(pet)) # Dog, Cat
print(pet.speak()) # says woof!, says meow!
```

View File

@@ -0,0 +1,74 @@
# Control Flow
## If/Else
If/else statements in python are pretty straightforward and similar to other languages. `elif` is used instead of else if, and there are no parenthesis when stating the conditions.
```python
num = 3
if num == 1:
print("1")
elif num == 2:
print("2")
else:
print("Other")
```
## For loops
For loops can iterate over lots of data structures. Range is exclusive of the end, and inclusive of the beginning.
```python
fruits = ["apple", "banana", "cherry"]
for x in fruits:
print(x)
for x in "banana":
print(x)
for x in range(6):
print(x) # Prints 0-5
for x in range(2,6):
print(x) # Prints 2-5
```
You can also use an else block after the for loop to run some code after the loop has finished. However, if the for loop is escaped with `break`, it won't run.
```python
for x in range(6):
print(x)
else:
print("I will be shown!")
for x in range(6):
if x == 3: break
print(x)
else:
print("I will not be shown :(")
```
## While loops
Very similar to for loops in syntax and behavior. Can also include else statements to run after the loop concludes.
```python
i = 1
while i < 6:
print(i)
i += 1
else:
print("Finished")
```
## Match
New in Python 3.10, you can now perform match statements in python.
```python
num = 1
match num:
case 1:
print("1")
case 2:
print("2")
case _:
print("other")
```

View File

@@ -0,0 +1,16 @@
# Decorators
Decorators can be added to functions to run additional code before or after the function run.
```python
def decorator(original_func):
def wrap_func():
print("Before executing original function")
original_func()
print("After executing original function")
return wrap_func
@decorator
def my_func():
print("Executing my function")
```

View File

@@ -0,0 +1,60 @@
# Enums
Enums are kind of hacky in python. See the below example.
```python
import enum
# Enums are kind of hacky, use a class
class Animal(enum.Enum):
dog = 1
cat = 2
lion = 3
# printing enum member as string
print(f"The string representation of enum member is : {Animal.dog}") # Animal.dog
# printing enum member as repr
print(f"The repr representation of enum member is : {repr(Animal.dog)}") # <Animal.dog: 1>
# printing the type of enum member using type()
print ("The type of enum member is : ",end ="")
print (type(Animal.dog)) # <enum 'Animal'>
# printing name of enum member using "name" keyword
print ("The name of enum member is : ",end ="")
print (Animal.dog.name) # dog
# Accessing enum member using value
print ("The enum member associated with value 2 is : ",end="")
print (Animal(2)) # Animal.cat
# Accessing enum member using name
print ("The enum member associated with name lion is : ",end="")
print (Animal['lion']) # Animal.lion
# Assigning enum member
mem = Animal.dog
# Displaying value
print ("The value associated with dog is : ",end="")
print (mem.value) # 1
# Displaying name
print ("The name associated with dog is : ",end="")
print (mem.name) # dog
# Comparison using "is"
if Animal.dog is Animal.cat:
print ("Dog and cat are same animals")
else : print ("Dog and cat are different animals")
# Comparison using "!="
if Animal.lion != Animal.cat:
print ("Lions and cat are different")
else : print ("Lions and cat are same")
# Iterable
for a in (Animal):
print(a)
```

View File

@@ -0,0 +1,30 @@
# Exceptions
Exceptions are defined in python by using a `try` block followed by an `except` (catch) block. You can listen for a particular kind of error, or just catch all. You can also have an `else` block which will run if no exception was thrown, or a `finally` block which will run regardless of whether or not an exception was thrown.
```python
try:
num = 5
string = "string"
result = num + string
except TypeError as err: # Put type of error after except
print("Looks like you did something wrong... %s" % err)
else:
print("You did everything right!")
print(result)
finally:
print("I happen at the end no matter what")
def ask_for_int():
while True:
try:
result = int(input("Provide a number:"))
except:
print("You have to give a number")
continue
else:
print("Thank you!")
break
```

View File

@@ -0,0 +1,33 @@
# Functions
Functions are defined with the `def` keyword. They can take any number of named arguments, which can be given a default value with an `=`. Functions also receive an optional `*args`, or postiional arguments, and `**kwargs`, or key word arguments.
Functions in python are first-class objects, meaning they can be returned from other functions or passed as arguments into other functions.
```python
def hello(name="David"):
return "Hello " + name
def options_args(arg1, *args):
print("First argument :", arg1)
for arg in args:
print("Next argument through *args :", arg)
options_args('Hello', 'Welcome', 'to', 'my', 'docs!')
def optional_kwargs(arg1, **kwargs):
for key, value in kwargs.items():
print("%s == %s" % (key, value))
optional_kwargs("Hi", first='Hello', mid='world', last='!')
# Functions can also be returned
def cool():
def super_cool():
return "I am very cool"
return super_cool
# or passed as an argument
def other(some_other_func):
some_other_func()
```

View File

@@ -0,0 +1,24 @@
# Generators
Generators are functions return iterable results that do not execute until the next iteration is requested. This is achieved with the `yield` keyword which acts as a return. You can iterate over the function as you would any other iterable type. You can also manually request the next return value with the `next` function.
Some types can also be turned into generators with the `iter` function.
```python
def create_cubes(n):
for x in range(n):
yield x**3
for x in create_cubes(10):
print(x)
y = create_cubes(10)
print(y) # Generator function
print(next(y)) # First value, 0
print(next(y)) # POP! Second value, 1
# Can turn some types into generators with iter
s = "hello"
s_iter = iter(s)
print(next(s_iter)) # First value, h
```

View File

@@ -0,0 +1,19 @@
# Types
You can find out the type of an object in python with the `type` function.
```python
x = 5
print(type(x)) # int
```
| Type | Variations |
| --------- | ------------- |
| Text | `str` |
| Numeric | `int`, `float`, `complex` |
| Sequence | `list`, `tuple`, `range` |
| Mapping | `dict` |
| Set | `set`, `frozenset` |
| Boolean | `bool` |
| Binary | `bytes`, `bytearray`, `memoryview` |
| None | `NoneType` |

View File

@@ -0,0 +1,38 @@
# Virtual Environments
Virtual environments are a way of creating a unique workspace for each of your python projects so that you can have different versions of dependencies installed on one machine. Once in the virtual environment, any packages installed will only apply to that enviroment.
### To Install
```bash
pip install virtualenv
```
### To Create
```bash
virtualenv <env_name>
OR
python -m venv <env_name>
```
### To start
```bash
On Unix:
source <env_name>/bin/activate
On Windows:
<env_name>/Scripts/activate
```
### To exit
```bash
deactivate
```
### Requirements file
```bash
To save:
pip freeze > requirements.txt
To install:
pip install -r requirements.txt
```

View File

@@ -1 +1,3 @@
Test python
# Introduction
Python needs no introduction! Here are some basics about the language, as well as some helpful snippets of some packages that I use often.