1. 程式人生 > 其它 >名稱空間與作用域及函式補充

名稱空間與作用域及函式補充

名稱空間

名稱空間是存放變數名與變數值繫結關係的地方

名稱空間的分類

1.內建名稱空間
python直譯器提前定義好的,我們可以直接使用
eg:

print()
input()
type()
file.read()
file.write()

2.全域性名稱空間
在py檔案中編寫的程式碼執行產生的名字都會存到全域性名稱空間

password = '123456'  # 變數名password存入全域性名稱空間
def func():  # 函式名func存入全域性名稱空間
    pass
if True:
    username = input('please enter your username>>>:')  # 變數名username存入全域性名稱空間
for line in file:  # 變數名line存入全域性名稱空間
    pass
while True:
username = input('please enter your username>>>:')  # 變數名username存入全域性名稱空間
password = input('please enter your password>>>:')  # 變數名password存入全域性名稱空間

3.區域性名稱空間
函式體程式碼執行產生的都是區域性名稱空間

def register():
    username = input('please enter your username>>>:')  # 變數名username存入區域性名稱空間
    password = input('please enter your password>>>:')  # 變數名password存入區域性名稱空間

存活週期

  1. 內建名稱空間
    python直譯器執行,內建名稱空間產生
    python直譯器關閉,內建名稱空間消失
  2. 全域性名稱空間
    py檔案開始執行,全域性名稱空間產生
    py檔案執行結束,全域性名稱空間消失
  3. 全域性名稱空間
    函式體程式碼開始執行,全域性名稱空間產生
    函式體程式碼執行結束,全域性名稱空間消失

名字的查詢順序

在查詢變數名或函式名等名字的時候,一定要先確定該名字在哪個名稱空間
1.如果在區域性名稱空間
查詢順序:區域性名稱空間 >>> 全域性名稱空間 >>> 內建名稱空間
2.如果在全域性名稱空間
查詢順序:全域性名稱空間 >>> 內建名稱空間

input = '我是全域性名稱空間中的input'
def index():
    input = '我是區域性名稱空間中的input'
    print(input)
index()  # 呼叫函式,函式體就會執行,產生區域性名稱空間
print(input)


x = 8
'''通過註釋讓函式體程式碼不執行來發現區域性名稱空間的查詢規律'''
def f1():
    x = 88
    def f2():
        # x = 888
        def f3():
            # x = 8888
            def f4():
                # x = 88888
                print(x)  # 依次註釋法f4,f3,f2,f1讓函式體程式碼,找到規律
            f4()
        f3()
    f2()
f1()
x = 8
'''通過註釋讓函式體程式碼不執行來發現區域性名稱空間的查詢規律'''
def f1():
    x = 88
    def f2():
        x = 888
        def f3():
            x = 8888
            def f4():
                print(x)  # 特例,檢測語法的時候發現f4的區域性名稱空間有變數名x,查詢的時候就只找f4的區域性名稱空間。
                x = 88888  # 如果修改變數名x,就可以正常執行
            f4()
        f3()
    f2()
f1()

作用域

作用域就是名稱空間能夠作用的範圍

  1. 內建名稱空間
    程式任意階段任意位置均可使用(全域性有效)
  2. 全域性名稱空間
    程式任意階段任意位置均可使用(全域性有效)
  3. 區域性名稱空間
    一般情況下,只在所屬的區域性名稱空間中有效(區域性有效);
    補充:也可以通過global與nonlocal關鍵字打破規則

global與nonlocal關鍵字

gloabl關鍵字可用於區域性修改全域性不可變型別,修改全域性可變型別不需要gloabl關鍵字

# 可變型別
name = 'trump'
def modify_name():
    # name = 'obama'  # 並不能修改全域性的name(值為字串,不可變型別),而是在modify_name區域性名稱空間中建立了一個新的name
    # 如果想要在區域性名稱空間中修改全域性名稱空間中的名字 那麼需要使用關鍵字申明
    global name  # 修改的是全域性name而不是在modify_name區域性名稱空間中建立新的name
    name = 'obama'
modify_name()
print(name)
# 不可變型別
dict1 = {'name': 'trump', 'age': '74', 'position': 'president'}
def delete():
    dict1.pop('position')  # 不需要global關鍵字
delete()
print(dict1)
# 區域性名稱空間巢狀的情況下
def func():
    name = 'trump'
    dict1 = {'name': 'trump', 'age': '74', 'position': 'president'}
    def modify():
        nonlocal name
        name = 'obama'  # 不可變型別需要使用關鍵字nonlocal
        dict1['position'] = 'ex-president'  # 可變型別不需要使用關鍵字nonlocal
    modify()
    print(name)
    print(dict1)
