11日目関数オブジェクト、関数の入れ子、名前空間とスコープ、デコレータ

Pythonでは、関数はファーストクラスのオブジェクトであり、関数はファーストクラスの市民です

本质上函数可以当变量用
def func():                # func=函数的内存地址
    print("from func")


 1.可以赋值
f = func
print(f)            #打印的结果就是func的内存地址
f()                  #运行代码func(),from func

2.可以当作参数传给另一个函数
def foo(x):
    print(x)
    x()               #加括号触发func代码的运行,from func
func=内存地址
foo(func)

3.可以当作函数的返回值
def foo(x):
    return x


res=foo(func)
print(res)

4.可以当作容器类型的元素
l=[func]
l[0]()                 #把func函数名当作元素放进l的列表中.运行代码结果为from func
银行取款功能
def withdraw():
    print("提款")
def tranfer():
    print("转账")
def check_balance():
    print("查询余额")
def save():
    print("存款")


func_dic = {
    
    
    "1": ["提款", withdraw],
    "2": ["转账", tranfer],
    "3": ["查询余额", check_balance],
    "4": ["存款", save]
}
while True:
    print("0" "退出")
    for k,v in func_dic.items():
        print(k)
    choice = input("输入指令").strip()
    if choice == "0":
        break
    if choice in func_dic:
        func_dic[choice][1]()
    else:
        print("输入错误")

入れ子関数呼び出し

def max2(x,y):
    if x>y:
        return x
    else:
        return y


def max4(a, b, c, d):
    res1 = max2(a, b)
    res2 = max2(res1, c)
    res3 = max2(res2, d)
    return res3

print(max4(11, 99, 66, 55))    #打印结果为99

関数のネストされた定義

def f1():
    x = 10
    def f2():
        print("from f2")
    print(x)         #一个变量放进函数里面只能在函数里面使用
    print(f2)
f1()
print(x)   #打印结果不显示
print(f2)  #打印结果不显示

名前空間:
名前が格納されている場所。組み込みの名前空間:組み込みの名前。
ライフサイクル:Pythonインタープリターの起動時に生成され、閉じられると破棄されます。

    全局名称空间:存放的是顶级的名字(只有不在函数内的都是顶级名字)
            生命周期:运行python文件时则产生,python文件运行完毕则销毁
运行python,启动python解释器,先运行内置名称空间文件,然后会立刻运行全局名称空间文件,再是局部空间
x = 10
y = 20
if 1 > 0:
    z = 30

with open("a.txt", mode="wt")as f:
    a = 333

while True:
    c = 444
以上这些都是属于全局名称空间

    局部名称空间:存放的是函数内的名字
            生命周期:定义函数时是不会产生名称空间的,调用函数则产生,函数调用完毕则销毁
x=10
def foo(m):
    m=111
    n=222
foo(111)

内置名称空间就一个,一个文件就一个全局名称空间,调用一个函数就有一个局部空间名称,局部空间名称有好多个
名称空间找名字的优先级关系:先从当前空间找,一级一级往上找.名称空间之间没有嵌套关系
在函数内找名称,先从函数局部名称空间里找名字,再去全局名称空间找,最后再去内置名称空间找
如果在全局名称空间找,就先从全局名称空间里面找名字,再去内置空间找,不会去局部名称空间找
核心:名字的访问优先级
基于当前的位置向外查找
函数内->外层函数->...->全局->内置
在定义的时候不要把内置的名字拿来定义.这样有可能会覆盖内置的名字
len = 10

def func():
    len = 20
    print(len)         #len在局部名称空间内,运行结果先运行len=20

func()
print(len)             #len在全局名称空间内,运行结果len=10


案例
def f1():
    # x=555
    def f2():
        # x=666
        print(x)
    f2()
 x = 444
f1()
 改代码运行时,先从局部名称空间最里层,先找到x=666,
再找到x=555,如果局部名称空间内没有找到名称时,会找到全局名称空间x=444
按照顺序找到任意一个名称都不会再继续往外层寻找了

