1. 程式人生 > >python3基礎10

python3基礎10

day10

全域性變數和區域性變數

 區域性變數:
  定義在函式內部的變數稱為區域性變數(函式的形參也是區域性變數)
  區域性變數只能在函式中使用
  區域性變數在函式呼叫時才能被建立,在函式呼叫之後會自動銷燬
 
 全域性變數:
  定義在函式外部,模組內部的變數稱為全部變數
  全域性變數所有的函式都可以直接訪問(但函式內部不能將其賦值)
 
 示例見:
   global_local.py
 
 說明:
  1.區域性變數只能在其被宣告的函式內部訪問,而全域性變數可以在整個模組範圍內訪問
  2.在函式內部賦值語句不會對全域性變數造成影響
  3.在區域性範圍內可以訪問全域性變數,但是在全域性不能訪問區域性變數,因為在函式呼叫完畢後,區域性變數銷燬
  4.函式名也是全域性變數(fn)
 def fn(c, d):
    e = 300

 示意:
   L = []
   def input_number():
       L2 = []
       while True:
           n = int(input("請輸入正整數:"))
           if n < 0:
               break
            L2.append(n)
       L = L2
    input_number()
    print(L)


globals()/locals()函式
  globals()  返回當前全域性作用域內變數的字典
  locals()   返回當前區域性作用域內變數的字典
 
示例見:
   globals_locals.py

a = 1
b = 2
c = 3


def fn(c, d):
    e = 300
    print("locals()返回",locals())
    print("globals()返回",globals())
    print(c)    #列印區域性變數繫結的物件
    print(globals()['3'])   #列印全部變數繫結的物件

fn(100, 200)

函式變數:
  函式名是變數,它在建立函式時繫結一個函式
 
 示例見:
   function_variable.py

def fn():
    print("hello world!")   #fn繫結函式


f1 = fn    #f1也繫結這個函式
print(fn)   #<function fn at 0x7f138e4d6f28>
print(f1)   #<function f1 at 0x7f138e4d6f28>
print(f1())   #None


def f1():
    print("函式f1被呼叫")

def f2():
    print("函式f2被呼叫")

f1, f2 = f2, f1   #f1,f2交換繫結

f1()    #f2被呼叫
f2()    #f1被呼叫

 
  一個函式可以作為另一個函式的實參傳遞
 
 示例見:
   function_give_function.py

def f1():
    print("hello f1")

def f2():
    print("hello f2")

def fx(fn):
    print(fn) #<function f1 at 0x7fb921cebf28>
    fn()    #呼叫fn繫結的函式

fx(f1)  #請問如何執行?#fn是函式 fn()是呼叫函式fn
fx(f2)


#fx(f1)就是將f1繫結的語句塊交給fn繫結

 看懂下面的程式碼在做什麼:
   def myinput(fn):
       L = [1,3,5,7,9]
       return fn(L)
   print(myinput(max))   #9
   print(myinput(min))   #1
   print(myinput(sum))   #25

函式可以返回另一個函式:
 示例見:
  return_function.py

def get_function():
    s = input("請輸入您要做的操作:")
    if s == '求最大':
        return max
    elif s == '求最小':
        return min
    elif s == '求和':
        return sum

L = [2,4,6,8,10]
f = get_function()  #讓get_function返回給我們一個函式
print(f(L))


練習一:
 寫一個計算公式的解釋執行器
 已知有如下函式:
   def myadd(x, y):
       return x + y
   def mysub(x, y):
       return x -y
   def mymul(x, y):
       return x * y

   def get_fun(op):
   .....#自己實現
   get_fun(op)函式傳入字串'加'或'+'返回myadd
   get_fun(op)函式傳入字串'乘'或'*'返回mymul
   在主函式中程式如下:
     def main():
         while True:
             s = input("請輸入計算公式:")  #10加20
             L.s.split()   #L = ['10','加','20']
             a = int(L[0])
             b = int(L[2])
             fn = get_fun(L[1])
             print("結果是:",fn(a,b))   #結果是:30
#方法一:
def myadd(x, y):
    return x + y
def mysub(x, y):
    return x - y
def mymul(x, y):
    return x * y

def get_fun(op):
    if op == '加' or op == '+':
        return myadd
    if op in ('減', '-'):
        return mysub
    if op in ('乘', '*'):
        return mymul