func()

函式名的多種用法

用法1:函式名可以當做變數名賦值

def index():
    print('from function index')


print(index)  # <function index at 0x000001548A541EA0>
res = index  # index賦值給res
print(res)  # function index at 0x000001548A541EA0>
res()  # from function index

用法2:函式名還可以充當函式的實參

def delete():
    print(delete)  # <function delete at 0x000001D5E0141EA0>
    print('from delete‘s function')  # from delete‘s function


def func(a):
    print('from func')  # from func
    print(a)  # <function delete at 0x000001D5E0141EA0>記憶體地址一致
    a()


func(delete)

用法3:函式名還可以當做函式的返回值

def func():
    print('from func')  # from func
    print(index)  # <function index at 0x0000019830D5DC80>
    return index  # 將函式名當做返回值


def index():
    print('from index')  # from index


res = func()  # res接收函式名
print(res)  # <function index at 0x0000019830D5DC80>
res()  # index()

用法4:函式名可以作為容器型別的元素

# 容器型別(列表、元組、字典)的內部可以存檔多個元素的資料型別
def index():
    print('from index')


dict1 = {'func1': 'delete', 'func2': index}
print(dict1)  # {'func1': 'delete', 'func2': <function index at 0x00000254ABEE1EA0>}
dict1['func2']()  # from index

函式的巢狀

def modify():
    func()
    print("from modify function")
    return
def func():
    modify()
    print("from func function")
    return
modify()  # 報錯 maximum recursion depth exceeded
def two_max(a, b):
    '''返回兩個數中的較大值'''
    if a > b:
        return a
    return b


print(two_max(100, 666))
def many_max(a, b, c, d):
    '''返回四個數中的最大值'''
    res1 = two_max(a, b)
    res2 = two_max(res1, c)
    res3 = two_max(res2, d)
    return res3


print(many_max(66, 333, 888, 777))

用函式編寫員工管理系統

staff_info_dict = {}
# 三個小功能
def func1():
    '''輸入員工資訊介面'''
    staff_name = input('請輸入您的姓名>>>:').strip()
    staff_age = input('請輸入您的年齡>>>:').strip()
    staff_salary = input('請輸入您的薪資>>>:').strip()
    return staff_name, staff_age, staff_salary
def num_func(a):
    '''輸入工號'''
    staff_num = input(f'請輸入您的工號用於{a},例如1001,1002>>>:').strip()
    return staff_num
def print_func(staff_num):
    print('''
    員工工號:%s
    員工姓名:%s
    員工年齡:%s
    員工工資:%s                
        ''' % (staff_num.zfill(8), staff_info_dict[staff_num]['name'], staff_info_dict[staff_num]['age'], staff_info_dict[staff_num]['salary']))
# 七個主體功能
def register():
    '''新增員工資訊'''
    tag2 = True
    while tag2:
        staff_num = num_func('新增員工資訊')  # 呼叫工號輸入函式
        if staff_num.isdigit():
            if staff_num in staff_info_dict:
                print('工號已存在,不能重複,請重新輸入')
            else:
                print('溫馨提示,請記住您輸入的工號,工號檢視和修改工資的憑證;如有忘記,主介面輸入4檢視所有員工資訊')
                staff_name, staff_age, staff_salary = func1()  # 呼叫員工資訊輸入輸入函式
                staff_data = {}
                staff_data['name'] = staff_name
                staff_data['age'] = f'{staff_age}歲'
                staff_data['salary'] = f'{staff_salary}元'
                staff_info_dict[staff_num] = staff_data
                print(f'工號為{staff_num.zfill(8)}的員工資訊新增成功,新增的資訊如下')
                print_func(staff_num)  # 呼叫列印員工資訊函式
                tag2 = False
        else:
            print('溫馨提醒,工號只能為純數字,例如1001,1002,2222')
def search():
    '''檢視單個員工資訊'''
    print('檢視單個員工資訊'.center(30, '-'))
    tag3 = True
    while tag3:
        staff_num = num_func('檢視資訊')  # 呼叫工號輸入函式
        if staff_num in staff_info_dict:
            print_func(staff_num)  # 呼叫列印員工資訊函式
            cmd = input('是否繼續檢視其他員工資訊,輸入y繼續,其他退出>>>:')
            if cmd == 'y':
                pass
            else:
                tag3 = False
        else:
            print('工號不存在,您可以仔細想一想,有無限的嘗試次數')
