123#4#5 8##6
7
|
#def ##square (x):
# return#x**2
#
>>> square
<function ##square at 0x031AA230>
>>> dir (square)
#
['__call__',#'__class__', #'__closure__', #'__code__'##, '__defaults__', '__delattr__', ##'__dict__', '__doc__', '__format__'##, '__get__', '__getattribute__',#'__globals__', #'__hash__', ' __init__', '__module__', '__name__' , '__new__',#'__reduce__', '__reduce_ex__',#'__repr__', '__setattr__', '__sizeof__', '__str__ ' , '__subclasshook__'#,#'func_closure' , 'func_code',#'func_defaults'##, #'func_dict'
, |
其中,一些重要的函數屬性包括以下幾個:
1. __doc__傳回指定函數的文件字串。
#1 6##2 3
4
5
|
def
#square(
x#): """return square of given number"""#
return
#x#**2
#>>>
| ##square
2. __name__傳回函數名字。
#1 6##2 3
4
5
|
def
#square(
x#): """return square of given number"""#
return
#x#**2
#>>>
| ##square
3. __module__傳回函數定義所在模組的名字。
#1 6##2 3
4
5
|
def
#square(
x#): """return square of given number"""#
return
#x#**2
#>>>
| ##square
4. func_defaults傳回一個包含預設參數值的元組,預設參數將在後文進行討論。
5. func_globals傳回一個包含函數全域變數的字典引用。
#1 6##2 3
4
5
|
def
#square(
x#): """return square of given number"""#
return
#x#**2
#>>>##square.func_#globals{'__builtins__': <module '__builtin__' #(built-in#)>, '__name__': '__main__'##,##'square': <function ##square at 0x10f099c08>, '__doc__'#:
|
6. func_dict傳回支援任意函數屬性的命名空間。
#1 6##2 3
4
5
|
def
#square(
x#): """return square of given number"""#
return
#x#**2
#>>>
##square | .
7. func_closure傳回一個胞體元組,其中胞體包含了函數自由變數的綁定,閉包將在後文討論。
函數可以當作參數傳遞給其他函數。這些以其他函數作為參數的函數通常稱為更高階函數,這就構成了函數式程式設計中非常重要的部分。高階函數一個很好的例子就是map函數,該函數接受一個函數和一個迭代器作為參數,並將函數應用於迭代器中的每一項,最後返回一個新的列表。我們將在下面的範例中示範這一點,範例中將前面定義的square函數和一個數位迭代器傳遞給map函數。
#1 ##2 |
>>>#map##(( square, range(10##)
)
[0,1, 4, 9, #16, 25,#36##, 49, 64, #81]
|
此外,函數也可以在其他函數程式碼區塊內部定義,同時也能從其他函數呼叫中返回。
#1 5##2 3
4
|
defouter()
:
# outer_var#=
"outer variable"
# def#inner()
:
#return
#outer_var
return
inner |
在上面的範例中,我們在函數outer中定義了另一個函數inner,並且當函數outer執行時將傳回inner函數。此外,就像其他Python物件一樣,函數也可以賦值給變量,如下所示:
##6
#7
8
9
|
def #outer()
:
outer_var =
"outer variable"
defdef inner()
:
#return
outer_var
#return
inner >>> func #= outer(
)
#>>>
>>> #func<function #inner at##0x031AA270 |
在上面的範例中,outer函數在呼叫時將會傳回一個函數,並將傳回的函數賦值給變數func。最後,變數就可以像被傳回的函數一樣被呼叫:
12
#>>> |
func
(
)
Python #1 ##2 def square(x
|
在上面的square函數中,當包含該函數的模組載入到Python解釋器中時,或者如果該函數在Python REPL中定義,那麼將會執行函數定義語句def square(x)。然而,這對以可變資料結構作為值的預設參數有一些影響,這一點我們將會在後文講述。函數定義的執行會綁定目前本地命名空間中的函數名稱(可以將命名空間當作名字到值的一種映射,並且這種映射還可以嵌套,命名空間和範圍會在另一個教程中詳細介紹)到一個函數對象,該對像是一個對函數中可執行程式碼的包裝器。這個函數物件包含了一個對目前全域命名空間的引用,而目前命名空間指該函數呼叫時所使用的全域命名空間。此外,函數定義不會執行函數體,只有在函數被呼叫時才會執行函數體。
函數呼叫參數
除了正常的參數之外,Python函數也支援數量可變的參數。這些參數有主要有下面描述的三種類別:
1. 預設參數值:這允許使用者為函數的參數定義一些預設值。在這種情況下,可以以更少的參數來呼叫函數,而函數呼叫時未提供的參數,Python會使用預設提供的值作為這些參數值。下面的範例展示了這種用法:
1 | 2
def#show_args(arg, def_arg#=1##, def_arg2=2#)
:
## return "arg={}, def_arg={}, def_arg2={}".format(arg, #def_arg,# #def_arg2)
|
上面範例函數的定義中,包含一個正常位置的參數arg和兩個預設參數def_arg和def_arg2。此函數可以以下面中的任何一種方式進行呼叫:
(1)只提供非預設位置參數值。在本例中,預設參數取預設值:
12345def show_args(#arg,##def_arg=
1
, #def_arg2=#2 ): return "arg={}, def_arg= {}, def_arg2={}".format#(
arg##,
##def_arg, def_arg2)## #
>>> #show_args
|
(2)用提供的值覆寫一些預設的參數值,包括非缺省位置參數:
1234 | # 5
def show_args##(##arg , def_arg=1,#def_arg2=##2)#:
# return "arg={}, def_arg={}, def_arg2={}".format#( arg, def_arg, def_arg2 )
#>>>show_args ("tranquility", "to Houston"##)
'arg=tranquility, def_arg=to Houston, def_arg2=2'
|
12#34 | 5
def #show_args(arg , def_arg=#1,## def_arg2=2)
#:
return #"arg={}, def_arg={}, def_arg2={}".format##( arg, def_arg#, def_arg2 )
#>>>##show_args ("tranquility", #"to Houston", "the eagle 有 landed")
'arg=tranquility, def_arg=to Houston, def_arg2=the eagle has landed' |
當使用可變的預設資料結構作為預設參數時,需要特別小心。因為函數定義只執行一次,所以這些可變的資料結構(引用值)只在函數定義時建立一次。這就意味著,相同的可變資料結構將用於所有函數調用,如下面範例所示:
1234#567 | 8
#def show_args_using_mutable_defaults(arg, #def_arg=##[])
:
def_arg.append ("Hello World"
)
# return "arg={}, def_arg={}".#format#(##arg , def_arg)
#
##>>> ; show_args_using_mutable_defaults("test")
# "arg=test, def_arg=['Hello World']"
>>> show_args_using_mutable_defaults("test 2")
# "arg=test 2, def_arg=['Hello World', 'Hello World']"
|
在每個函數呼叫中,「Hello World」都被加入了def_arg列表中,在呼叫兩次函數之後,預設參數中將有兩個「Hello World」字符串。當使用可變預設參數作為預設值時,注意到這一點非常重要。當我們討論Python資料模型時,將會清楚理解其原因。
2. 關鍵字參數:以「kwarg=value」的形式使用關鍵字參數也可以呼叫函數。其中,kwarg指函數定義中使用的參數名稱。以下面定義的含有預設和非預設參數的函數為例:
12#def ##show_args (arg,
def_arg=##1): return "arg={}, def_arg={} ".format
( | arg
為了示範使用關鍵字參數呼叫函數,下面的函數可以以後面的任何一種方式呼叫:
show_args(arg="test", def_arg=3 |
#1show_args
( | test
######### ######## |
1 #3
# #show_args ("測試",
| ##)
在函數呼叫中,關鍵字參數不得早於非關鍵字參數,所以以下呼叫會失敗:
show_args(def_arg=4 |
1#show_args ("test", arg
= | "testing"
在上面的範例中,參數arg是位置參數,所以值「test」會被指派給它。而試圖將其再次分配給關鍵字arg,意味著在嘗試多重賦值,而這是非法的。
傳遞的所有關鍵字參數必須符合一個函數接受的參數,而包含非可選參數的關鍵字順序並不重要,所以下面調換了參數順序的寫法是合法的:
show_args(def_arg#="testing", #arg="test" |
3. 任意的參數列表:Python也支援定義這樣的函數,該函數可以接受以元組形式傳遞的任意數量的參數,Python教程中的一個例子如下所示:
#1 2def#write_multiple_items( file, separator, ##* args)
: # file. write(separator.#join(args
|
任意數量的參數必須在正常參數之後。在本例中,任意數量參數存在於參數file和separator之後。以下是一個呼叫上述定義函數的範例:
1 2f#= open("test.txt",
"wb" )write_multiple_items(f, #" ", "one",#"two", "three", "four",
| "five"
上面的參數one、two、three、four、five捆綁在一起共同組成了一個元組,透過參數args就能存取該元組。
解包函數參數
有時候,函數呼叫的參數可能是以元組、列表或字典的形式存在。可以透過使用“*”或“**”操作符將這些參數解包到函數內部以供呼叫。以下面的函數為例,函數接受兩個位置參數,並列印出兩個參數的值。
#1 3##2 |
def#print_args##(a, b):
#print a
print #b |
如果提供給函數的參數值是以列表形式存在,那麼我們可以直接將這些值解包到函數中,如下所示:
#12 #4##3
|
>>> args = [1, ##2#]
>>> print_args##(##*args)
1
2
|
1234567 | 8
>>> def (voltage, #state='a stiff', action='voom '): print #"-- This parrot wouldn't",
action,# printprint "if you put", #voltage,
"volts through it.", print #"E's", state
, ### ######"!"######### # ##
>>> ##=##{ "voltage": "four million"#, "state": "bleedin' demised", "action" : "VOOM"}
>>> parrot(**##d)
>>>
This parrot wouldn't#VOOM if you put four million volts through it#. ##E's bleedin' demised
|
1
|
show_args(arg##, *args, #**kwargs )
|
12345#678910111213 | 1415 161718#def show_args(arg,#*args ,
**kwargs):
print #arg #for
item in args:
#print args for key ,
value in#kwargs##: print
key#####,##### ######value###########,##### ######value################# ######value##### ##### ###
>>> args = [1, 2, ##3, 4]
#>> kwargs ##= #dict(名稱# #=# '測試', 年齡=24,#年份=2014)> ;>>
show_args("嘿"#,* args, **kwargs)嘿
1
2
#3
#4
年齡
#24##名稱
測試年份
2014
|
1 | 2
>>> show_args#("hey"# , *args, **kwargs
)
|
在函數呼叫中,普通參數以正常方式提供,而可選參數則可以透過解包的形式到達函數呼叫中。
匿名函數
Python也支援匿名函數,這些函數使用lambda關鍵字建立。 Python中Lambda表達式的形式如下所示:
1lambda_expr ::= "lambda"
| [
Lambda表達式傳回評估後的函數對象,並且具有與命名函數相同的屬性。在Python中,Lambda表達式通常只用於非常簡單的函數,如下所示:
##6
#7
8
9
10
11
12
13
|
>>> square#= lambda x
:
##x**2#>>>##for i in
#range##(#10):
square(
i )
0
#1
##4
#9
16
#25
36
49
64
| #81
上面的lambda表達式的函數與下面命名函數的函數相同:
1
|
def
##square(x)
: |
Nested functions and closures
Defining a function inside a function creates a nested function, as shown below:
##1 2
3
4
5
6
7
|
##` ``python
def outer():
outer_var = "outer variable"
def inner():##
return
outer_var
return
inner` `
`
In this type of function definition, the function inner is only valid inside the function outer, so when the inner function needs to be returned (moved to the outer scope) or passed to another When working with functions, it's often convenient to use nested functions. In the nested function above, a new nested function instance is created every time the outer function is called. This is because the inner function definition is executed every time the outer function is executed, and its function body is will not be executed. Nested functions have access to the environment in which they were created, which is a direct result of Python's function definition semantics. One consequence is that variables defined in the outer function can be referenced in the inner function, even after the outer function has completed execution.
When the inner nested function references a variable in the outer function , we say that the nested function is closed relative to the reference variable. We can access this enclosed variable using a special attribute "__closure__" of the function object, as shown below:
|