道のPython Pythonのグローバル変数とローカル変数、入れ子関数、再帰関数

まず、ローカル変数とグローバル変数

 

1、サブルーチンと呼ばれるローカル変数で定義された変数は、変数のグローバル変数と呼ばれるプログラムで最初に定義。グローバル変数のスコープは、ローカル変数のスコープは、変数のサブルーチンが定義され、プログラム全体です。

任意のインデントのないグローバル変数は、任意の位置に呼び出すことができます。

 

サブルーチンます:defで定義された関数。

 

スコープ

スコープ識別子である識別子の可視範囲、。一般的には、多くの場合、変数のスコープと言いました

グローバルスコープ(グローバル):プログラムの実行環境全体に目に見えます

ローカルスコープ:目に見える内部機能、等;ローカル変数の範囲は、それは、ローカルスコープを超えることができません。

 

NAME = "ニコラス" 
change_NAME DEF():
    プリント( "change_NAME"、NAME)
change_NAME()
プリント(NAME)

 


出力

change_NAMEのニコラス
ニコラス

 


分析:NAME =「ニコラス」でグローバル変数であり、
in vivoでの機能を直接「change_NAMEのニコラス」をプリントアウトするために呼び出すことができるchange_NAME()

 

図2に示すように、グローバル変数とローカル変数と同じ名前:


グローバル変数は、他の場所で機能するには、ローカル変数の定義内のサブプログラムでは、ローカル変数は、役割を果たしています。

例:

 

NAME = "ニコラス" 
change_NAME DEF():
    NAME = "niubi" 
    プリント( "change_NAME"、NAME)
change_NAME()
プリント(NAME)

 

  

出力

change_NAME niubi 
ニコラス

 

分析:グローバル変数と同じ名前のローカル変数:デフchange_NAME():内部機能、
印刷実行(「change_NAME」、NAME)ステートメント、NAME関数呼び出し内部優先順位値は、関数の後に印刷を実行する実行される(NAME )の文、グローバル変数NAME =「ニコラス」の仕事。


3、もしグローバルキーワードのない内部関数


グローバル変数のこの時点で割り当てることができない何もグローバル変数が存在しない場合の優先順位は、ローカル変数を読んで、ローカル変数が読み込まれます。

しかし、可変オブジェクトを操作することができるため(例えば、追加()POP())内部要素の。

 

前提:なしグローバルキーワード

声明(同義語)ローカル変数と、