def modify_salary():
    '''修改單個員工工資'''
    print('修改單個員工工資'.center(30, '-'))
    count = 0
    while count < 3:
        staff_num = num_func('修改工資')  # 呼叫工號輸入函式
        if staff_num.isdigit():
            count += 1
            if staff_num in staff_info_dict:
                print_func(staff_num)  # 呼叫列印員工資訊函式
                staff_info_dict[staff_num]['salary'] = input('請輸入修改後的工資>>>:').strip() + '元'
                temp_salary = staff_info_dict[staff_num]['salary']
                print(f'工號為{staff_num.zfill(8)}的員工工資已經修改為{temp_salary},修改資訊如下')
                print_func(staff_num)  # 呼叫列印員工資訊函式
                break
            else:
                print('工號不存在,請重新輸入')
        else:
            print('溫馨提醒,工號只能為純數字,例如1001,1002,2222')
    else:
        print('三次機會使用完畢')
def search_all():
    '''檢視所有員工資訊'''
    print('檢視所有員工資訊'.center(30, '-'))
    for staff_num in staff_info_dict:
        print_func(staff_num)  # 呼叫列印員工資訊函式
def delete_staff():
    '''刪除單個員工資訊'''
    print('刪除單個員工資訊'.center(30, '-'))
    tag4 = True
    while tag4:
        count2 = 0
        while count2 < 3:
            staff_num = num_func('刪除資訊')  # 呼叫工號輸入函式
            count2 += 1
            if staff_num.isdigit():
                if staff_num in staff_info_dict:
                    print(f'您正在刪除工號為{staff_num.zfill(8)}的資訊為')
                    print_func(staff_num)  # 呼叫列印員工資訊函式
                    cmd = input("刪除後不可撤回,輸入'yes'確定刪除,如果要刪除其他的員工資訊,輸入其他返回主介面>>>:")
                    if cmd == 'yes':
                        staff_info_dict.pop(staff_num)
                        print(f'工號為{staff_num.zfill(8)}的員工資訊刪除成功')
                        count2 = 3
                        tag4 = False
                    else:
                        print(f'取消刪除工號為{staff_num.zfill(8)}的員工資訊成功')
                        count2 = 3
                else:
                    print('工號不存在,您還有兩次機會')
            else:
                print('溫馨提醒,工號只能為純數字,例如1001,1002,2222')
        else:
            print('退回主介面')
            tag4 = False
def modify_staff():
    '''修改單個員工資訊'''
    print('修改單個員工資訊'.center(30, '-'))
    count = 1
    while count < 4:
        staff_num = num_func('修改員工資訊')  # 呼叫工號輸入函式
        count += 1
        if staff_num.isdigit():
            if staff_num not in staff_info_dict:
                print('工號不存在,不能重複,請重新輸入')
            else:
                print('溫馨提示,請記住您輸入的工號修改員工資訊')
                staff_name, staff_age, staff_salary = func1()  # 呼叫員工資訊輸入輸入函式
                staff_data = {}
                staff_data['name'] = staff_name
                staff_data['age'] = f'{staff_age}歲'
                staff_data['salary'] = f'{staff_salary}元'
                staff_info_dict[staff_num] = staff_data
                print(f'工號為{staff_num}的員工資訊修改成功,修改後的資訊如下')
                print_func(staff_num)  # 呼叫列印員工資訊函式
                count = 4
        else:
            print('溫馨提醒,工號只能為純數字,例如1001,1002,2222;您可以仔細想一想,有三次的嘗試次數')
def exit_func():
    '''退出員工系統'''
    global tag  # 修改全域性tag的布林值
    tag = False
    print('歡迎下次使用')
func_dict = {1:register, 2:search, 3:modify_salary, 4:search_all, 5:delete_staff, 6:modify_staff, 7:exit_func}
tag = True
while tag:
    print('''
        ---------------------歡迎使用員工管理系統-------------------------
        ----------------1.新增員工資訊-----------------------------------
        ----------------2.檢視特定員工-----------------------------------
        ----------------3.修改員工薪資-----------------------------------
        ----------------4.查詢所有員工-----------------------------------
        ----------------5.刪除特定員工-----------------------------------
        ----------------6.修改員工資訊-----------------------------------
        ----------------7.退出員工系統----------------------------------- 
        ''')
    chioce = input('現在位置為主介面,請輸入功能編號').strip()
    if chioce.isdigit():
        chioce = int(chioce)
        if chioce in func_dict:
            func_dict[chioce]()
        else:
            print('請好好輸入功能編號,只有1-7')
    else:
        print('請好好輸入純數字,不要亂填')