Python 基礎語法

此篇是集結 Python 所有的基礎語法內容,我將此篇當作學習筆記,需要用到時才回來複習,但未覆蓋到 List Unpacking 的用法,
關於 List Unpacking 的使用方式可以參考 Mike 的這篇文章 Python Unpacking實用技巧分享

Data Type

  • int
  • float
  • bool
  • str
  • list: 動態的 Array, Javascript Array 類似
  • tuple: 可以想成是 immuable 的 list
    my_tuple = (1, 2, 3)
  • set: collection of uniqe values
    my_set = {1, 2, 3, 4, 5}
  • dict: Javascript 的 Object, Java 的 HashMap

Ternary Expression

is_lisenced = True
word = "I can sense that lisence in you" if is_lisenced else "get out"

Truthy and Falsey

以下為 Falsey 值, 其他皆視為 Truthy 值

  • None
  • False
  • 0
  • 0.0
  • 0j
  • decimal.Decimal(0)
  • fraction.Fraction(0, 1)
  • [] - an empty list
  • {} - an empty dict
  • () - an empty tuple
  • '' - an empty str
  • b'' - an empty bytes
  • set() - an empty set
  • an empty range, like range(0)
  • objects for which
    • obj.__bool__() returns False
    • obj.__len__() returns 0

is vs ==

== 檢查值是否相同, 如果非相同的型別,python 會試著轉型別

print(True == 1) # True, pythonthon compare True == bool(1)
print('' == 1) # False
print([] == 1) # False
print(10 == 10.0) # True
print([] == []) # True

is 檢查記憶體地址是否相同

print(True == 1) # False
print('' == 1) # False
print([] == 1) # False
print(10 == 10.0) # False
print([] == []) # False

for Loops and Iterator

for item in 'Brian':
print(item)

Iterate Object

user = {
"name": "Brain",
"age": 28,
"can_swim": True
}

for item in user.items():
print(item)

for key, value in user.items():
print(key, value)

用 range()

for item in range(100):
print(item)

如果你不需要用參數的話:

for _ in range(100):
print('haha')

while loop

i = 0
while i < 50:
print(i)
i += 1
else:
print('Done with all the work')

如果用 Break 的話就不會跑 else 的程式

i = 0
while i < 50:
print(i)
i += 1
break
else:
print('Done with all the work')

continue

在迴圈裡用 continue, 就會略過迴圈裡 continue 以後的程式,直接跑下一個迴圈

my_list = [1, 2, 3]
for item in my_list:
print('haha')
continue
print(item) # 此行永遠不會跑


i = 0
while i <len(my_list):
print(my_list[i])
i += 1
continue
print(i) # 此行永遠不會跑

Function

*args*kwargs

*_args:_ 將所有的 arugements 轉為 tuple

def super_func(*args):
print(args) # (1, 2, 3, 4, 5)

super_func(1, 2, 3, 4, 5)

*_kwargs:_ 將所有的 arguments 轉為 dict

def super_func(**kwargs):
print(kwargs) # { name: "Brian", age: 27 }

super_func(name='Brian', age=27)

同時使用

def super_func(*args, **kwargs):
print(args) # (1, 2, 3)
print(kwargs) # { name: "Brian", age: 27 }

super_func(1, 2, 3, name='Brian', age=27)

如果要使用多種不同的參數
順序: params, *args, default params, **kwargs

Function Docstring

可以利用 docstring 幫 function 進行註解

def test():
'''
Info: this function tests and prints param a string
'''
print('Hello world')

Walrus Operator

Before:

a = 'Helloooooooooooo'

if (len(a) > 10):
print(f"Too long {len(a)} letters")

After:

a = 'Helloooooooooooo'

if ((n := len(a)) > 10):
print(f"Too long {n} letters")

變數 Scope

順序為

  • 是否為 local 變數
  • 是否為 parent 層 local 變數
  • 是否為 global 變數
  • 是否為內建 method

global

如果要在 function 裡, 用 global 的變數, 則需要用 global keyword

totoal = 0

def count():
global total
total += 1
return total

print(count())

但不推薦這麼做,可以直接將 global 的變數丟進 function 裡閱讀性較好

nonlocal

在 function 裡使用 parent function 的變數, 則需要用 nonlocal keyword

def outter():
x = "local"

def inner():
nonlocal x
x = "nonlocal"
print(x)
inner()
print("outer:", x)

outer()

class

