mirror of
https://github.com/TrudeEH/web.git
synced 2025-12-06 16:33:37 +00:00
1146 lines
22 KiB
Markdown
1146 lines
22 KiB
Markdown
---
|
|
title: Python
|
|
description:
|
|
draft: false
|
|
tags:
|
|
- python
|
|
- programming
|
|
author: TrudeEH
|
|
showToc: true
|
|
---
|
|
|
|
## Python3 [Documentation](https://docs.python.org/3/)
|
|
|
|
- `number`: Replace with a number.
|
|
- `*object`: Any number of objects.
|
|
- `[, ndigits]`: Anything between `[]` is optional.
|
|
|
|
## Run Python Code
|
|
|
|
Python is an interpreted language. It is not compiled like C.
|
|
|
|
```Shell
|
|
python hello.py
|
|
```
|
|
|
|
Skipping the compiling step makes the language easier to use but at the cost of performance.
|
|
|
|
## Print
|
|
|
|
Print information on the console.
|
|
|
|
```Python
|
|
print("hello, world")
|
|
answer = "Some Text"
|
|
print(f"Your answer is: {answer}") # formatted string (any type)
|
|
print("Your answer is: " + answer) # answer must be string
|
|
print("Your answer is:", answer) # answer can be any type
|
|
print("Same line", end="")
|
|
print("!" * 4) # "!!!!
|
|
# '' and "" do the same.
|
|
```
|
|
|
|
## Input
|
|
|
|
Prompt the user for information.
|
|
|
|
```Python
|
|
# String Input
|
|
name = input("Prompt: ")
|
|
number = int(input("Prompt: "))
|
|
name = name.strip() # Remove whitespaces from a string
|
|
```
|
|
|
|
## Variables
|
|
|
|
Python infers the type of variable automatically.
|
|
|
|
```Python
|
|
answer = "Some Text"
|
|
counter = 0
|
|
counter = counter + 1
|
|
counter += 1
|
|
# Counter++ does not exist in Python
|
|
```
|
|
|
|
### Global Variables
|
|
|
|
Use the global keyword to modify a global variable while outside its scope.
|
|
|
|
```Python
|
|
balance = 0
|
|
def deposit(n):
|
|
global balance
|
|
balance += n
|
|
```
|
|
|
|
## Comments
|
|
|
|
```Python
|
|
# Comment
|
|
"""
|
|
Multi
|
|
Line
|
|
Comment
|
|
"""
|
|
```
|
|
|
|
### Docstring
|
|
|
|
The documentation for a function.
|
|
This can later be used to generate manuals and documentation Some IDEs do so automatically.
|
|
|
|
```Python
|
|
def code():
|
|
"""
|
|
Does something.
|
|
"""
|
|
...
|
|
```
|
|
|
|
### Type Hints
|
|
|
|
Type hints are not enforced. These can be read by debuggers, but Python itself allows these types to be violated.
|
|
|
|
```Python
|
|
def meow(n: int) -> None: # -> None indicates that the function does not return a value
|
|
...
|
|
number: int = int(input("Number: "))
|
|
```
|
|
|
|
## Data Types
|
|
|
|
| Data Type Category | Data Types |
|
|
| ------------------ | ---------------------------------- |
|
|
| Text Type | `str` |
|
|
| Numeric Types | `int`, `float`, `complex` |
|
|
| Sequence Types | `list`, `tuple`, `range` |
|
|
| Mapping Type | `dict` |
|
|
| Set Types | `set`, `frozenset` |
|
|
| Boolean Type | `bool` |
|
|
| Binary Types | `bytes`, `bytearray`, `memoryview` |
|
|
| None Type | `NoneType` |
|
|
|
|
> `float` types can overflow, much like C, but `int` never does, and instead grows as large as needed to fit a given value.
|
|
|
|
### Type Conversion
|
|
|
|
```Python
|
|
int("1") # convert to int
|
|
float(2) # convert to float
|
|
```
|
|
|
|
### Data Type Functions
|
|
|
|
```Python
|
|
round(5.12) # round a number
|
|
round(3.43, 2) # round to the 2nd decimal place
|
|
len(list) # length of a list (nº of elements)
|
|
```
|
|
|
|
### Unpack Values
|
|
|
|
Values can be split using `*`. This method works with lists, dictionaries, and tuples.
|
|
For dictionaries, `*dict` returns key names and `**dict` returns the value names.
|
|
Unpack can also be used when returning values from functions.
|
|
|
|
```Python
|
|
def total(gold, silver, copper):
|
|
return gold * 100 + silver * 10 + copper
|
|
coins = [100, 50, 25]
|
|
print(total(*coins), "Copper coins")
|
|
```
|
|
|
|
### F Strings
|
|
|
|
A string that executes formatting.
|
|
|
|
```Python
|
|
f'Some text: {1+1}' # Executes 1+1 and prints "Some text: 2"
|
|
f'{z:.2f}' # Variable z is rounded to the 2nd decimal place.
|
|
```
|
|
|
|
### Ranges
|
|
|
|
Produce a range of numbers.
|
|
|
|
```Python
|
|
range(10) # 1, 2, 3... 10
|
|
if 80 <= score < 90:
|
|
code...
|
|
```
|
|
|
|
### Lists
|
|
|
|
Arrays are flexible in Python, unlike C. Elements can be added and removed at runtime.
|
|
|
|
```Python
|
|
scores = [72, 73, 33]
|
|
scores.append(32)
|
|
# scores += [43, 45] # Adds a list to another list
|
|
average = sum(scores) / len(scores)
|
|
print(f"Average: {average}")
|
|
scores[1:] \#Slice the list -> From 1 to the end. (Skips element 0)
|
|
scores[1:-1] \#Slice the list -> From 1 to the end. (Skips element 0 and last)
|
|
```
|
|
|
|
#### List Comprehension
|
|
|
|
Create a new list with a function applied to every element of the list.
|
|
|
|
```Python
|
|
words = ["This", "is", "CS50"]
|
|
uppercased = [word.upper() for word in words]
|
|
print(*uppercased)
|
|
```
|
|
|
|
In this example, every element in `words` is uppercased.
|
|
This feature is useful to filter items as well:
|
|
|
|
```Python
|
|
students = [
|
|
{"name": "Trude", "class": "code"},
|
|
{"name": "Maxs", "class": "art"},
|
|
{"name:" "JCionx", "class": "code"},
|
|
]
|
|
codeStudents = [
|
|
student["name"] for student in students if student["class"] == "code"
|
|
]
|
|
```
|
|
|
|
#### Filter Function
|
|
|
|
Similar code, but for a more functional oriented programming approach.
|
|
|
|
```Python
|
|
def is_class(s):
|
|
return s["class"] == "code"
|
|
coders = filter(is_class, students)
|
|
```
|
|
|
|
### Sets
|
|
|
|
Similar to a list, but can only contain unique items.
|
|
|
|
```Python
|
|
values = set(1, 1, 1, 2)
|
|
print(values) # 1, 2
|
|
```
|
|
|
|
### Dictionaries
|
|
|
|
A list, but instead of using an index, uses keywords.
|
|
|
|
```Python
|
|
students = {
|
|
"Key1": "Value",
|
|
"Key2": "Value",
|
|
"Key3": "Value",
|
|
}
|
|
print(students["Key1"])
|
|
```
|
|
|
|
#### Loop over Dictionary
|
|
|
|
```Python
|
|
for student in students:
|
|
print(student) # Iterates over keys.
|
|
print(students[student]) # Iterates over values.
|
|
```
|
|
|
|
#### Dictionary Comprehension
|
|
|
|
Filter dictionaries.
|
|
|
|
```Python
|
|
students = ["Trude", "Maxs", "JCionx"]
|
|
# Classic for
|
|
coders = []
|
|
for student in students:
|
|
coders.append({"name": student, "class": "code"})
|
|
# List comprehension (3 dicts in a list)
|
|
coders = [{"name": student, "class": "code"} for student in students]
|
|
# Dict comprehension (1 dict with name: class for all 3)
|
|
coders = {student: "code" for student in students}
|
|
```
|
|
|
|
### Hashtable
|
|
|
|
```Python
|
|
table = [
|
|
{"Key1": "Value", "Key2": "Value", "Key3": "Value"},
|
|
{"Key1": "Value", "Key2": "Value", "Key3": "Value"},
|
|
{"Key1": "Value", "Key2": "Value", "Key3": "Value"},
|
|
{"Key1": "Value", "Key2": "Value"},
|
|
]
|
|
print(table[0]["Key2"])
|
|
for tab in table:
|
|
print(tab["Key1"]) # Print all Key1 values.
|
|
```
|
|
|
|
## Conditions
|
|
|
|
### IF
|
|
|
|
```Python
|
|
if x < y:
|
|
print("x is less than y")
|
|
elif x > y:
|
|
print("x is greater than y")
|
|
else:
|
|
print("x is not less than y")
|
|
if test in numbers:
|
|
code...
|
|
```
|
|
|
|
`()` are optional in the condition.
|
|
|
|
### `:=` Operator
|
|
|
|
Syntax sugar to integrate an assignment operator with an IF statement.
|
|
**Without it**
|
|
|
|
```Python
|
|
matches = 1 == 1
|
|
if matches:
|
|
print(matches) # True
|
|
```
|
|
|
|
**With it**
|
|
|
|
```Python
|
|
if matches := 1 == 1:
|
|
print(matches) # True
|
|
```
|
|
|
|
## Loops
|
|
|
|
### While
|
|
|
|
```Python
|
|
while True:
|
|
print("meow")
|
|
i = 0
|
|
while i < 3:
|
|
print("meow")
|
|
i += 1
|
|
```
|
|
|
|
### For
|
|
|
|
#### Loop through an Array
|
|
|
|
```Python
|
|
for _ in [0, 1, 2]:
|
|
print("Hello World.")
|
|
# _ throws away the value (no variable).
|
|
```
|
|
|
|
#### Loop through a Range
|
|
|
|
```Python
|
|
for i in range(3):
|
|
print("Loops from 0 - 3")
|
|
```
|
|
|
|
#### Loop through an Array, Using Its Value as the Index
|
|
|
|
```Python
|
|
students = ["one", "two", "three"]
|
|
for student in students:
|
|
print(student)
|
|
```
|
|
|
|
#### Enumerate
|
|
|
|
Iterate over a sequence, and get the current value and index.
|
|
|
|
```Python
|
|
students = ["Trude", "Maxs", "JCionx"]
|
|
for i, student in enumerate(students):
|
|
print(i + 1, student)
|
|
```
|
|
|
|
### Map
|
|
|
|
Execute a function on every element of a list.
|
|
Takes two arguments:
|
|
- Name of a function
|
|
- Data structure to apply the function on
|
|
|
|
```Python
|
|
words = ["This", "is", "CS50"]
|
|
uppercased = map(str.upper, words)
|
|
print(*uppercased)
|
|
```
|
|
|
|
### Keywords
|
|
|
|
- `break`: leave the loop
|
|
- `continue`: skip to next iteration
|
|
|
|
## Libraries
|
|
|
|
```Python
|
|
import lib
|
|
lib.component(...)
|
|
from lib import component
|
|
component(...)
|
|
```
|
|
|
|
### Packages
|
|
|
|
A package is a collection of libraries in the same directory, often built by other developers.
|
|
You can download user packages on [pypi.org](http://pypi.org/).
|
|
|
|
#### Install Packages with Pip
|
|
|
|
`pip` is a package manager for Python.
|
|
|
|
```Bash
|
|
pip install package
|
|
```
|
|
|
|
### Useful Libraries
|
|
|
|
- `random` Generate random numbers
|
|
- `shuffle`
|
|
- `choice`
|
|
- `randint`
|
|
- `statistics`
|
|
- `mean`
|
|
- `requests` Web requests (similar to `curl`) useful for interfacing with APIs
|
|
|
|
#### APIs
|
|
|
|
APIs usually communicate in JSON.
|
|
|
|
```Python
|
|
import requests, sys
|
|
import json
|
|
response = requests.get("<https://itunes.apple.com/search?entity=song(...)>")
|
|
print(response.json()) # Print respose formatted for json (as a py dictionary))
|
|
print(json.dumps(response.json(), indent=2)) # Print response indented to read easily.
|
|
o = response.json()
|
|
for result in o["results"]:
|
|
print(result["trackName"]) # Print all songs in the response
|
|
```
|
|
|
|
### Create Custom Library
|
|
|
|
```Python
|
|
# LIBRARY: lib.py file
|
|
def main():
|
|
hello("world")
|
|
def hello(name):
|
|
print(f"hello, {name}")
|
|
# Only call main if ran from the command line. Not as a library.
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
```Python
|
|
# MAIN CODE: main.py file
|
|
from lib import hello
|
|
hello("trude")
|
|
```
|
|
|
|
## Functions
|
|
|
|
```Python
|
|
def hello(name):
|
|
print(f'Hello {name}')
|
|
hello("trude")
|
|
```
|
|
|
|
### Default Values
|
|
|
|
```Python
|
|
def hello(to='world'):
|
|
print("hello,", to)
|
|
hello() # hello, world
|
|
hello('trude') # hello, trude
|
|
```
|
|
|
|
### Main Function
|
|
|
|
```Python
|
|
def main():
|
|
# main code ...
|
|
# other fucntions ...
|
|
main()
|
|
```
|
|
|
|
### Generator Function (Yield)
|
|
|
|
Return one value at a time, without ending the function, and then loop again.
|
|
Useful when working with a large amount of logic that takes a long time to execute.
|
|
|
|
```Python
|
|
def sheep(n):
|
|
for i in range(n):
|
|
yield "SHEEP" * i
|
|
```
|
|
|
|
`yield` returns an iterator that allows the program to handle one element at a time and not lose track.
|
|
|
|
### Command Line Arguments
|
|
|
|
```Python
|
|
from sys import argv
|
|
if len(argv) == 2:
|
|
print(f"Hello, {argv[1]}")
|
|
else:
|
|
print("Hello World.")
|
|
# argv[0] is the program name
|
|
# List all arguments
|
|
for arg in argv:
|
|
print(arg)
|
|
```
|
|
|
|
#### Flags
|
|
|
|
To support commands like: `python file.py -n 2`
|
|
|
|
```Python
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description="Meow like a cat")
|
|
parser.add_argument("-n", default=1, type=int, help="number of times to meow")
|
|
args = parser.parse_args()
|
|
for _ in range(args.n): # .n is the -n flag
|
|
print("meow")
|
|
```
|
|
|
|
#### Allow Function to Take Any Number of Arguments (Unpack)
|
|
|
|
```Python
|
|
def f(*args, **kwargs):
|
|
print("Positional: ", args)
|
|
print("Named: ", kwargs)
|
|
f(100, 50, 25) # Positional: (100, 50, 25)
|
|
f(100, 50, 25, 5) # Positional: (100, 50, 25, 5)
|
|
f(gold=10, silver=20, copper=1) # Named: {'gold': 10, 'silver'20 ...}
|
|
```
|
|
|
|
### Pass Functions as Arguments
|
|
|
|
```Python
|
|
def get_name(student):
|
|
return student["name"] # Sort by student name
|
|
for student in sorted(students, key=get_name):
|
|
...
|
|
```
|
|
|
|
#### Lambda Function
|
|
|
|
Pass a function without having to give it a name.
|
|
|
|
```Python
|
|
for student in sorted(students, key=lambda student: student["name"]):
|
|
...
|
|
```
|
|
|
|
## Exceptions
|
|
|
|
```Python
|
|
# Int
|
|
try: # Try to execute
|
|
x = int(input("What's your number?"))
|
|
except ValueError: # If error is ValueError
|
|
print("Not a number.")
|
|
except: # If error
|
|
print("Unknown Error.")
|
|
else: # If success
|
|
print(f"Your number+1 is {x + 1}")
|
|
```
|
|
|
|
```Python
|
|
try:
|
|
...
|
|
except:
|
|
pass # Catch the error, but then ignore it.
|
|
```
|
|
|
|
## Operators
|
|
|
|
### Comparison Operators
|
|
|
|
- `<`
|
|
- `>`
|
|
- `≤`
|
|
- `≥`
|
|
- `≠`
|
|
- `==`
|
|
|
|
### Logic Operators
|
|
|
|
- `and`
|
|
- `or`
|
|
|
|
```Python
|
|
s = input("Do you agree?")
|
|
if s == 'y' or s == 'Y' or s == "Yes" or s == "yes":
|
|
(...)
|
|
# This can be improved:
|
|
s = input("Do you agree?").lower()
|
|
if s in ['y', 'yes']:
|
|
(...)
|
|
```
|
|
|
|
## Scope
|
|
|
|
1. Program
|
|
2. Function (Variables in loops and IFs are global to the function)
|
|
|
|
## Exit with Error Codes
|
|
|
|
```Python
|
|
from sys import exit
|
|
exit(1) # Exit with error code 1
|
|
exit("Failed for some reason")
|
|
```
|
|
|
|
## Unit Tests
|
|
|
|
Helper code to test the main code and (hopefully) catch bugs before they can reach production.
|
|
|
|
### Manual Tests
|
|
|
|
**Main code**
|
|
|
|
```Python
|
|
def main():
|
|
x = int(input("X value: "))
|
|
print(f"X^2 is {square(x)}")
|
|
def square(n):
|
|
return(n * n)
|
|
if __name__ = "__main__":
|
|
main()
|
|
```
|
|
|
|
**Test code (Using IF)**
|
|
|
|
```Python
|
|
from file import square
|
|
def main():
|
|
test_square()
|
|
def test_square():
|
|
if square(2) != 4:
|
|
print("2 squared was not 4.")
|
|
if square(3) != 9:
|
|
print("3 squared was not 9.")
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
**Improved test code (Using assert)**
|
|
|
|
```Python
|
|
from file import square
|
|
def main():
|
|
test_square()
|
|
def test_square():
|
|
try:
|
|
assert square(2) == 4
|
|
except AssertionError:
|
|
print("2 squared was not 4.")
|
|
try:
|
|
assert square(3) == 9
|
|
except AssertionError:
|
|
print("3 squared was not 9.")
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
### **Pytest**
|
|
|
|
`pytest` is an external program that simplifies python's unit testing.
|
|
|
|
```Python
|
|
import pytest
|
|
from file import square
|
|
def test_square():
|
|
assert square(2) == 4
|
|
assert square(3) == 9
|
|
assert square(-2) == 4
|
|
assert square(-3) == 9
|
|
assert square(0) == 0
|
|
def test_str(): # Verify that an error will happen for a str
|
|
with pytest.raises(TypeError):
|
|
square("cat")
|
|
```
|
|
|
|
Test with `pytest`:
|
|
|
|
```Shell
|
|
pytest test_file.py
|
|
```
|
|
|
|
> A function with side effects (doesn't return a value) can't be tested.
|
|
|
|
## File I/O
|
|
|
|
### Write to a File (Replace)
|
|
|
|
```Python
|
|
name = "trude"
|
|
file = open("name.txt", "w")
|
|
file.write(name)
|
|
file.close()
|
|
```
|
|
|
|
### Append to a File (Add)
|
|
|
|
```Python
|
|
name = "trude"
|
|
file = open("name.txt", "a")
|
|
file.write(name)
|
|
file.close()
|
|
```
|
|
|
|
### Open a File and close Automatically
|
|
|
|
```Python
|
|
name = "trude"
|
|
with open("name.txt", "a") as file:
|
|
file.write(name) \\#File is only open in this scope
|
|
```
|
|
|
|
### Read a File
|
|
|
|
`"r"` is optional when reading.
|
|
|
|
```Python
|
|
with open("name.txt", "r") as file:
|
|
lines = file.readlines() # Return all lines as a list
|
|
for line in lines:
|
|
print(line.rstrip()) # Print all lines and remove \\n separating each line
|
|
```
|
|
|
|
#### Better Code for Reading Every line
|
|
|
|
```Python
|
|
with open("name.txt") as file:
|
|
for line in file:
|
|
print(line.rstrip())
|
|
```
|
|
|
|
#### Sort File Lines
|
|
|
|
```Python
|
|
names = []
|
|
with open("name.txt") as file:
|
|
for line in file:
|
|
names.append(line.rstrip())
|
|
for name in sorted(names):
|
|
print(f"Hello, {name}")
|
|
```
|
|
|
|
### CSV Files
|
|
|
|
#### Read
|
|
|
|
**Python**
|
|
|
|
```Python
|
|
import csv
|
|
students = []
|
|
with open("students.csv") as file:
|
|
reader = csv.reader(file)
|
|
for name, home in reader:
|
|
students.append({"name": name, "home": home})
|
|
for student in students:
|
|
print(f"{student['name]"} is from {student['home']}")
|
|
```
|
|
|
|
**CSV File**
|
|
|
|
```Plain
|
|
trude, myHome
|
|
maxs, hisHome
|
|
jcionx, anotherHome
|
|
```
|
|
|
|
#### Dict Reader
|
|
|
|
Ignores column order and doesn't break the program if new columns are added. It is recommended to **always** use `**DictReader**` **instead of** `**Reader**`**.**
|
|
**Python**
|
|
|
|
```Python
|
|
import csv
|
|
students = []
|
|
with open("students.csv") as file:
|
|
reader = csv.DictReader(file)
|
|
for row in reader:
|
|
students.append({"name": row["name"], "home": row["home"]})
|
|
for student in students:
|
|
print(f"{student['name]"} is from {student['home']}")
|
|
```
|
|
|
|
**CSV File**
|
|
|
|
```Plain
|
|
name, home
|
|
trude, myHome
|
|
maxs, hisHome
|
|
jcionx, anotherHome
|
|
```
|
|
|
|
#### Write
|
|
|
|
```Python
|
|
import csv
|
|
name = 'trude'
|
|
home = 'myHome'
|
|
with open("students.csv", "a") as file:
|
|
writer = csv.writer(file)
|
|
writer.writerow([name, home])
|
|
```
|
|
|
|
#### Dict Writer
|
|
|
|
```Python
|
|
import csv
|
|
name = 'trude'
|
|
home = 'myHome'
|
|
with open("students.csv", "a") as file:
|
|
writer = csv.DictWriter(file, fieldnames=["name", "home"])
|
|
writer.writerow({"name": name, "home": home})
|
|
```
|
|
|
|
### Other Formats
|
|
|
|
- TXT
|
|
- CSV
|
|
- JSON
|
|
- BINARY
|
|
- Images (PIL library)
|
|
|
|
#### Animated GIF Program
|
|
|
|
```Python
|
|
from PIL import Image
|
|
items = ["image1.png", "image2.png"]
|
|
images = []
|
|
for item in items:
|
|
image = Image.open(item)
|
|
images.append(image)
|
|
images[0].save(
|
|
"images.gif", save_all=True, append_images=[images[1]], duration=200, loop=0
|
|
)
|
|
```
|
|
|
|
## Regular Expressions (regex)
|
|
|
|
Define patterns for comparisons.
|
|
|
|
```Python
|
|
import re
|
|
email = input("Email Address: ").strip()
|
|
if re.search(r"^.+@.+\\.edu$", email, re.IGNORECASE):
|
|
print("Email is valid.")
|
|
else:
|
|
print("Email is not valid.")
|
|
```
|
|
|
|
### Regular Expression Symbols
|
|
|
|
- `.` any character except a newline
|
|
- 0 or more repetitions
|
|
- `+` 1 or more repetitions
|
|
- `?` 0 or 1 repetition
|
|
- `\\` escape character
|
|
- `{m}` m repetitions
|
|
- `{m,n}` m-n repetitions (range)
|
|
- `^` match the start of the string
|
|
- `$` match the end of the string
|
|
- `[]` set of characters
|
|
- `[^]` complementing the set
|
|
- `\\d` decimal digit
|
|
- `\\D` not a decimal digit
|
|
- `\\s` whitespace characters
|
|
- `\\S` not a whitespace character
|
|
- `\\w` word character, numbers and underscore
|
|
- `\\W` not a word character
|
|
- `A|B` either A or B
|
|
- `(…)` a group
|
|
- `(?:…)` non-capturing version
|
|
Always use `r"string"` (raw string) so python won't interpret `\\` as a special character.
|
|
|
|
### RE Lib Flags
|
|
|
|
- `re.IGNORECASE`
|
|
- `re.MULTILINE`
|
|
- `re.DOTALL`
|
|
|
|
### Examples
|
|
|
|
#### Regular Expression for Email Validation
|
|
|
|
```Python
|
|
import re
|
|
regex = re.compile(r"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$")
|
|
def isValid(email):
|
|
if re.fullmatch(regex, email):
|
|
print("Valid email")
|
|
else:
|
|
print("Invalid email")
|
|
```
|
|
|
|
[More regular expressions](https://www.labnol.org/internet/regular-expressions-forms/28380/)
|
|
`compile` caches the query to make new lookups faster.
|
|
When a regular expression becomes too complex, the rule of thumb is to **use a library instead**.
|
|
|
|
## Object-Oriented Programming: OOP
|
|
|
|
### Tuple
|
|
|
|
An immutable (constant) list.
|
|
|
|
```Python
|
|
tuple = (val1, val2)
|
|
```
|
|
|
|
#### Return More than One Value from a Function
|
|
|
|
```Python
|
|
def get_student():
|
|
n = input("Name: ")
|
|
h = input("House: ")
|
|
return n, h
|
|
name, house = get_student()
|
|
print(name)
|
|
student = get_student()
|
|
print(student[0])
|
|
```
|
|
|
|
To make the values mutable, return a list instead.
|
|
|
|
```Python
|
|
return [item1, item2]
|
|
```
|
|
|
|
### Class
|
|
|
|
Classes are 'blueprints' for data; They define custom data types.
|
|
For example, you can use a class to represent a real-world entity.
|
|
|
|
#### Basic Class
|
|
|
|
```Python
|
|
class Student:
|
|
... # '...' is a valid placeholder
|
|
student = Student # Create an object from the Student class
|
|
student.name = "trude" # Add a new instance variable
|
|
student.house = "myHome"
|
|
print(student.name) # 'trude'
|
|
```
|
|
|
|
#### Attributes
|
|
|
|
```Python
|
|
class Student:
|
|
def __init__(self, name, house): # Initialization function
|
|
self.name = name
|
|
self.house = house
|
|
name = 'trude'
|
|
house = 'myHome'
|
|
student = Student(name, house)
|
|
```
|
|
|
|
- `self` is the object created from the class definition.
|
|
- When an object is created, the `__init__` function is executed.
|
|
|
|
#### Attributes Error Handling
|
|
|
|
```Python
|
|
class Student:
|
|
def __init__(self, name="Unknown", house): # Initialization function
|
|
if not name:
|
|
raise ValueError("Missing name") # Create and output a custom error
|
|
if house not in ["myHome", "yourHome", "hisHome"]:
|
|
raise ValueError("Invalid house")
|
|
self.name = name
|
|
self.house = house
|
|
```
|
|
|
|
#### Change what Happens when an Object is Printed
|
|
|
|
```Python
|
|
class Student:
|
|
def __init__(self, name, house): # Initialization function
|
|
self.name = name
|
|
self.house = house
|
|
def __str__(self):
|
|
return f"A Student - {self.name}"
|
|
student = Student("trude", "myHome")
|
|
print(student) # "A Student - trude"
|
|
```
|
|
|
|
#### Methods
|
|
|
|
```Python
|
|
class Mage:
|
|
def __init__(self, name, clan, element): # Initialization function
|
|
self.name = name
|
|
self.clan = clan
|
|
self.element = element
|
|
def castElement(self):
|
|
match self.element:
|
|
case "Fire":
|
|
return "FIRE SPELL"
|
|
case "Water":
|
|
return "Water SPELL"
|
|
case "Earth":
|
|
return "Earth SPELL"
|
|
case "Air":
|
|
return "AIR SPELL"
|
|
case _:
|
|
return "NO SPELL"
|
|
mage = Mage("trude", "magicINC", "Fire")
|
|
print(mage.castElement())
|
|
```
|
|
|
|
#### Properties
|
|
|
|
Dot notation (`student.name = ""`) can bypass any data validation. To avoid this, make attributes constant.
|
|
A constant attribute is referred to as a property.
|
|
|
|
```Python
|
|
class Mage:
|
|
def __init__(self, name, clan, element): # Initialization function
|
|
self.name = name
|
|
self.clan = clan
|
|
self.element = element
|
|
# Getter (function to get house attribute)
|
|
@property # Indicates that this is a getter
|
|
def clan(self):
|
|
return self._clan # Add _ to avoid name collision.
|
|
# Setter (function to set a value)
|
|
@clan.setter # Indicates that this is a setter
|
|
def clan(self, clan):
|
|
if clan not in ["magicINC", "spellInator", "glyphGens"]:
|
|
raise ValueError("Invalid Clan")
|
|
self._clan = clan
|
|
mage = Mage("trude", "spellInator", "Fire")
|
|
mage.clan = "not-a-clan"
|
|
```
|
|
|
|
#### Example
|
|
|
|
```Python
|
|
class Mage:
|
|
...
|
|
def main():
|
|
mage = get_mage()
|
|
print(f"{mage.name} from {mage.clan}")
|
|
def get_mage():
|
|
mage = Mage()
|
|
mage.name = "trude"
|
|
mage.clan = "spellInator"
|
|
return mage
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
#### Class Methods
|
|
|
|
A method that relates to the class itself, and doesn't depend on the objects individually.
|
|
|
|
```Python
|
|
import random
|
|
class Hat:
|
|
def __init__(self):
|
|
self.clans = ["magicINC", "spellInator", "glyphGen"]
|
|
def sort(self, name):
|
|
print(name "is in", random.choice(self.clans))
|
|
|
|
hat = Hat()
|
|
hat.sort("Trude")
|
|
```
|
|
|
|
#### Class Variables
|
|
|
|
- `self.var` A variable unique for each object
|
|
- `var` A variable shared with all objects
|
|
|
|
```Python
|
|
class Hat:
|
|
clans = ["magicINC", "spellInator", "glyphGen"]
|
|
@classmethod
|
|
def sort(cls, name):
|
|
print(name "is in", random.choice(cls.clans))
|
|
Hat.sort("Trude")
|
|
```
|
|
|
|
A class method is a method global to the class, instead of created for each object. It relates to the data type (class) itself.
|
|
|
|
#### Example
|
|
|
|
```Python
|
|
class Mage:
|
|
...
|
|
@classmethod
|
|
def get(cls):
|
|
name = input("Name: ")
|
|
clan = input("Clan: ")
|
|
return cls(name, clan) # name and clans are returned to the class as self.name and self.clan.
|
|
...
|
|
def main():
|
|
mage = Mage.get()
|
|
print(mage)
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
### Inheritance
|
|
|
|
Inherit code from a parent class to avoid code duplication.
|
|
|
|
```Python
|
|
class Person:
|
|
def __init__(self, name)
|
|
if not name:
|
|
raise ValueError("Missing name")
|
|
self.name = name
|
|
class Student(Person): # Pass Person to Student
|
|
def __init__(self, name, house):
|
|
super().__init__(name) # Execute Person's __init__ method.
|
|
self.house = house
|
|
...
|
|
class Professor(Person):
|
|
def __init__(self, name, subject):
|
|
super().__init__(name)
|
|
self.subject = subject
|
|
...
|
|
person = Person("Random Guy")
|
|
student = Student("Trude", "myHome")
|
|
professor = Professor("Someone", "Math")
|
|
```
|
|
|
|
### Operator Overloading
|
|
|
|
Customize what an operator does with a Class.
|
|
- `__add__` Behavior of '+' operator.
|
|
|
|
```Python
|
|
class Vault:
|
|
def __init__(self, gold=0, silver=0, copper=0):
|
|
self.gold = gold
|
|
self.silver = silver
|
|
self.copper = copper
|
|
def __str__(self):
|
|
return f"{self.gold} Gold, {self.silver} Silver, {self.copper} Copper."
|
|
def __add__(self, other):
|
|
gold = self.gold + other.gold
|
|
silver = self.silver + other.silver
|
|
copper = self.copper + other.copper
|
|
return Vault(gold, silver, copper)
|
|
trude = Vault(100, 50, 25)
|
|
jcionx = Vault(25, 50, 100)
|
|
print(trude) # 100 Gold, 50 Silver, 25 Copper
|
|
print(jcionx) # 25b Gold, 50 Silver, 100 Copper
|
|
total = trude + jcionx
|
|
print(total) # 125b Gold, 100 Silver, 125 Copper
|
|
```
|