Quick Introduction
Python is an interpreted programming language where codes go through a program called interpreter, which reads and executes the code line by line.
- Flexible
- Platform independent
Python is popular for
- Machine Learning (PyTorch, TensorFlow)
- Data Science (numpy, pandas, matplotlib, scikit-learn)
- Large-scale web application (Django).
Install Python
Virtual Environment
It’s recommended to create a virtual environment for each of your project.
Python Venv
1
2
3
4
5
6
7
8
9
10
11
|
$ python -m venv /path/to/new/virtual/environment
# Example
$ pwd
/Users/zheng/Documents/demo
$ python -m venv project_venv
# Activate venv
$ source project_venv/bin/activate
# Verify
$ which python
/Users/zheng/Documents/demo/project_venv/bin/python
|
Anaconda/Miniconda Venv
1
2
3
4
5
6
7
8
9
10
|
# Create venv
# https://docs.conda.io/projects/conda/en/latest/commands/create.html
$ conda create -n project_venv python=3.11
# List conda venvs
$ conda env list
base * /Users/zheng/miniconda3
CV /Users/zheng/miniconda3/envs/CV
Django /Users/zheng/miniconda3/envs/Django
# Activate venv
$ conda activate CV
|
Install Python Libraries
With the flag -i
, you can specify *PyPi (The Python Package Index)
1
2
3
4
5
6
7
8
9
|
# A collection of PyPi for users in China
# -----------------------------------------------------#
https://pypi.tuna.tsinghua.edu.cn/simple/
https://mirrors.aliyun.com/pypi/simple/
https://repo.huaweicloud.com/repository/pypi/simple/
# -----------------------------------------------------#
# Example
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ numpy
|
Variables
Python Variable Names
Naming Conventions
- Must start with a letter
[A-z]
or _
- Can NOT start with a number
[0-9]
- Contain ONLY
[A-z]
, [0-9]
and _
- Are case-sensitive
Name
≠ name
Numerical Variables
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# Define variables
>>> a = 2
>>> b = 10
>>> c = 3
# 1. Numerical Operations:
# +-*/
# 2. Power
>>> a ** b
1024
# 3. Mod
>>> b % c
1
# 4. To string variables
>>> str(a)
'2'
|
*You can get get the type of any variable with type(<var_name>)
String Variables
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# Define variables
>>> a = "TeSt"
>>> b = "2"
# 1. title(), lower() and upper() methods
>>> a.title()
'Test'
>>> a.lower()
'test'
>>> a.upper()
'TEST'
# 2. strip(), lstrip() and rstrip() methods
>>> c = ",.+-* TeSt *-+.,"
>>> c.strip(",.+-* ")
'TeSt'
>>> c.lstrip(",.+-* ")
'TeSt *-+.,'
>>> c.rstrip(",.+-* ")
',.+-* TeSt'
# 3. Combine strings together
>>> a + " " + b
'TeSt 2'
# 4. To other types
>>> int(b)
2
>>> float(b)
2.0
|
Loops
Loop with if
1
2
3
4
5
6
7
8
9
|
if condition_1:
function_1
return return_value
elif condition_2:
function_2
return return_value
else condition_3:
function_3
return return_value
|
Loop with while
1
2
3
4
5
6
7
8
|
while condition:
function
if break_condition:
break
if continue_condition:
continue
if pass_condition:
pass
|
-
Break will terminate the loop
-
Continue will only terminate/skip the current iteration
-
Pass is typically used as a placeholder for future code
Normal Function Arguments
Parameters are placeholders in a function definition, while Arguments are actual values passed during function invocation
Defining Your Own Python Function
Positional Arguments
- Internally, values in
*args
as represented as in a tuple
- The name
args
can be named arbitrarily
1
2
3
4
5
6
7
8
9
10
|
def cal_average(*int_nums):
sum = 0
for item in int_nums:
sum += item
return sum / len(int_nums)
>>> cal_average(1, 2)
1.5
>>> cal_average(*[i for i in range(10)])
4.5
|
Keyword Arguments
- Internally, values in
**kwargs
as represented as in a dict
- The name
kwargs
can be named arbitrarily
1
2
3
4
5
6
7
8
9
10
11
|
def learn_kwargs(**kwargs):
print(kwargs)
print(type(kwargs))
for key, val in kwargs.items():
print(f"{key} -> {val}")
>>> learn_kwargs(first_name='Zheng', last_name='Yuan')
{'first_name': 'Zheng', 'last_name': 'Yuan'}
<class 'dict'>
first_name -> Zheng
last_name -> Yuan
|
All-in-One
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def aio_func(a, b, *args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
>>> aio_func(1, 2, 3, 4, 5, first_name='Zheng', last_name='Yuan')
1
2
(3, 4, 5)
{'first_name': 'Zheng', 'last_name': 'Yuan'}
# a, b are positional arguments
# 3, 4, 5 are also positional arguments
# first_name, last_name are keyword arguments
|
X-Only Function Arguments
Why do we need them?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
# Q: In the following function, how to give the prefix a default value?
def concat(prefix, *args):
print(f'{prefix}{".".join(args)}')
>>> concat('//', 'a', 'b', 'c')
//a.b.c
# 1. Try-1
def concat(prefix='-> ', *args):
print(f'{prefix}{".".join(args)}')
>>> concat('a', 'b', 'c')
ab.c
# This won't work because prefix is a positional argument, so when invoking
# the function call, 'a' will replace the default value '-> '.
# Actually, the default value can never be reached.
# 2. Try-2
>>> concat(prefix='//', 'a', 'b', 'c')
File "<stdin>", line 1
concat(prefix='//', 'a', 'b', 'c')
^
SyntaxError: positional argument follows keyword argument
# This also won't work, because python requires keyword arguments after
# positional arguments
# 3. Try-3
>>> concat('a', 'b', 'c', prefix='... ')
File "<stdin>", line 1, in <module>
TypeError: concat() got multiple values for argument 'prefix'
# As Try-1, 'a' is thought to be the positional argument prefix, but it's given again.
# This only works for python3
def concat(*args, prefix='-> '):
print(f'{prefix}{".".join(args)}')
>>> concat('a', 'b', 'c')
-> a.b.c
def concat(*args, prefix='-> ', sep='.'):
print(f'{prefix}{sep.join(args)}')
>>> concat('a', 'b', 'c', prefix='//', sep='-')
//a-b-c
# In examples above, prefix and sep are both keyword-only arguments
|
Keyword-Only Arguments
The bare variable argument parameter *
indicates that there aren’t any more positional parameters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
def oper(x, y, *, op='+'):
if op == '+':
return x + y
elif op == '-':
return x - y
elif op == '/':
return x / y
else:
return None
>>> oper(3, 4, '+')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: oper() takes 2 positional arguments but 3 were given
>>> oper(3, 4, "I don't belong here")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: oper() takes 2 positional arguments but 3 were given
|
1
2
3
4
5
6
7
8
9
10
11
|
# https://peps.python.org/pep-3102/
# Old syntax and fix
def compare(a, b, *ignore, key=None):
# The ‘ignore’ argument will also suck up any erroneous positional arguments
if ignore:
raise TypeError
do_smth
# New syntax
def compare(a, b, *, key=None):
do_smth
|
Positional-Only Arguments
Python 3.8: Cool New Features for You to Try
The bare variable argument parameter /
indicates that parameters before it are positional-only (cannot be passed by keyword) and parameters after it are regular arguments that can be passed either by position or keyword.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# Python 3.8
def f(x, /, y):
print(x)
print(y)
>>> f(x=1, y=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got some positional-only arguments passed as keyword arguments: 'x'
>>> f(1, y=2)
1
2
>>> f(1, 2)
1
2
|
All-in-One
1
2
3
4
5
6
|
def f(a, b, c, /, d, e, */, f, g):
do_smth
# a, b, c are postitional-only arguments
# d, e are normal arguments
# f, g are keyword-only arguments
|
Metaprogramming is about creating functions and classes whose main goal is to manipulate code.
Decorators
Primer on Python Decorators
PEP 318 – Decorators for Functions and Methods
Decorators wrap a function, modifying its behavior.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def my_decorator(func):
def wrapper_func(*args, **kwargs):
do_smth
result = func(*args, **kwargs)
do_smth
return result
return wrapper_func
def foo_func():
do_smth
# 1. The complicated way
result = my_decorator(foo_func(my_args, my_kwargs))
# 2. The easy way
@my_decorator
def foo_func():
do_smth
results = foo_func(my_args, my_kwargs)
|
Problem: Important metadata such as the name, doc string, annotations, and calling signatures are lost. Workarounds \(\longrightarrow\)
1
2
3
4
5
6
7
8
9
10
|
from functools import wraps
def my_decorator(func):
@wraps
def wrapper_func(*args, **kwargs):
do_smth
result = func(*args, **kwargs)
do_smth
return result
return wrapper_func
|
Class Decorators
Lambda Function
Lambda expressions in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# Converting a simple function
def function_name(param_1, param_2, ...):
return do_smth
lambda param_1, param_2, ...: do_smth
# Converting a simple function with if
def function_name(param_1, param_2, ...):
if condition:
do_smth_1
else:
do_smth_2
lambda param_1, param_2: do_smth_1 if condition else do_smth_2
|
Function Annotations
PEP 3107 – Function Annotations
1
2
3
4
5
|
# Some demo syntax
def demo_func(param_1: tuple = (1, 2, 3),
param_2: int = 1024,
param_3: float = 1.0) -> bool:
do_smth
|
Data Structure
File Operations
Object-Oriented Programming