class Player():
# constructor
def __init__(self, name):
self.name = name

# method, 所有的 method 第一個參數都是 self
def run (self):
print('run')

@classmethod, @staticmethod

用來新增 class 本身的 method, 不需要 instantiate 就可以使用

與一般 method 不同,@classmethod 的第一個參數是自己本身的 class, @staticmethod 則沒有任何預設參數

class Player():
def __init__(self, name):
self.name = name

@classmethod
def sum(cls, num1, num2):
return num1+num2

@staticmethod
def sum2(num1, num2):
return num1+num2

Inheritance

子 class 需要利用該 Class名稱.__init__() 或是 super().__init__() 將父 class init 需要的直傳入
Class名稱.__init__(): 第一個參數要傳入 self

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

def greeting(self):
print(f'Hello, my name is {self.name} and i am {self.age} years old')

class Wizard(Person):
def __init__(self, name, age, power):
Person.__init__(self, name, age)
self.power = power

super().__init__(): 不需傳入 self

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

def greeting(self):
print(f'Hello, my name is {self.name} and i am {self.age} years old')


class Wizard(Person):
def __init__(self, name, age, power):
super().__init__(name, age)
self.power = power

def attack(self):
print(f'attacking with power of {self.power}')

Multiple Inheritance

class Wizard:
def __init__(self, name, power):
self.name = name
self.power = power

def magic_attack(self):
print(f'{self.name} shoot the magic fire ball with {self.power} damage')


class Archer:
def __init__(self, name, arrow_count):
self.name = name
self.arrow_count = arrow_count

def shoot_arrow(self):
print(f'{self.name} shoot {self.arrow_count} arrows')



class HybridMan(Wizard, Archer):
def __init__(self, name, power, arrow_count):
Wizard.__init__(self, name, power)
Archer.__init__(self, name, arrow_count)


super_man = HybridMan('Super Man', 10000, 500)

super_man.magic_attack()
super_man.shoot_arrow()

MRO - Method Resolution Order

class A:
num = 10

class B(A):
pass

class C(A):
num = 1

class D(B, C):
pass

print(D.num) # 1

# 繼承圖
A
/ \
B C
\ /
D

# method 執行順序為 D -> B -> C -> A

# 可以使用 .mro() 得到執行順序
D.mro()

Dunder Methods

python 裡所有東西都是 object, 當我們在創建一個物件時,就會繼承底層 object 的 methods, 所有你看到的 __xxx__ 屬性都是繼承底層 object 來的 method, 但我們也可以通過覆寫去重新實作這些 method

假設我們想要覆寫 __str__ method

class Toy():
def __init__(self, color):
self.color = color

def __str__(self):
return f'{self.color}'

toy = Toy('Yellow')
print(toy.__str__()) # yellow
print(str(toy)) # yellow
  • __name__: 檔案(模組)的名稱, 如果是執行的檔案則是 __main__

functional programming

Build in methods

map

my_list = [1, 2, 3]

def multiply(num):
return num * 2

mapObject = map(multiply, my_list)
new_list = list(mapObject)

filter

test_list = [1, 2, 3]

def is_odd(num):
return num % 2 != 0

odd_numbers = list(filter(is_odd, test_list))

zip

test_list = [1, 2, 3]
test_list2 = ["David", "Amy", "John"]
def is_odd(num):
return num % 2 != 0

zipped_list = list(zip(test_list, test_list2))
print(zipped_list)

# ------------------
# output:
# [(1, 'David'), (2, 'Amy'), (3, 'John')]
# ------------------

reduce

from functools import reduce

my_list = [1, 2 ,3]

def accumulator(acc, number):
return acc + number

print(reduce(accumulator, my_list, 0))

Lambda

語法: lambda param: action(param)

test_list = [1, 2, 3,]

# map
map(lambda num: num * 2, my_list)

# filter
list(filter(lambda num: num % 2 != 0, my_list))

# reduce
reduce(lambda acc, num: acc + num, my_list, 0)

# List Sorting
a = [(0,2), (4,3), (9,9), (10, -1)]
a.sort(key=lambda x: x[1])
print(a)

list, set, dictionary comprehension

這是一個只有 pythonthon 獨有的語法糖
before:

my_list = []

for char in "Heloo":
my_list.append(char)

after:

my_list = [char for char in 'hello']

其他範例:

my_list2 = [num for num in range(0, 200)]

如果我想讓 output 的數字都乘2

my_list2 = [num*2 for num in range(0, 200)]