コードをコピー
名前= [ "ポニー"、 "ジャック"】
プリント(1名)
DEF change_name():
    名= "ニコラス" 
    プリント( "change_name"、名)
change_name()
プリント(2名)
コードをコピー


出力

1 [ 'ポニー'、 'ジャック'] 
change_nameのニコラス
2 [ 'ポニー'、 'ジャック']
1 [ 'ポニー'、 'ジャック'] 
change_nameのニコラス
2 [ 'ポニー'、 'ジャック']

 

  

分析:ここgolbalないキーワードは、ステートメントは、グローバル変数名を読み出す際にプリント(1名)を実行= [「ポニー」、「ジャック」]、 Change_Name()関数を実行した後、NEMA「ニコラス」が割り当てられている機能
関数名=「ニコラス」の内側に、ここで印刷(「change_name」、名)の文、名前のローカル変数の読み込み優先順位を実行し
、出力change_nameニコラス。change_name後()関数は終了します。
印刷(2、名)文を実行します。そこには、まだグローバル変数名= [「ポニー」、「読んでいるジャック」]。


B、無宣言(同義語)ローカル変数
として

コードをコピー
名前= [ "ポニー"、 "ジャック"】
プリント(1名)
DEF change_name():
    プリント(3名)
    name.append( "ニコラス") 印刷(4名)
change_name()
プリント(2、名前)
コードをコピー

 

  


出力

1 [ 'ポニー'、 'ジャック'] 
3 [ 'ポニー'、 'ジャック'] 
4 [ 'ポニー'、 'ジャック'、 'ニコラス'] 
2 [ 'ポニー'、 'ジャック'、「ニコラス]

 

  


分析:変数オブジェクトは、あなたが内部の要素を操作することができるかどうかグローバル変数のグローバルなキーワード。

 

グローバル「キーワードがある場合、変数は基本的にグローバル変数である4は、それが読書割り当てることができます。

 

声明(同義語)ローカル変数と、

コードをコピー
NAME = "ニコラス" 
プリント(1、NAME)
change_NAME DEF():
    グローバル名
    NAME = "niubi" 
    プリント( "change_NAME"、NAME)
change_NAME()
プリント(2、NAME)
コードをコピー

 

  

出力

ニコラス。1 
Change_Name niubi 
2 niubi

 

  

分析:印刷(「1」、NAME)の実装ではステートメント、NAMEは、グローバル変数を使用し、次に関数内change_NAME()関数を実行するには、全体文を実行した後、NAME =「niubi」を実行した後、グローバルキーワードステートメントを有しますプログラムの名前の変数値が「niubi」に変更されました。
出力change_NAME niubi、関数の終わりまで続きます。

最後に、印刷の実装(「2」、NAME)ステートメント、内部NAME機能を改変するので「niubi」ので、ここでは出力
2 niubi

 


例2

コードをコピー
名前= [ "ポニー"、 "ジャック"】
プリント(1名)
DEF change_name():
    グローバル名
    名= "ニック"] 
    name.append( "ニコラス")
    プリント(3名)
change_name()
プリント( 2、名称)
コードをコピー

 



出力

1 [ 'ポニー'、 'ジャック'] 
3 [ 'ニック'、 'ニコラス'] 
2 [ 'ニック'、 'ニコラス']

 

分析:
名前= [「ポニー」、「開始ジャック」] グローバル変数を変更するようにchange_name()関数は、関数のグローバルキーワードと関係行った後、次に行わ名変更の名前と同等である、グローバル変数であります。


C、地球上の位置に注意を払います

 

エラーの例

 

  

分析:あなたはグローバルグローバル変数を変更する必要がある場合はグローバル名の下に=「ニック」配置することはできません。

 

 

5、コード仕様:グローバル変数すべての大文字、小文字の変数名ローカル変数。


第二に、マルチレイヤ機能と、ネストされたスコープ


(1)関数を使用した後、最初に定義しなければならないことに注意してください
例1

デフTEST1():
    印刷( "TEST1")
デフTEST2():
    印刷( "TEST2")
TEST1()
テスト2()

 


分析:これは、関数を定義することにより、可能であるが、その関数を使用します

エラーの例

デフTEST1():
    印刷( "TEST1")
TEST2()
DEF TEST2():
    印刷( "TEST2")
TEST1()

 

  


分析:このTEST2()が実行されません。

(2)関数で定義された関数が外部に使用することができません


例2

()DEFアウター:
    DEF()内:
        プリント( '内側') 印刷( '外側') 
    )(内側
、外側()

 

  


分析:関数のスコープの概念であり、可視範囲、。内部外部関数を直接使用することはできません。

デフFOO():
    印刷( "foo"という)
    あまりにも()
DEFあまりにも():
    プリント( "あまりにも")
のfoo()

 

  


分析:ここでは、実行の順序がロードされているデフfooの():
ロードDEFあまりにも():その後、FOO()を実行し、その誤りがないだろう。

(3)解析実行ネストされた関数の結果

コードをコピー
NAME = 'ニコラス
DEFジャック():
    名= "ジャック" 
    プリント(名)
    デフポニー():
        名= "ポニー" 
        プリント(名)
        デフ・チャールズ():
            名='チャールズの
            印刷(名)
        印刷(名)
        チャールズ()
    ポニー()
    印刷(名)
ジャック()
コードをコピー

 


出力:

ジャック
ポニー
ポニー
チャールズ・
ジャック

 

分析:

次のように図行います

 

実行順序:1. 3 ---- 2 ---- ---- ---- 3.1 3.2 ---- 3.3 ---- 3.4 ---- ---- 3.3.1
3.3.2-- 3.3.4 --3.3.3 ---- ---- ---- 3.5 3.3.5--3.3.3.1--3.3.3.2

 

1ファーストネーム=「ニコラス」ステートメントを実行します

2ロードDEFジャック():メモリ機能コンパイルするが、実行しません

3コールジャック()関数で、開始

3.1 执行name = "jack"语句

3.2 执行print(name)语句,这里由于没有global关键字,优先读取局部变量name = "jack",所以这里输出jack

3.3 加载def pony():函数到内存进行编译,但不执行

3.4 调用pony():函数,开始执行

3.3.1 执行name = "pony"语句,这里是一个局部变量

3.3.2 执行print(name)语句,这里由于没有global、nonlocal关键字,优先读取局部变量name = "pony",所以这里输出pony

3.3.3 加载charles():函数到内存进行编译,但不执行

3.3.4 执行print(name)语句,这里由于没有global、nonlocal关键字,优先读取同一层级的局部变量name = "pony",所以这里输出pony

3.3.5 调用charles():函数,开始执行

3.3.3.1 执行name = 'charles'语句,这里是个局部变量

3.3.3.2 执行print(name)语句,优先读取局部变量name = "charles",所以这里输出charles

~~charles():函数结束

~~pony():函数


3.5 执行执行print(name)语句,优先使用同层级的局部变量name = "jack",所以这里输出jack。


~~整体结束

 

例子

 

コードをコピー
name = "nicholas"
def outer():
    name = "nick"
    def inner():
        print(name)
    print(name)
    inner()
outer()
コードをコピー

 

 

输出结果

 

nick
nick

 

  分析:注意这里的inner()函数内部的print(name)语句,这里仍然是优先使用outer()函数内部的局部变量name = "nick",而非全局变量。

 

(4)

nonlocal关键词
nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
例子
看这个程序,分析输出过程和结果。

 

コードをコピー
def scope_test():
    def do_local(): 
        spam = "local spam"  
    def do_nonlocal(): 
        nonlocal spam 
        spam = "nonlocal spam"   
    def do_global(): 
        global spam 
        spam = "global spam"       
    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()  
    print("After global assignment:", spam)       
scope_test()
print("In global scope:", spam)
コードをコピー

 

  

输出结果

After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam

 

  

分析:
程序执行步骤如图

 

 

从1开始
1--2--2.1--2.2--2.3--2.4--2.5--2.5.1--2.5.2--2.6--2.7--2.7.1--2.7.2--2.8

--2.9--2.9.1--2.9.2--2.10--2.11


下面具体分析下程序执行的过程

1 将def scope_test():函数体作为一个整体加载到内存中,但不执行

2 调用def scope_test():开始执行

2.1 将def do_local():函数体作为一个整体加载到内存中,但不执行

2.2 将def do_nonlocal(): 函数体作为一个整体加载到内存中,但不执行

2.3 将 def do_global(): 函数体作为一个整体加载到内存中,但不执行

2.4 执行 spam = "test spam"

2.5 调用 def do_local():函数

2.5.1 执行 def do_local():函数

2.5.2 执行 spam = "local spam"

--完成2.5.2之后 def do_local():函数结束,其所占的内存被回收, spam =

"local spam"数据被销毁

2.6 执行print("After local assignment:", spam)语句

由于没有global关键字,这里优先读取局部变量,即spam = "test spam"

打印出After local assignment: test spam

2.7 调用do_nonlocal()函数

2.7.1 执行def do_nonlocal():

遇到 nonlocal 声明,nonlocal关键字用来在函数外层(非全局)变量。

这里的外层即为def scope_test():这个作用域内

2.7.2 执行spam = "nonlocal spam"语句

这时def scope_test():这个作用域内由以前的spam = "test spam"被重新覆盖为

spam = "nonlocal spam"

--do_nonlocal()函数体结束

2.8 执行 print("After nonlocal assignment:", spam)语句

由于spam被重新赋值为"nonlocal spam",这里输出

After nonlocal assignment: nonlocal spam

2.9 调用do_global()函数

2.9.1 执行def do_global(): 函数

2.9.2 执行 spam = "global spam" 语句

遇到global声明,global关键字用来在函数整体作用域使用全局变量。类似于在

def scope_test():上面写了一句spam = "global spam"

--def do_global(): 函数体结束

2.10 执行print("After global assignment:", spam)语句

由于这一层级作用域没有global关键字,这里优先读取局部变量,即被修改过一次的

spam = "nonlocal spam"

这里输出After global assignment: nonlocal spam

2.11执行print("In global scope:", spam)语句

由于在2.9.2 spam被声明了全局变量,即spam = "global spam"

所以这里输出

In global scope: global spam

 

例子2

コードをコピー
name = "jack"
def foo():
    name = "nick"
    print(name)
    def too():
        nonlocal name
        name = "nicholas"
        print(1,name)
    too()
    print(name)
foo()
コードをコピー

 

  输出结果

nick
1 nicholas
nicholas

 

  分析:注意这里的def too():函数内print(1,name)语句仍然优先读取局部变量name = "nicholas"。


三、递归


1、递归的定义


如果在调用一个函数的过程中直接或间接调用自身本身,那么这种方法叫做递归。

 

2、递归的特点


a、递归必须有一个明确的结束条件(基例)。
b、每次进入更深一层递归时,问题规模相比上次递归都应有所减少。
c、递归效率不高,递归层次过多会导致栈溢出。


3、递归的执行过程

例子

def calc(n):
    print(n)
    if int(n/2) ==0:
        return n
    return calc(int(n/2))
calc(10)

 

  


输出结果

10
5
2
1

 


分析执行过程:

 

具体过程

(1)执行def calc(n):语句,将calc(n)函数加载到内存中进行编译,但不执行


(2)执行calc(10)语句,调用calc(n)函数,将n = 10 传入calc(n)函数


(3)执行print(n)语句,此时n = 10,打印10


判断n/2是否等于0,10/2 = 5不等于0


执行retun语句,return调用calc(n)函数,


此时具体是执行calc(int(10/2))即calc(5)


此层函数暂停,等待calc(5)返回值


(4)执行print(n)语句,此时n = 5,打印5


判断n/2是否等于0,5/2 = 2不等于0


执行retun语句,return调用calc(n)函数,


此时具体是执行calc(int(5/2))即calc(2)


此层函数暂停,等待calc(2)返回值


(5)执行print(n)语句,此时n = 2,打印2


判断n/2是否等于0,2/2 = 1不等于0


执行retun语句,return调用calc(n)函数,


此时具体是执行calc(int(2/2))即calc(1)


此层函数暂停,等待calc(1)返回值


(6)执行print(n)语句,此时n = 1,打印1


判断n/2是否等于0,1/2 = 2等于0,


执行if条件下的retun语句,return n 给上一层函数,


即return 1给上层函数


(7)将1传给calc(1),calc(1)得到值为1 ,


return calc(1)即return 1,再次将1传给上层的return calc(2),


calc(2)得到值为1,再次将1传给上层的return calc(5),


calc(5)得到值为1,最后将1传给calc(10),


即calc(10)= 1。

 

这里可以打印下calc(10)的值

コードをコピー
def calc(n):
    print(n)
    if int(n / 2) == 0:
        return n
    return calc(int(n / 2))
v = calc(10)
print("calc(10)是",v)
コードをコピー

 

  输出结果

10
5
2
1
calc(10)是 1

 

  

 

例子2

 

コードをコピー
import time
person_list=['Pony','Charles','Richard ','Jack']
print("How can I make good money?")
def ask(person_list):
    print('-'*60)
    if len(person_list) == 0:
        return "I don't know"
    person=person_list.pop(0)
    if person == "Jack":
        return "%s say:Better have a dream, in case it comes true someday." %person
    print('hi Boss[%s],How can I make good money?' %person)
    print("%s replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask %s..." %(person,person_list))
    time.sleep(10)
    res=ask(person_list)
    #print('%s say: %res' %(person,res))#注释语句
    return res
 
res = ask(person_list)
 
print(res)
コードをコピー

 

  


输出结果

コードをコピー
How can I make good money?
------------------------------------------------------------
hi Boss[Pony],How can I make good money?
Pony replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Charles', 'Richard ', 'Jack']...
------------------------------------------------------------
hi Boss[Charles],How can I make good money?
Charles replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Richard ', 'Jack']...
------------------------------------------------------------
hi Boss[Richard ],How can I make good money?
Richard  replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Jack']...
------------------------------------------------------------
Jack say:Better have a dream, in case it comes true someday.
コードをコピー

 

  

 

如果取消上面print('%s say: %res' %(person,res))注释,执行这一语句,可以看出return返回的过程
如下

コードをコピー
import time
person_list=['Pony','Charles','Richard ','Jack']
print("How can I make good money?")
def ask(person_list):
    print('-'*60)
    if len(person_list) == 0:
        return "I don't know"
    person=person_list.pop(0)
    if person == "Jack":
        return "%s say:Better have a dream, in case it comes true someday." %person
    print('hi Boss[%s],How can I make good money?' %person)
    print("%s replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask %s..." %(person,person_list))
    time.sleep(1)
    res=ask(person_list)#第一处
    print('%s say: %res' %(person,res))
    return res
 
res = ask(person_list)#第二处
 
print(res)
コードをコピー

 


输出结果

コードをコピー
How can I make good money?
------------------------------------------------------------
hi Boss[Pony],How can I make good money?
Pony replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Charles', 'Richard ', 'Jack']...
------------------------------------------------------------
hi Boss[Charles],How can I make good money?
Charles replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Richard ', 'Jack']...
------------------------------------------------------------
hi Boss[Richard ],How can I make good money?
Richard  replied:I don't know,But I konw you are a smart boy,hold on ,I can help you ask ['Jack']...
-------------------------------------------------- ---------- 
リチャードは言う。「ジャックは言う:良い夢を持って、それは本当来る場合には、someday.'es 
チャールズは言う。」ジャックは言う:良い夢を持って、ケースには、それは本当いつか来ます。 「ES 
ポニーは言う。」ジャックは言う:より良いsomeday.'esそれは本当来る場合には、夢を持っている
ジャックは言う:それは本当いつか来る場合にはより良い、夢を持っています。
コードをコピー

 

  

分析:最終的な結果が戻っリチャード・チャールズに返され、チャールズはポニーに戻って
より良い、夢を持っている:実行が終わっても、解像度のジャックが言ってもらう最初=尋ねる(person_list)でRESそれが真いつか来る場合。

そして、最後に印刷この文は、関数の外解像度に戻ります。

おすすめ

転載: www.cnblogs.com/QaStudy/p/11514928.html