網站首頁 編程語言 正文
1.引子:函數也是對象
木有括號的函數那就不是在調用。
def hi(name="yasoob"):
return "hi " + name
print(hi())
# output: 'hi yasoob'
# 我們甚至可以將一個函數賦值給一個變量,比如
greet = hi
# 我們這里沒有在使用小括號,因為我們并不是在調用hi函數
# 而是在將它放在greet變量里頭。我們嘗試運行下這個
print(greet())
# output: 'hi yasoob'
# 如果我們刪掉舊的hi函數,看看會發生什么!
del hi
print(hi())
#outputs: NameError
print(greet())
#outputs: 'hi yasoob'
2.函數內的函數
(1)在python中,一個函數內能嵌套定義另一個函數,并且可以在該大函數內調用該小函數。
def hi(name="yasoob"):
print("now you are inside the hi() function")
def greet():
return "now you are in the greet() function"
def welcome():
return "now you are in the welcome() function"
print(greet())
print(welcome())
print("now you are back in the hi() function")
hi()
#output:now you are inside the hi() function
# now you are in the greet() function
# now you are in the welcome() function
# now you are back in the hi() function
# 上面展示了無論何時你調用hi(), greet()和welcome()將會同時被調用。
# 然后greet()和welcome()函數在hi()函數之外是不能訪問的,比如:
greet()
#outputs: NameError: name 'greet' is not defined
(2)開始神奇的是,大函數的返回值可以是一個函數:
def hi(name="yasoob"):
def greet():
return "now you are in the greet() function"
def welcome():
return "now you are in the welcome() function"
if name == "yasoob":
return greet #這里!!
else:
return welcome
a = hi()
print(a)
#outputs: <function greet at 0x7f2143c01500>
#上面清晰地展示了`a`現在指向到hi()函數中的greet()函數
#現在試試這個
print(a())
#outputs: now you are in the greet() function
在 if/else 語句中我們返回 greet 和 welcome,而不是 greet() 和 welcome()。
為什么那樣?這是因為當你把一對小括號放在后面,這個函數就會執行;然而如果你不放括號在它后面,那它可以被到處傳遞,并且可以賦值給別的變量而不去執行它。
當我們寫下 a = hi(),hi() 會被執行,而由于 name 參數默認是 yasoob,所以函數 greet 被返回了。
PS:如果我們打印出 hi()(),這會輸出 now you are in the greet() function。
(3)最后要說的是函數作為參數傳入一個函數:
def hi():
return "hi yasoob!"
def doSomethingBeforeHi(func):
print("I am doing some boring work before executing hi()")
print(func())
doSomethingBeforeHi(hi)
#outputs:I am doing some boring work before executing hi()
# hi yasoob!
3.裝飾器小栗子
終于來到了帶@的裝飾器,其實就是帶了@帽子的函數作為參數,傳入@后面的函數中。
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
"""Hey you! Decorate me!"""
print("I am the function which needs some decoration to "
"remove my foul smell")
a_function_requiring_decoration()
#outputs: I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
#the @a_new_decorator is just a short way of saying:
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
上面的代碼等價于我們熟悉的:
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")
a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()
a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
不過一開始上面被裝飾過的函數名字已經悄悄發生“改變”,如果print下可以看出(如下代碼)。
解決方案:
@wraps接受一個函數來進行裝飾,并加入了復制函數名稱、注釋文檔、參數列表等等的功能。這可以讓我們在裝飾器里面訪問在裝飾之前的函數的屬性。
print(a_function_requiring_decoration.__name__)
# Output: wrapTheFunction
最終加上@wraps的代碼如下:
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
"""Hey yo! Decorate me!"""
print("I am the function which needs some decoration to "
"remove my foul smell")
print(a_function_requiring_decoration.__name__)
# Output: a_function_requiring_decoration
5.property和setter用法
class Timer:
def __init__(self, value = 0.0):
self._time = value
self._unit = 's'
# 使用裝飾器的時候,需要注意:
# 1. 裝飾器名,函數名需要一直
# 2. property需要先聲明,再寫setter,順序不能倒過來
@property
def time(self):
return str(self._time) + ' ' + self._unit
@time.setter
def time(self, value):
if(value < 0):
raise ValueError('Time cannot be negetive.')
self._time = value
t = Timer()
t.time = 1.0
print(t.time)
原文鏈接:https://blog.51cto.com/u_15717393/5470902
相關推薦
- 2023-02-01 Bat腳本-Call,Start,直接調用,goto?四種方式調用批處理_DOS/BAT
- 2023-02-09 Go語言高效編程的3個技巧總結_Golang
- 2022-04-23 window.open打開新窗口設置顯示位置及大小
- 2022-06-10 SQL?Server中函數、存儲過程與觸發器的用法_MsSql
- 2022-04-09 cas5 編譯安裝依賴時提示: Failure to find net.shibboleth.too
- 2022-08-04 基于Python實現煙花效果的示例代碼_python
- 2022-09-16 nginx緩存以及清除緩存的使用_nginx
- 2022-07-01 Armbian5.9.0安裝docker及部署可視化portainer的詳細教程_docker
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支