加上 condition

# **是 power 的意思
# if 後面是結果篩選的條件
my_list2 = [num**2 for num in range(0, 100) if num % 2 == 0]

Dictionary Example:

my_dict = {num:num*2 for num in [1,2,3]}

print(my_dict)

#--------------
# output: {1: 2, 2: 4, 3: 6}
#--------------
simple_dict = {
'a': 1,
'b': 2
}
my_dict = {key:value**2 for key, value in simple_dict.items()}
print(my_dict)

#--------------
# output: { 'a': 1, 'b': 4 }
#--------------

加上 condition

simple_dict = {
'a': 1,
'b': 2
}
my_dict = {k:v**2 for k,v in simple_dict.items()
if v%2 == 0}
print(my_dict)

#--------------
# output: { 'b': 4 }
#--------------

Decorator

Higher Order function

以下兩種都算是 higher order function

  1. 參數為 function
def greet(func):
func()
  1. 返回 function
def greet():
def func():
return 5
return func

Decorator function 的格式

只要符合以下格式就可以當 decorator function, 所以事實上 decorator 只是 higher order function 的語法糖

def my_decorator(func):
def wrap_func():
print("開始執行~")
func()
print("執行成功 😀😀😀😀")
return wrap_func

使用:

@my_decorator
def hello():
print("我是一個 function")

hello()

#-----------
# output:
# 開始執行~
# 我是一個 function
# 執行成功 😀😀😀😀
#-----------

以下兩個語法相等
Higher Order Function 版:

def hello():
print("我是一個 function")

wrap_func = my_decorator(hello)
wrap_func()

Decorator 版:

@my_decorator
def hello():
print("我是一個 function")

hello()

傳參數

傳單個參數

def my_decorator(func):
def wrap_func(param):
print("----------")
func(param)
print("----------")
return wrap_func

傳多個參數: 利用 list unpacking

def my_decorator(func):
def wrap_func(*args, **kwargs):
print("----------")
func(*args, **kwargs)
print("----------")
return wrap_func

Error Handling

Built-In Error

語法

while(True):
try:
age = int(input('What is your age?'))
10/age
except:
print('Please enter a number')
else:
print('Thank you!')
break

抓特定 exception
這邊我們想要抓使用者打 0 的時候的,10/0 發生的錯誤,

while(True):
try:
age = int(input('What is your age?'))
10/age
except ValueError:
print('Please enter a number')
except ZeroDivisionError:
print('Please enter age higher than 0')
else:
print('Thank you!')
break

使用 Error 物件

def sum(num1, num2):
try:
return num1 + num2
except TypeError as err:
print(f'Please enter numbers {err}')

一次抓取兩種錯誤

def sum(num1, num2):
try:
return num1/num2
except (TypeError, ZeroDivisionError) as err:
print(f'Error: {err}')

利用 finally keyword

while(True):
try:
age = int(input('What is your age?'))
except ValueError:
print('Please enter a number')
except ZeroDivisionError:
print('Please enter age higher than 0')
else:
print('Thank you!')
break
finally:
print('ok, i am finally done')

raise keyword主動發出 Error
有時候我們想要針對特定邏輯主動發起錯誤,這時候我們就可以用 raise keyword

def sum(num1, num2):
try:
number = num1/num2
if (number < 0):
raise ValueError('The number should be positive')
return number
except (TypeError, ZeroDivisionError) as err:
print(f'Error: {err}')

Generator

語法
Example 01

def generator_function(num):
for i in range(num):
yield i*2

generator = generator_function(100)
print(next(generator)) # output: 0
print(next(generator)) # output: 2
print(next(generator)) # output: 4

Example 02

def gen_func(num):
for i in range(num):
yield i

for i in gen_func(10):
print(i)

Modules

假設我現在除了 main.py 以外還以一個 utilities.py 的檔案在同一個檔案夾
import 整個 file

import utilities

num = utilies.mutiply(2, 3)

import 個別變數和 methods
注意:如果 import 的 method 與 built in method 撞名, 會執行 import 的 method, 或是可以用 as keyword 將 import 的 method 改名

from utilities import multiply, divide

num = multiply(2,3)

如果要 import 檔案夾裡面的檔案,python 會把檔案夾當作是 package

# import 整個模組
import folder_name.file_name

# import method
from folder_name.file_name import the_method
Python 檔案讀寫(File I/O) Linux | Alter Permissions
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×