function 主要有三個部分主成,input、function本體、output.開頭是使用 def 做宣告,input 就是 () 內的參數,return 就是 output 值.
>>> def add_nums(num1,num2):
... return num1 + num2
...
>>> print(add_nums(2,3))
5
但 input 跟 output 可以不給,代表不需傳入參數且不會得到回傳值,例如下面的 function 就只有 print 字串.
>>> def printHello():
... print('Hello')
...
>>> printHello()
Hello
如果使用變數去接一個沒有回傳值的 function 會得到 None.
>>> hello_str = printHello()
Hello
>>> print(hello_str)
None
當然 function 也是物件,python 會建立一個 function name 的變數,指到 funtcion 物件.
>>> id(printHello)
4344525168
>>> type(printHello)
<class 'function'>
當在 def function 的冒號(:) 的下一行可以定義一串字串來描述該 function 是在做些什麼事.定義好後就可以透過 __doc__
來看 function 的功能.
>>> def printHello():
... '''
... only print Hello string
... '''
... print('Hello')
...
>>>
>>> print(printHello.__doc__)
only print Hello string
沒定義 docstring 的話值是 None.
>>> print(add_nums.__doc__)
None
也可以透過 help 看到內容.
>>> help(printHello)
Help on function printHello in module __main__:
printHello()
only print Hello string
scope 有分成 global、local、built-in 三種.built-in scope 是在一開始就先被 python 定義好的.function 裡的為 local scope.global 則是不包含在 function 裡的.
>>> global_num = 1
>>> def print_numbers():
... local_num = 5
... print('global num {}'.format(global_num))
... print('local num {}'.format(local_num))
... print('built-in variables {}'.format(dir))
...
>>> print_numbers()
global num 1
local num 5
built-in variables <built-in function dir>
當在全域的 scope 裡呼叫區域變數會出現變數沒定義的 Error.
>>> local_num
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'local_num' is not defined
在 python 裡可以覆寫全域或 built-in scope 的變數.原本的 dir 是可以查看某個物件提供的 function.
>>> dir('')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>>
但如果被覆寫了,原本 built-in 的 dir 就被覆蓋了,感覺這是很危險的,所以要注意.
>>> def dir():
... print('empty dir')
...
>>> dir('')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: dir() takes 0 positional arguments but 1 was given
>>> dir()
empty dir
由於 python 的變數不用一開始就宣告好型態,會在直譯的當下轉成適合的型態來操作,所以下面的例子可以傳入 int、float、string.因為這些物件都有自訂的 + 方法,所以不會有問題.
>>> def add_nums(num1,num2):
... return num1 + num2
...
>>> add_nums(1,2)
3
>>> add_nums(1.1,2.2)
3.3000000000000003
>>> add_nums('1','2')
'12'
但如果型態不一樣就會出錯了,因為 string 本來就不能 + int 物件.
>>> add_nums('1',2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in add_nums
TypeError: can only concatenate str (not "int") to str
function 的參數可以給預設值,如果沒帶入參數值給 function 時,會使用預設值當作 input.
>>> def say_hello(name = 'Python'):
... print('Hello {}'.format(name))
...
>>> say_hello()
Hello Python
>>> def add_nums(num1,num2 = 10):
... return num1 + num2
...
>>> add_nums(5)
15
>>> add_nums(5,2)
7
如果使用 mutable 當作 default 的物件,每次呼叫該 function 所引用的物件都是同一個的.
>>> def to_Set(value,default_set=set([])):
... default_set.add(value)
... return default_set
...
>>> to_Set(5)
{5}
>>> to_Set('Daniel')
{'Daniel', 5}
如果改成 default 是 None,如果是 None 就建立新的 Set,所引用的物件就不會是相同的.
>>> def to_Set(value,default_set=None):
... if default_set is None:
... default_set=set([])
... default_set.add(value)
... return default_set
...
>>> to_Set(5)
{5}
>>> to_Set('Daniel')
{'Daniel'}
>>> nums = set([1,2,3,4,2,5])
>>> to_Set(99,nums)
{1, 2, 3, 4, 5, 99}