def main():
    while True:
        s = input("請輸入計算公式:")  #10 加 20
        L = s.split()   #L = ['10','加','20']
        a = int(L[0])
        b = int(L[2])
        fn = get_fun(L[1])
        print("結果是:",fn(a,b))   #結果是:30
main()


#方法二:

def get_fun(op):
    if op == '加' or op == '+':
        def myadd(x, y):
            return x + y
    if op in ('減', '-'):
        def mysub(x, y):
            return x - y
    if op in ('乘', '*'):
        def mymul(x, y):
            return x * y

def main():
    while True:
        s = input("請輸入計算公式:")  #10 加 20
        L = s.split()   #L = ['10','加','20']
        a = int(L[0])
        b = int(L[2])
        fn = get_fun(L[1])
        print("結果是:",fn(a,b))   #結果是:30
main()

函式的巢狀定義:
  函式巢狀定義是指一個函式裡用def語句來建立另一個函式的情況

 示例:

  def fn_outter():
      print("fn_outter()被呼叫")
      def fn_inner():
          print("fn_inner被呼叫")
      fn_inner()  #呼叫巢狀函式fn_inner
      fn_inner()  #第二次呼叫
      print('fn_outter呼叫結束')
  fn_outter()   #呼叫外層函式


python3 的四個作用域
 作用域也叫名字空間,是訪問變數時查詢變數名的範圍空間

python3 的四個作用域 LEGB
 作用域                 英文解釋                  英文簡寫
 區域性作用域(函式內)     local(function)              L
 外部巢狀函式作用域     Enclosing function locals    E
 函式定義所在模組作用域  Global(module)               G
 python內建模組的作用域  Builtin(Python)             B

 注:
 內建函式: max min sum 等都在python內建模組的作用域,不能改變,只能讀取

示例見:
  namespace.py

v = 100  #函式定義所在模組作用域


def fun1():
    v = 200        # 外部巢狀函式作用域 
    print("fun1.v=",v)
    def fun2():
        v = 300  #區域性作用域(函式內)
        print('fun2.v=',v)
    fun2()


fun1()
print("全域性變數v=",v)


變數名查詢規則:
  在訪問變數時,先查詢本地(區域性)變數,然後是包裹此函式外部的函式內的變數,之後是全域性變數,最後是內建作用域內的變數
  即: L----->    E------>  G----->B
  在預設情況下,變數名賦值(賦值語句)會在當前作用域內建立變數和修改變數
 
 v = 0
 def fn(x):
     v += x   #錯誤,把v看做區域性變數,在區域性內未繫結

global語句
 作用:
   告訴解釋執行器,global語句宣告一個或多個變數,這些變數的作用域為模組級作用域,也稱全域性作用域
   全域性宣告global將賦值變數對映到模組檔案內部的作用域
 語法:
   global 變數名1, 變數名2...
 示例見:
   global.py

v = 100


def fn():
    global v    # 告訴解釋執行器python3,v是全部變數,不是區域性變數
    v = 200


fn()
print('v=',v)
 說明:
   1.全域性變數如果要在函式內部被賦值,則必須經過全域性宣告(否則
     會被認為是區域性變數)
   2.全域性變數在函式內部不經過宣告就可以直接訪問
   示例: global2.py

v = 100


def fn():
    v = 200     # 不建議在globalz之前宣告區域性變數
    print(v)

    global v   #v不能既是全域性又是區域性變數
    v = 300
    print(v)


fn()
print('v=',v)

   3.不能先宣告區域性變數,再用global宣告全域性變數,此做法不和規則
   4.global變數列表裡的變數名不能出現在函式的形參列表裡
   示例: global3.py

v = 100 


def fx(v):
    global v  #此處錯誤,fx(v)形參中的v與全域性變數中的v衝突
    v = 300


fx(v)
print(v)

nonlocal語句
 作用:
  告訴解釋執行器,nonlocal宣告的變數不是區域性變數,也不是全域性變數,而是外部巢狀函式內的變數
 語法:
   nonlocal 變數名1,變數名2,...

 示例見:
   nonlocal.py

v = 100


def f1():
    v = 200
    print("f1.v=",v)


    def f2():
        nonlocal v
        v = 300
        print("f2.v=",v)
    f2()
    print("呼叫f2()後的f1.v=",v)


