python 小社-4

function

數學學過的函式

f(x)=x^2+2x+1\\ f(0)=1\\ f(1)=4\\ f(2)=9\\

丟一個參數x 會得到一個對應的值

python裡的函式

要先宣告才能用

#定義函式
def 函式名稱(參數1, 參數2, ..., 參數n):
  函式裡的程式碼
  return 回傳值

實際使用

#宣告和定義函式
def f(x):
  ans = x**2 + 2*x + 1
  return ans

#使用函式
print(f(1)) #4
print(f(2)) #9

可不可以不要有參數呢

#沒有參數的函數
def sayhi():
  return 'hi'

print(sayhi()) #hi

那可以不要有回傳值嗎

#沒有回傳值的函數
def greeting(name):
  print(f'Hello, {name}')

greeting('Bob') #Hello, Bob

沒有回傳值的函數不能用來賦值

#沒有回傳值的函數
def greeting(name):
  print(f'Hello, {name}')

s = greeting('Bob') #Hello, Bob
print(s) #None

因為 s = greeting('Bob')呼叫到函式

所以那行會印出Hello, Bob

執行到return就會結束

#執行到return就會結束
def f(num1, num2):
  return num1 + num2
  return num1 - num2
  print('Hello, World')
  
print(f(5, 2)) #7

變數的範圍

#沒有回傳值的函數
def greeting(name):
  var_in_function = f'Hello, {name}'
  return var_in_function

greeting('Bob')
print(var_in_function)
#Traceback (most recent call last):
#File "/home/main.py", line 8, in <module>
#print(var_in_function)
##NameError: name 'var_in_function' is not defined

在函式裡宣告的變數

生命只到函數結束

其他酷東東

參數預設值

#宣告和定義函式
def f(x = 0):
  ans = x**2 + 2*x + 1
  return ans

#使用函式
print(f())  #1 x=預設的0
print(f(1)) #4
print(f(2)) #9

需要初始化的時候會用

關鍵字參數

#宣告和定義函式
def minus(num1, num2):
  ans = num1 - num2
  return ans

#使用函式
print(minus(5, 2))           #3
print(minus(num2=5, num1=2)) #-3

可以不用管參數的順序 超棒!

處理大量參數

前面提到的函式寫法最多只能輸入和設定的參數一樣多的變數值 但如果我想寫一個函式 可以有無限個參數呢?

*args

def plus(*args):
  total = 0
  for i in args:
    total += i
  return total

print(plus())           #0
print(plus(1))          #1
print(plus(1, 2))       #3
print(plus(1, 2, 3, 4)) #10

可以輸入幾乎無限個數

輸入的東西會被存到一個Tuple裡

**kwargs

def introduce(**kwargs):
    print(kwargs)

introduce(黑黑='我', 袋鼠='*1') #{'黑黑': '我', '袋鼠': '*1'}

使用之前要先賦值

給的資料會變成一個字典

回傳多個值

def plus(x, y):
  return x+1, y+1

n, m = plus(1, 2)
print(n) #2
print(m) #3

也可以回傳tuple, list...之前教過的東西

把函式當參數

def func(x, f):
  return x + f(x)

def square(x):
  return x ** 2

def power(x):
  return 2 ** x

print(func(3, square)) #12=3 + 3**2
print(func(3, power))  #11=3 + 2**3
print(square(3))       #9
print(power(3))        #8

遞迴

遞迴

在函式裡呼叫自己或其他函數

def f(n):
  if n>0:
    return n
  else:
    return n * f(n-1)

遞迴飯粒-費氏數列

a_1=1, a_2=1\\ a_n=a_{n-1}+a_{n-2}
def fib(n):
  if n==1 or n==2:
    return 1
  else:
    return fib(n-1) + fib(n-2)
  
print(fib(10)) #55

遞迴飯粒-階乘

5!=1\times2\times3\times4\times5\\ n!=1\times2\times3...\times n
def f(n):
  if n==1:
    return 1
  else:
    return n * f(n-1)

Lambda

Lambda

匿名函式 不用定義函式名稱

pow: lambda x, y: x**y
  
print(pow(2, 10)) #1024

只需要寫一行 超簡便

Lambda和迴圈

square = []
for i in range(5):
    square.append(lambda: i**2)
    
print(square[0]()) #16
print(square[2]()) #16
print(square[4]()) #16

想一想 為甚麼square裡都是16

而不是預期的0, 1, 4, 9, 16

