1. 程式人生 > >Python 使用全域性變數

Python 使用全域性變數

今天在寫以下Python程式碼時出現了問題。該段程式碼根據一些URL下載視訊:

#coding=utf-8

def save_case_infos(case_urls):
    for case_url in case_urls:

        # some download code ...

        # 列印已下載的視訊個數
        # 希望訪問全域性變數 case_total_num 
        case_total_num += 1
        print("current count: " + str(case_total_num))


# 全域性變數,表示已下載的視訊個數
case_total_num = 0 # 下載視訊檔案 urls = [r'http://cynhard.com/live/001', r'http://cynhard.com/live/002', r'http://cynhard.com/live/003'] save_case_infos(urls)

但是在執行時報以下錯誤:

Traceback (most recent call last):
  File "G:\projects\python\globaltest.py", line 21, in <module>
    save_case_infos(urls)
  File "G:\projects\python\globaltest.py"
, line 10, in save_case_infos case_total_num += 1 UnboundLocalError: local variable 'case_total_num' referenced before assignment

意思是說case_total_num為區域性變數,在使用它之前沒有被賦值。Python並沒有按照我的意圖將case_total_num當成全部變數。看來在函式內無法直接使用全域性變數。

有什麼辦法能在函式內使用全域性變數呢?根據官方文件,可以用global語句:

The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global

.

意思是說global語句可以宣告一個或多個變數為全域性變數。該宣告僅在當前程式碼塊中有效。除此之外,沒辦法訪問全域性變數。

於是,在上面的程式碼中加入global宣告語句就可以達到目的了:

#coding=utf-8

def save_case_infos(case_urls):
    global case_total_num  # global宣告
    for case_url in case_urls:

        # some download code ...

        # 列印已下載的視訊個數
        # 希望訪問全域性變數 case_total_num 
        case_total_num += 1
        print("current count: " + str(case_total_num))


# 全域性變數,表示已下載的視訊個數
case_total_num = 0

# 下載視訊檔案
urls = [r'http://cynhard.com/live/001',
        r'http://cynhard.com/live/002',
        r'http://cynhard.com/live/003']
save_case_infos(urls)

用global宣告多個變數需要用逗號分隔:

#coding=utf-8

def save_case_infos(case_urls):
    global succeeded_total_num, failed_total_num  # 多個變數用逗號分隔
    for case_url in case_urls:

        ok = False

        # some download code ...

        if ok:
            succeeded_total_num += 1
        else:
            failed_total_num += 1
        print("succeeded: " + str(succeeded_total_num) + 
            " failed: " + str(failed_total_num))


# 全域性變數,下載成功和失敗的視訊個數
succeeded_total_num = 0
failed_total_num = 0

# 下載視訊檔案
urls = [r'http://cynhard.com/live/001',
        r'http://cynhard.com/live/002',
        r'http://cynhard.com/live/003']
save_case_infos(urls)

在使用全域性變數的場合,也可用類變數代替:

#coding=utf-8

def save_case_infos(case_urls):
    for case_url in case_urls:

        ok = False

        # some download code ...

        if ok:
            G.succeeded_total_num += 1
        else:
            G.failed_total_num += 1
        print("succeeded: " + str(G.succeeded_total_num) + 
            " failed: " + str(G.failed_total_num))


# 將全域性使用的變數定義在類中        
class G:
    succeeded_total_num = 0
    failed_total_num = 0

# 下載視訊檔案
urls = [r'http://cynhard.com/live/001',
        r'http://cynhard.com/live/002',
        r'http://cynhard.com/live/003']
save_case_infos(urls)

這樣便去掉了global宣告,但是每一次用到類變數的時候都需要冠以類名。