f1()
print("全域性的v=",v)


#結果為:
# f1.v= 200
# f2.v= 300
# 呼叫f2()後的f1.v= 300
# 全域性的v= 100

 說明:
  1.nonlocal 語句只能被巢狀函式的內部進行使用
  def fx():
      nonlocal v
      v = 100
    #沒有巢狀不能使用
  2.訪問nonlocal變數進行賦值操作,將對外部巢狀函式作用域內的
    變數進行操作
  
  3.當有兩層或兩層以上函式巢狀時,訪問nonlocal變數只是
    對近一層變數進行操作

  示例見nonlocal2.py

def f1():
    v = 200
    def f2():
        v = 300
        
        def f3():
            nonlocal v    #修改f2中的區域性變數v
            v = 400
        f3()
        print("f2.v",v)
    f2()
    print("f1.v",v)
f1()

#結果是
# f2.v 400
# f1.v 200

  4.nonlocal語句的變數列表裡的變數名,不能出現在此函式形參列表中


 
def 語句
  語法:
   def 變數名/函式名(形參):
      語句塊


lambda 表示式
  作用:
   建立一個匿名函式物件
   同def 類似,但不提供函式名
  語法:
   lambda [形參名1,形參名2,....]:表示式

  示例見:
   lambda.py

# def myadd(x, y):
#     return x + y
# 等同於
myadd = lambda x, y: x + y #建立函式

print('20 + 30 =',myadd(20, 30))
print('40 + 50 =',myadd(40, 50))

fx = lambda:print("hello world!")
fx()
# hello wprld!

  語法說明:
   1.lambda只是一個表示式,它用來建立一個函式
   2.當lambda表示式呼叫時,先執行(:)                             後的表示式,並返回表示式的結果的引用
   3.lambda表示式建立的函式只能包含一條表示式
   4.lambda比函式簡單且可以隨時建立和銷燬,有利於減少程式的偶合度
   (形參越少對外界依賴程度越小,偶合度越低的程式越好)

練習二:
 1.寫一個lambda表示式,建立一個函式,此函式判斷引數n 的平方
   加1能否被5整除,如果能整除返回True,否則返回False
    fx = lambda n:...
    print(fx(3))  #True
    print(fx(4))  #False

fx  = lambda n: True if (n ** 2 + 1) % 5 == 0  else False
# fx = lambda n:(n ** 2 + 1) % 5 == 0

print(fx(3))
print(fx(4))

 2.寫一個lambda表示式,返回兩個形參的最大值
   def mymax(x, y):
   ...
   mymax = lambda...
   print(mymax(100,200))   #200


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

mymax = lambda x, y:max(x, y)
#mymax = lambda x, y:x if x > y else y
print(mymax(100,200))  


看懂下面的程式在做什麼?
def fx(f, x, y):
    print(f(x, y))

fx((lambda a, b:a + b),100,200)  
fx((lambda x, y:x ** y),3,4)

#lambda附給f

eval,exec函式
eval()函式
  作用:
   把一個字元當成一個表示式來執行,返回表示式執行後的結果

  注:eval只能給表示式不能給語句
  格式:
   eval(source, globals=None, locals=None)

  示例見:
    eval.py

x = 100
y = 200
s = "x + y"

a = eval(s)   #解釋執行s字串,把表示式的值返回回來
print(a)    #300

b = eval(s,None,{'x':1,'y':2})
print(b)    #3

c = eval(s,{'x':10,'y':20},{'x':1})
print(c)    #21

exec()函式
  作用:
    把一個字串當成一個程式來執行
  格式:
    exec(source, globals=None, locals=None)
  示例:
s = "x=100\ny=200\nprint('x+y=',x+y)\ndel x, y"   
exec(s)

課後練習:
1.給出一個數n,寫一個函式myfac(n)來計算n!(n的階乘)
 n! = 1*2*3*4*5*....*n

 print(myfac(5))   #120

2.給出一個數n,寫一個函式計算:
  1 +2**2+3**3+4**4+....+n**n的和

3.寫程式列印楊輝三角(只打印六層)
      
      1
     1 1
    1 2 1
   1 3 3 1
  1 4 6 4 1
1 5 10 10 5 1