神奇的海螺,装饰器永远滴神
1. 今天实现贪吃蛇代码功能时,发现有一个函数需要添加功能,但是不能动函数内部的代码,因此了解到有一种神奇的海螺叫做装饰器,能够实现此功能
2. 首先让我们定义一个函数,只能打印出Hello 夜斗小神社
```python
def greet():
print("Hello 夜斗小神社 !")
```
3. 现在我们想要在不改变f1函数内部代码的前提下,增加一个打招呼后的礼貌用语,比如说"请多指教",我们可以这样做!
```python
def decorate(fun):
fun()
print("请多指教")
return fun
@decorate()
def greet():
print("Hello 夜斗小神社 !")
greet()
'''
打印结果:
Hello 夜斗小神社 !
请多指教
Hello 夜斗小神社 !
Process finished with exit code 0
'''
```
- 首先我们要知道`@decorate()等价于greet = decorate(greet)`,替换一下其实就是如下代码
```python
def decorate(fun):
fun()
print("请多指教")
return fun
def greet():
print("Hello 夜斗小神社 !")
greet = decorate(greet)
greet()
'''
打印结果:
Hello 夜斗小神社 !
请多指教
Hello 夜斗小神社 !
Process finished with exit code 0
'''
```
- 如果一个函数上方有装饰器,首先会执行装饰器的作用修饰该函数,如下代码所示, 可以直接执行函数!
```python
def decorate(fun):
fun()
print("请多指教")
return fun
@decorate()
def greet():
print("Hello 夜斗小神社 !")
'''
结果如下:
Hello 夜斗小神社 !
请多指教
Process finished with exit code 0
'''
```
但是,这样做有个缺点:尽管你没有调用greet()函数,它还是执行了装饰器的功能,你忘了自己本质上是为了给greet()函数增加功能才使用的装饰器,当调用greet()函数时,装饰器才起作用,因此修改的代码如下:
```python
def decorate(fun):
def inner():
fun()
print("请多指教")
return inner
@decorate
def greet():
print("Hello 夜斗小神社 !")
greet()
'''
结果如下:
Hello 夜斗小神社 !
请多指教
Process finished with exit code 0
'''
```
- 这样子不仅实现了增加功能的装饰器,原函数内部一点都没有改变,**当你调用greet()函数时,其实返回的时inner的函数地址,每次调用greet()函数其实就是调用inner函数,这样子只要在inner函数内部修改功能就可以间接增加greet()函数功能而不改变greet函数内部代码**
- 上面讲的是原函数没有传入参数,那如果有参数怎么办?,其实道理和上方是一样的,下面我们直接来看代码!
```python
def decorate(fun):
def inner(name):
fun(name)
print("请多指教")
return inner
@decorate
def greet(name):
print(f"Hello {name} !")
greet("夜斗小神社")
'''
结果如下:
Hello 夜斗小神社 !
请多指教
Process finished with exit code 0
'''
```
- 很简单只要保证`inner()中的参数与greet()中的参数名一致即可`
- 那如果装饰器的应传入的参数首先是一个变量而不是需要增加功能的函数怎么办呢?很简单,两层闭包就很容易实现啦!具体看代码如下:
```python
def decorate_2(arg):
def decorate_1(fun):
def inner(name):
fun(name)
print("请多指教")
# 打印出fun函数参数的名字,以及arg变量是啥
print(f'{fun.__name__}, {arg}')
return inner
return decorate_1
@decorate_2("夜斗小神社")
def greet(name):
print(f"Hello {name} !")
greet("夜斗小神社")
'''
结果如下:
Hello 夜斗小神社 !
请多指教
greet, 夜斗小神社
Process finished with exit code 0
'''
```
- `def decorate_2(arg)接受@decorate_2传入的参数"夜斗小神社",decorate_1接受的还是greet()函数`
- 好啦,以上就是关于装饰器相关知识的分享啦!
- **在这个星球上,你很重要,请珍惜你的珍贵** ~~~~夜斗小神社