# example1
def f():
# function body
print("Hello World")
f() # function call
Hello World
# example2
def f(n):
# function body
print(n)
x = "Hello World"
f(x) # function call
Hello World
# example 3
def g(n):
# function body
tmp = 1
for i in range(1, n+1 ,1):
tmp = tmp * i
return tmp
x = g(5) # function call, 5*4*3*2*1
print(x)
120
# example 4
# Computes the total cost, including 3% sales tax
# on number items at a cost of price each
def total_cost(number, price):
# function body
tax_rate = 0.03 # 3% sales tax
cost = number * price
total = cost + (cost*tax_rate)
return total
n = 5
p = 30
bill = total_cost(n, p)
print('Bill: ',bill)
Bill: 154.5
如果撰寫程式時,將 return object 的 object 省略,在呼叫 function 的階段會發生什麼事?
# return statement without object
def f():
x = 5
return
y = f() # function call
print(y)
# answer
def f():
x = 5
return
y = f() # function call
print(y)
None
# without return statement
def f():
x=5
y = f()
print(y)
None
# 請計算四個人的 BMI: 1.63m-50kg, 1.8m-88kg, 1.9m-60kg, 1.5m-60kg
height = 1.63 # 公尺
weight = 50 # 公斤
calculate = weight / (height*height)
if calculate < 18.5:
result = '過輕'
elif 18.5 < calculate and calculate < 24:
result = '正常'
else:
result='過重'
print("result1: ", result)
# person 2 =====================================
height = 1.8 # 公尺
weight = 88 # 公斤
calculate = weight / (height*height)
if calculate < 18.5:
result = '過輕'
elif 18.5 < calculate and calculate < 24:
result = '正常'
else:
result='過重'
print("result2: ", result)
# person 3 =====================================
height = 1.9 # 公尺
weight = 60 # 公斤
calculate = weight / (height*height)
if calculate < 18.5:
result = '過輕'
elif 18.5 < calculate and calculate < 24:
result = '正常'
else:
result='過重'
print("result3: ", result)
# person 4 =====================================
height = 1.5 # 公尺
weight = 60 # 公斤
calculate = weight / (height*height)
if calculate < 18.5:
result = '過輕'
elif 18.5 < calculate and calculate < 24:
result = '正常'
else:
result='過重'
print("result4: ", result)
result1: 正常 result2: 過重 result3: 過輕 result4: 過重
# 公式:體重(公斤) / 身高^2(公尺^2)
# 過輕:BMI < 18.5; 正常:18.5≦ BMI<24; 過重:24≦BMI
def bmi(height, weight):
calculate = weight / (height*height)
if calculate < 18.5:
result = '過輕'
return result
elif 18.5 < calculate and calculate < 24:
result = '正常'
return result
else:
result='過重'
return result
h = 1.63 #公尺
w = 50 #公斤
r = bmi(h, w)
print("result1: ", r) # 正常
# one line
print("result2: ", bmi(1.8, 88)) # 過輕
print("result3: ", bmi(1.9, 60)) # 過輕
print("result4: ", bmi(1.5, 60)) # 過輕
result1: 正常 result2: 過重 result3: 過輕 result4: 過重
# Procedural decopsition example
# pizza-making robot
def mixing_the_dough() #和麵
def rolling_it_out() #桿麵
def adding_toppings() #放料
def baking_it() #烤
x = 4**0.5
print(x)
y = 2**0.5
print(y)
def get_sqrt(num):
return num**0.5
print(get_sqrt(4))
print(get_sqrt(2))
2.0 1.4142135623730951 2.0 1.4142135623730951
import math
print(math.sqrt(4))
print(math.sqrt(2))
2.0 1.4142135623730951
定義一個function f,可以將 a, b 的值互換後,需回傳值回來。
# sample answer 1
def swap(a, b):
c = a
a = b
b = c
return a, b
a = 1
b = 2
a, b = swap(a,b)
print(a ,b)
2 1
# sample answer 2
def swap(a, b):
return b, a
a = 1
b = 2
a, b = swap(a, b)
print(a, b)
2 1
# exsample answer 3
# without function
a = 1
b = 2
a, b = b, a
print(a, b)
2 1
x = 99 # Global (module) scope x
def f():
x = 88 # Local (function) scope x: a different variable
當我們使用variable, python 在scope中搜尋variable的順序為 L, E, G 最後是 B
# Global scope
x = 99 # X and f assigned in module: global
def f(y): # Y and Z assigned in function: locals
# Local scope
z = x + y # X is a global
return z
f(1) # function1 in module: result=100
100
import builtins
dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__IPYTHON__', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
# Global scope
w = 21 # W and outer assigned in module: global
def outer(x):# X and inner assigned in enclosing function: Enclosing def locals
def inner(y): # Z, Y assigned in function: local
z = w + x + y # W is a global (21+88+1)
print(z)
inner(1)
outer(88)
110
# example1
x = 'Spam'
def func():
print(x)
func()
# answer
x = 'Spam'
def func():
print(x)
func()
Spam
# example2
x = 'Spam'
def func():
x = 'HI!'
func()
print(x)
# answer
x = 'Spam'
def func():
x = 'HI!'
func()
print(x)
Spam
# example3
x = 'World'
def func():
x = 'Hello'
print(x)
func()
print(x)
# answer
x = 'World'
def func():
x = 'Hello'
print(x)
func()
print(x)
Hello World
# example 4
w = 22
def outer():
w = 23
def inner():
w = 24
print('first: ', w) # first print
inner()
print('second: ', w) # second print
outer()
print('third: ', w) # third print
# answer
w = 22
def outer():
w = 23
def inner():
w = 24
print('first: ', w) # first print
inner()
print('second: ', w) # second print
outer()
print('third: ', w) # third print
first: 24 second: 23 third: 22
# example
x = 88 # Global x
def f():
global x
x = 99 # Global x: outside def
f()
print(x)
99
Everything in python is an object
a = 3
print(id(a), id(3)) # id(a) 表示 a 實際的物件記憶體位址
10910464 10910464
a = 3 # 將 a 指到 一個 immutable object (list)
b = a
print(id(a), id(b))
a += 2 # a 所指的位址已經改變了, 但不影響 b
print(id(a), id(b)) # 可看到 a 跟 b 的記憶體位址已經不一樣了
10910464 10910464 10910528 10910464
a = [1,2,3] # 將 a 指到 一個 mutable object (list)
b = a
print(id(a), id(b)) # 可看到這時 a 跟 b 的記憶體位址是一樣的
a[0] = 's'
print(id(a), id(b)) # 可看到這時 a 跟 b 的記憶體位址依舊是一樣的,從頭到尾都沒變化
139663417770952 139663417770952 139663417770952 139663417770952
def f(a): # a is assigned to (references) the passed object
a = 99 # Changes local variable a only
b = 88
f(b) # a and b both reference same 88 initially
print(b) # b is not changed
88
def change_element(b): # Arguments assigned references to objects
print('before_change b:', b)
b[0] = 'spam' # Changes shared object in place
print('after_change b:', b)
print('after_change b_id:', id(b))
test_list = [1, 2]
print('list_id:', id(test_list))# original id of test_id
change_element(test_list) # Pass test_list (mutable object)
print('list:', test_list) # elements of test_list is different (changed)
print('list_id:', id(test_list))
list_id: 139663066640648 before_change b: [1, 2] after_change b: ['spam', 2] after_change b_id: 139663066640648 list: ['spam', 2] list_id: 139663066640648
Avoiding Mutable Argument Changes: If we don’t want in-place changes within functions to impact objects we pass to them, though, we can simply make explicit copies of mutable objects,
def change_element(b): # Arguments assigned references to objects
b[0] = 'spam' # Changes shared object in place
test_list = [1, 2]
copy_list = test_list[:] # copy a new list
print('before change: test_list:', test_list, '; list_id:', id(test_list))
print('before change: copy_list', copy_list, '; copy_list_id:', id(copy_list))
change_element(copy_list)
print('after change: test_list:', test_list, '; test_list_id:', id(test_list)) # the same id
print('after change: copy_test_list:', copy_list, '; copy_test_list_id:', id(copy_list)) # the same id
before change: test_list: [1, 2] ; list_id: 139663067218376 before change: copy_list [1, 2] ; copy_list_id: 139663502102344 after change: test_list: [1, 2] ; test_list_id: 139663067218376 after change: copy_test_list: ['spam', 2] ; copy_test_list_id: 139663502102344
Arguments are passed by automatically assigning objects to local variable names
Assigning to argument names inside a function does not affect the caller
Changing a mutable object argument in a function may impact the caller.
# positionals example
def f(x, y, z):
print(x, y, z)
f(1, 2, 3)
1 2 3
# keywords example
def f(x, y, z):
print(x, y, z)
# In real cases, we should not change the order of the argument names. It is hard for other people to understand your code.
f(z=4, y=5, x=6)
6 5 4
# defaults and postional
def f(x, y, z = 3):
print(x, y, z)
f(4, 5)
f(4, 5, 6)
4 5 3 4 5 6
# varargs collecting, one * for tuple
def f1(*args):
print(args)
f1(1, 2, 3, 4, 5, 6, 8, 'hello')
f1('how', 'do', 'you', 'do')
def f2(x, y, *args):
print(x,y)
print(args)
f2(1,2,3,4,5,6,8,'hello')
(1, 2, 3, 4, 5, 6, 8, 'hello') ('how', 'do', 'you', 'do') 1 2 (3, 4, 5, 6, 8, 'hello')
# varargs collecting, two * for dictionary
def f(**kwargs):
print(kwargs)
f(key1=1, key2=2, key3=3)
{'key1': 1, 'key2': 2, 'key3': 3}
# mix varargs collecting
def mix(x, y, *args, **kwargs):
print(x,y)
print(args)
print(kwargs)
mix(1, 2, 3, 4, 5, 6, 8, 'hello', key1=1, key2=2, key3=3)
1 2 (3, 4, 5, 6, 8, 'hello') {'key1': 1, 'key2': 2, 'key3': 3}
# Varargs unpacking
def f(x, y, z):
print(x, y, z)
some_args=(1, 2, 3)
f(*some_args)
some_kwargs = {'x': 1, 'y': 2, 'z': 3}
f(**some_kwargs)
1 2 3 1 2 3
# example
# What is the output of the following code?
def f1(a, b=4, c=5):
print(a, b, c)
f1(1, 2)
def f2(a, b, c=5):
print(a, b, c)
f2(1, c=3, b=2)
def f3(a, *args):
print(a, args)
f3(1, 2, 3)
def f4(a, **kargs):
print(a, kargs)
f4(a=1, c=3, b=2)
def f5(a, b, c=3, d=4):
print(a, b, c, d)
f5(1, *(5, 6))
1 2 5 1 2 3 1 (2, 3) 1 {'c': 3, 'b': 2} 1 5 6 4
# Function objects example: assigned to name
def f(msg):
print(msg)
f('hello word!')
x = f
x('hello word!')
hello word! hello word!
# Function objects example: pass to other function
def f(msg):
print(msg)
def g(f_obj, arg):
f_obj(arg)
g(f, 'Hello world!') # Pass the function to another function
Hello world!
# Function objects example: embedded in data structures
def f(msg):
print(msg)
test_list = [(f, 'Hello'), (f, 'World!!')]
for (f_obj, arg) in test_list:
f_obj(arg) # Call functions embedded in containers
Hello World!!
# Function objects example: return
def f(msg):
def g(msg2):
print(msg+':'+msg2)
return g
t = f('hello')
t('world!')
hello:world!