まず、ローカル変数とグローバル変数
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それが真いつか来る場合。
そして、最後に印刷この文は、関数の外解像度に戻ります。