LEGB :(関数定義段階で確立されます)
L:ローカル関数の内部スコープ
E:囲んでいる関数の内部と組み込み関数の間
G:グローバルなグローバルスコープ
B:組み込みの組み込み関数

名称空间与作用域的关系时在函数定义阶段(扫描语法时)就确立的,与什么时候调用以及调用位置无关
案例1:
x=111
def f1():
    print(x)

def f2():
    x = 222
    f1()
f2()      在定义阶段,x=111,结果为111

案例2:
x = 111
def f1():
    print(x)
    x = 222     #局部名称空间的x是先引用后定义的,运行代码会直接语法报错
f1()

スコープ
グローバルスコープ:組み込み名前空間+グローバル名前空間
機能:グローバルサバイバル、グローバル有効
ローカルスコープ:ローカル名前空間名
機能:一時インベントリ、ローカル有効

グローバル
ケース1グローバル名前空間の名前が変数タイプの場合

l = []
def func():
     l.append(1111)
func()
print(l)

ケース2グローバルスペース名が不変型の場合

x = 111
def func():
    global    #当全局的值是不可变类型时,加了global全局作用域后会把全局的x=111的值改成函数里面x=222的值
    x = 222
func()
print(x)
尽量不要用global局部作用域改全局的作用域

非ローカル

x = 111
def f1():
    x = 222
    def f2():
        nonlocal x    # 声明函数名是来自外层函数的,不是全局。加了nonlocal打印结果为x=333
        x=333
    f2()
    print(x)
f1()
#nonlocal会把外层的f1的x=222改成内层的x=333,如果说第一个外层没有找到局部名会一直往外层找,找到全局层之前还找不到会直接报错

クロージャ関数:
closed:関数が定義されたときに関数内の関数を参照します。
パッケージ:関数が外部関数スコープの名前を参照することは価値があります。

def outter():
    x = 111

   def wrapper():
        print(x)

   return wrapper


f = outter()
print(f)

def foo():
    x=222
    f()

foo()

関数本体コードのパラメーターを渡すスキーム

方案1:直接用参数传
def wrapper(x):
    print(x)

wrapper(111)
wrapper(222)
wrapper(333)


方案2:闭包函数传参
def outter(x):
    # x=111
    def wrapper():
        print(x)
    return wrapper
f1 = outter(111)
f1()
f2 = outter(222)
f2()
f3 = outter(333)
f3()

デコレータデコレータ
とは?
デコレータは、装飾されたオブジェクトに新しい機能を追加するために使用されるツールです。

デコレータを使用する理由
オープンおよびクローズの原則:ソフトウェアがオンラインになったら、ソースコードを変更して拡張関数を開発するために、ソフトウェアをクローズする必要があります。
原則:
1
関数内のソースコードを変更しないでください。2。呼び出しを変更しないでください。関数のメソッド
デコレータは従うことです原則1と2の前提の下で、装飾されたオブジェクトに新しい関数を追加します

デコレータの実装方法
要件:関数インデックスの実行時間をカウントする関数を追加します

方案一:
import time


def index():
    start = time.time()
    time.sleep(1)
    print("from index")
    stop = time.time()
    print("run time is %s" % (stop - start))


index()
方案二:
import time


def index():
    time.sleep(1)
    print("from index")


start = time.time()
index()
stop = time.time()
print("run time is %s" % (stop - start))
方案三:
import time


def index():
    time.sleep(1)
    print("from index")

def wrapper():
    start = time.time()
    index()
    stop = time.time()
    print("run time is %s" % (stop - start))

wrapper()
方案四:
import time


def index():
    time.sleep(1)
    print("from index")

def wrapper(func):
    start = time.time()
    func()
    stop = time.time()
    print("run time is %s" % (stop - start))

wrapper(index)
方案五:
import time


def index():
    time.sleep(1)
    print("from index")

def wrapper(func):
    start = time.time()
    func()
    stop = time.time()
    print("run time is %s" % (stop - start))

wrapper(index)

おすすめ

転載: blog.csdn.net/Yosigo_/article/details/111919044
おすすめ