會發生這種情況 是因為程式裡的lambda函式不是迴圈裡定義的 而是在迴圈外定義

因為迴圈結束的時候i=4 所以所有的lambda都變成16

square = []
for i in range(5):
    square.append(lambda: i**2)
    print(square[0]())

# 0
# 1
# 4
# 9
# 16
0 1 2 3 4
lambda lambda lambda lambda lambda

list裡存的都是同樣的lambda函式

(記憶體位置一樣)

迴圈結束lambda函式=16

所以最後取值都會得到16

解決方法

square = []
for i in range(5):
    square.append(lambda x=i: x**2)
    
    
print(square[0]()) #0
print(square[2]()) #4
print(square[4]()) #16

用x=i建立一個新的變數

此時每個位置裡的lambda各自獨立

(記憶體位置不同)

得到正確的答案

把lambda放進函式

def make_incrementor(n):
    return lambda x: x + n

f = make_incrementor(42)
print(f(0)) #42
print(f(1)) #43
print(f(2)) #44

map(補充)

map(function, iterable object)

 

前面放入函式 後面放入可以迭代的東西

例如list 功能簡單來說就是把前面的函式套用到後面的所有物件

實際操作

def plus_one(n):
    return n + 1

num = [1, 2, 3, 4, 5]
num = map(plus_one, num)
print(list(num)) #[2, 3, 4, 5, 6]

第4行回傳一個map

要取用時記得改成你要的型別

Class

其實這堂課沒有要教這個

但既然函式都講了 就順便幫你們遇襲下禮拜的課吧

Title Text

Class

建立一個自訂的型態

class class_name:
  i = 123
  def f():
    ...

class_name.i
class_name.f()

Title Text

__init__

初始化 就是建立變數的時候給他一些設定

class student:
  def __init__(self, name, height, weight, age, gender):
    self.name = name
    self.height = height
    self.weight = weight
    self.age = age
    self.gender = gender
   
I = student('嘿嘿嘿', 170, 50, 17, 'M')
print(I.name, I.height, I.weight, I.age, I.gender) #嘿嘿嘿 170 50 17 M

__init__

class student:
  def __init__(self, name, height, weight, age, gender):
    self.name = name
    self.height = height
    self.weight = weight
    self.age = age
    self.gender = gender
   
I = student(height = 170, weight = 50, name = '嘿嘿嘿', gender = 'M', age = 17)
print(I.name, I.height, I.weight, I.age, I.gender) #嘿嘿嘿 170 50 17 M

用剛剛提過的關鍵字參數 就不用照順序打了

幫class寫函式

class student:
  def __init__(self, name, height, weight, age, gender):
    self.name = name
    self.height = height
    self.weight = weight
    self.age = age
    self.gender = gender
  def introduce(self):
    print(f'Hi, my name is {self.name}. I am {self.age} years old')
   
I = student(height = 170, weight = 50, name = '嘿嘿嘿', gender = 'M', age = 17)
I.introduce() #Hi, my name is 嘿嘿嘿. I am 17 years old

Python 內建函式

ord chr

print(ord('a'))        #97
print(chr(97))         #a
print(chr(ord('a')+1)) #b

ord會把字元轉成ascii

chr會把ascii轉成字元

all

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True
  

如果iterable裡的所有元素都為True

則回傳True 否則回傳False

等價於上面的程式碼

any

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

如果iterable裡的任一個為True

則回傳True 否則回傳False

等價於上面的程式碼

bin

print(bin(3))   #0b11
print(bin(-10)) #-0b1010

將整數轉成0b開頭的二進位制字串

format

print(format(10, 'b')) #1010
print(format(10, 'o')) #12
print(format(10, 'x')) #a

可以轉變成各種不同進位

= 將標誌放置在最左側
b 將數值轉換為等價的二進位制
o 將數值轉換為八進位制格式
x 將數值轉換為十六進位制格式
d 將給定值轉換為小數
E 科學格式,大寫為 E
X 將數值轉換為大寫的十六進位制格式

eval

print(eval('1+1')) #2
print(eval('print('Hello, world!')')) #Hello, world!

把函式裡的字串直接當作程式碼執行

不能用來賦值

這題就輕鬆解決了

exec

exec('''
for i in range(10):
    print(i)
''')

把函式裡的多行字串直接當作程式碼執行

如果有回傳值會回傳None

python有非常多內建的函式

這裡只介紹了其中幾種基本或常用的

如果想知道更多可以看官方文件

下課囉~~~

Made with Slides.com