Sử dụng các biến toàn cục trong một hàm


3114

Làm cách nào tôi có thể tạo hoặc sử dụng biến toàn cục trong hàm?

Nếu tôi tạo một biến toàn cục trong một hàm, làm thế nào tôi có thể sử dụng biến toàn cục đó trong một hàm khác? Tôi có cần lưu trữ biến toàn cục trong một biến cục bộ của hàm cần truy cập không?

Câu trả lời:


4246

Bạn có thể sử dụng một biến toàn cục trong các hàm khác bằng cách khai báo nó như globaltrong mỗi hàm gán cho nó:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

Tôi tưởng tượng lý do của nó là vì các biến toàn cầu rất nguy hiểm, Python muốn đảm bảo rằng bạn thực sự biết đó là những gì bạn đang chơi bằng cách yêu cầu globaltừ khóa rõ ràng .

Xem các câu trả lời khác nếu bạn muốn chia sẻ một biến toàn cục trên các mô-đun.


838
Thật quá đáng khi nói đến toàn cầu là "rất nguy hiểm". Quả cầu là hoàn toàn tốt đẹp trong mọi ngôn ngữ đã từng tồn tại và sẽ tồn tại. Họ có vị trí của họ. Những gì bạn nên nói là chúng có thể gây ra vấn đề nếu bạn không biết cách lập trình.
Anthony

207
Tôi nghĩ rằng chúng khá nguy hiểm. Tuy nhiên, trong các biến "toàn cầu" của python thực sự là cấp độ mô-đun, giải quyết được rất nhiều vấn đề.
Fábio Santos

246
Tôi không đồng ý rằng lý do Python yêu cầu globaltừ khóa là vì toàn cầu rất nguy hiểm. Thay vào đó, đó là vì ngôn ngữ không yêu cầu bạn khai báo rõ ràng các biến và tự động giả định rằng một biến mà bạn gán có phạm vi chức năng trừ khi bạn nói khác. Các globaltừ khóa là phương tiện được cung cấp để cho nó khác đi.
Nate CK

7
@avgvstvs: Và nếu bạn đang thực hiện cùng một chương trình mà không có toàn cầu, bạn vẫn có cùng số đường dẫn mã. Đối số bạn đã đưa ra không phải là một đối lập với toàn cầu.
Các cuộc đua nhẹ nhàng trong quỹ đạo

13
@LightnessRacesinOrbit Tôi không nhận được điểm của bạn. Nếu bạn loại bỏ một biến toàn cục, bạn loại bỏ yếu tố phức tạp trong đó, các hàm tùy ý không còn có thể thay đổi trạng thái chương trình , tại các điểm khác nhau trong thực thi - do đó thay đổi thực thi theo cách mà các hàm khác không thể chấp nhận được dựa vào biến đó. Bạn không còn phải theo dõi, "Đã f2()thay đổi trạng thái để bây giờ f3()có thể làm điều gì đó bất ngờ? Các chức năng hiện có thể vận hành bất khả tri đối với trạng thái chương trình bên ngoài.
avgvstvs

775

Nếu tôi hiểu chính xác tình huống của bạn, những gì bạn đang thấy là kết quả của cách Python xử lý các không gian tên cục bộ (chức năng) và toàn cầu (mô-đun).

Giả sử bạn đã có một mô-đun như thế này:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Bạn có thể mong đợi điều này sẽ in 42, nhưng thay vào đó nó sẽ in 5. Như đã được đề cập, nếu bạn thêm một globalkhai báo '' func1(), thì nó func2()sẽ in 42.

def func1():
    global myGlobal
    myGlobal = 42

Điều đang xảy ra ở đây là Python giả định rằng bất kỳ tên nào được gán cho , bất cứ nơi nào trong một hàm, là cục bộ của hàm đó trừ khi được nói rõ ràng khác đi. Nếu nó chỉ đọc từ một tên và tên đó không tồn tại cục bộ, nó sẽ cố gắng tra cứu tên trong bất kỳ phạm vi có chứa nào (ví dụ: phạm vi toàn cầu của mô-đun).

myGlobalDo đó, khi bạn gán 42 cho tên , Python sẽ tạo một biến cục bộ làm mờ biến toàn cục của cùng tên. Địa phương đó đi ra khỏi phạm vi và được thu gom rác khi func1()trở về; trong khi đó, func2()không bao giờ có thể nhìn thấy bất cứ điều gì khác ngoài tên toàn cầu (chưa sửa đổi). Lưu ý rằng quyết định không gian tên này xảy ra vào thời gian biên dịch, không phải trong thời gian chạy - nếu bạn đã đọc giá trị myGlobalbên trong func1()trước khi gán cho nó, bạn sẽ nhận được UnboundLocalError, bởi vì Python đã quyết định rằng đó phải là một biến cục bộ nhưng nó chưa có bất kỳ giá trị liên quan đến nó. Nhưng bằng cách sử dụng globalcâu lệnh '', bạn nói với Python rằng nó sẽ tìm tên khác thay vì gán cho nó cục bộ.

(Tôi tin rằng hành vi này bắt nguồn chủ yếu thông qua tối ưu hóa các không gian tên cục bộ - nếu không có hành vi này, VM của Python sẽ cần thực hiện ít nhất ba lần tra cứu tên mỗi khi một tên mới được gán cho bên trong một hàm (để đảm bảo rằng tên đó đã không t đã tồn tại ở cấp độ mô-đun / dựng sẵn), điều này sẽ làm chậm đáng kể một hoạt động rất phổ biến.)


Bạn đã đề cập rằng quyết định không gian tên xảy ra vào thời gian biên dịch , tôi không nghĩ đó là sự thật. từ những gì tôi học được trình biên dịch của python chỉ kiểm tra lỗi cú pháp, không phải lỗi tên, hãy thử ví dụ này def A (): x + = 1 , nếu bạn không chạy nó, nó sẽ không cung cấp cho UnboundLocalError , vui lòng xác minh cảm ơn bạn
watashiSHUN

1
Người ta thường sử dụng chữ in hoa cho các biến toàn cầu nhưMyGlobal = 5
Vassilis

3
@watashiSHUN: Quyết định không gian tên nào xảy ra tại thời gian biên dịch. Quyết định đó xlà cục bộ khác với kiểm tra trong thời gian chạy nếu tên cục bộ bị ràng buộc với một giá trị trước khi nó được sử dụng lần đầu tiên.
BlackJack

9
@Vassilis: Người ta thường chữ hoa tất cả các chữ cái: MY_GLOBAL = 5. Xem Hướng dẫn về Phong cách cho Mã Python .
BlackJack

223

Bạn có thể muốn khám phá khái niệm về không gian tên . Trong Python, mô-đun là nơi tự nhiên cho dữ liệu toàn cầu :

Mỗi mô-đun có bảng ký hiệu riêng, được sử dụng làm bảng ký hiệu toàn cục bởi tất cả các chức năng được xác định trong mô-đun. Do đó, tác giả của một mô-đun có thể sử dụng các biến toàn cục trong mô-đun mà không phải lo lắng về các xung đột ngẫu nhiên với các biến toàn cục của người dùng. Mặt khác, nếu bạn biết những gì bạn đang làm, bạn có thể chạm vào các biến toàn cục của mô-đun với cùng một ký hiệu được sử dụng để tham chiếu đến các chức năng của nó , modname.itemname.

Một cách sử dụng cụ thể của mô-đun toàn cầu được mô tả ở đây - Làm cách nào để chia sẻ các biến toàn cục trên các mô-đun? và để hoàn thiện nội dung được chia sẻ ở đây:

Cách chính tắc để chia sẻ thông tin giữa các mô-đun trong một chương trình là tạo một mô-đun cấu hình đặc biệt (thường được gọi là config hoặc cfg ). Chỉ cần nhập mô-đun cấu hình trong tất cả các mô-đun ứng dụng của bạn; mô-đun sau đó trở nên có sẵn như là một tên toàn cầu. Vì chỉ có một phiên bản của mỗi mô-đun, mọi thay đổi được thực hiện cho đối tượng mô-đun sẽ được phản ánh ở mọi nơi. Ví dụ:

Tập tin: config.py

x = 0   # Default value of the 'x' configuration setting

Tập tin: mod.py

import config
config.x = 1

Tập tin: main.py

import config
import mod
print config.x

1
vì một lý do tôi không thích config.x tôi có thể thoát khỏi nó không? Tôi đến với x = lambda: config.xvà sau đó tôi có giá trị mới trong x(). vì một số lý do, đã a = config.xkhông làm điều đó cho tôi.
vladosaurus

3
@vladosaurus có from config import xgiải quyết được điều đó?
jhylands

93

Python sử dụng một heuristic đơn giản để quyết định phạm vi nào sẽ tải một biến từ, giữa cục bộ và toàn cầu. Nếu một tên biến xuất hiện ở phía bên trái của một bài tập, nhưng không được khai báo toàn cục, thì nó được coi là cục bộ. Nếu nó không xuất hiện ở phía bên trái của một bài tập, nó được coi là toàn cầu.

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>> 

Xem cách baz, xuất hiện ở phía bên trái của một bài tập foo(), là LOAD_FASTbiến duy nhất .


12
Các heuristic tìm kiếm các hoạt động ràng buộc . Chuyển nhượng là một hoạt động như vậy, nhập khẩu khác. Nhưng mục tiêu của một forvòng lặp và tên sau asin withvà các exceptcâu lệnh cũng bị ràng buộc.
Martijn Pieters

@MartijnPieters Đối với tên sau astrong một exceptmệnh đề, điều này không rõ ràng đối với tôi. Nhưng nó sẽ tự động bị xóa để tiết kiệm bộ nhớ.
Robert

1
@Robert: không phải để lưu bộ nhớ, nhưng để tránh tạo tham chiếu vòng tròn, điều này có thể dẫn đến rò rỉ bộ nhớ. Đó là bởi vì một ngoại lệ tham chiếu một truy nguyên và truy nguyên này tham chiếu mọi không gian tên cục bộ và toàn cầu dọc theo toàn bộ ngăn xếp cuộc gọi, bao gồm cả as ...mục tiêu trong trình xử lý ngoại lệ.
Martijn Pieters

62

Nếu bạn muốn tham chiếu đến một biến toàn cục trong một hàm, bạn có thể sử dụng từ khóa toàn cầu để khai báo biến nào là toàn cục. Bạn không phải sử dụng nó trong mọi trường hợp (như ai đó ở đây tuyên bố không chính xác) - nếu tên được tham chiếu trong biểu thức không thể tìm thấy trong phạm vi cục bộ hoặc phạm vi trong các chức năng trong đó chức năng này được xác định, nó sẽ được tìm kiếm trên toàn cầu biến.

Tuy nhiên, nếu bạn gán cho một biến mới không được khai báo là toàn cục trong hàm, thì nó được khai báo ngầm định là cục bộ và nó có thể làm lu mờ bất kỳ biến toàn cục hiện có nào có cùng tên.

Ngoài ra, các biến toàn cục là hữu ích, trái với một số người quá khích OOP, người tuyên bố khác - đặc biệt là đối với các tập lệnh nhỏ hơn, trong đó OOP là quá mức cần thiết.


Hoàn toàn tái. sốt sắng. Hầu hết người dùng Python sử dụng nó để viết kịch bản và tạo các hàm nhỏ để tách các đoạn mã nhỏ.
Paul Uszak

51

Nếu tôi tạo một biến toàn cục trong một hàm, làm thế nào tôi có thể sử dụng biến đó trong một hàm khác?

Chúng ta có thể tạo một toàn cầu với chức năng sau:

def create_global_variable():
    global global_variable # must declare it to be a global first
    # modifications are thus reflected on the module's global scope
    global_variable = 'Foo' 

Viết một hàm không thực sự chạy mã của nó. Vì vậy, chúng tôi gọi create_global_variablechức năng:

>>> create_global_variable()

Sử dụng toàn cầu mà không sửa đổi

Bạn chỉ có thể sử dụng nó, miễn là bạn không muốn thay đổi đối tượng mà nó trỏ đến:

Ví dụ,

def use_global_variable():
    return global_variable + '!!!'

và bây giờ chúng ta có thể sử dụng biến toàn cục:

>>> use_global_variable()
'Foo!!!'

Sửa đổi biến toàn cục từ bên trong một hàm

Để trỏ biến toàn cục vào một đối tượng khác, bạn bắt buộc phải sử dụng lại từ khóa toàn cầu:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

Lưu ý rằng sau khi viết hàm này, mã thực sự thay đổi vẫn không chạy:

>>> use_global_variable()
'Foo!!!'

Vì vậy, sau khi gọi hàm:

>>> change_global_variable()

chúng ta có thể thấy rằng biến toàn cục đã được thay đổi. Các global_variabletên tại điểm đến 'Bar':

>>> use_global_variable()
'Bar!!!'

Lưu ý rằng "toàn cầu" trong Python không thực sự toàn cầu - nó chỉ toàn cầu ở cấp độ mô-đun. Vì vậy, nó chỉ có sẵn cho các chức năng được viết trong các mô-đun mà nó là toàn cầu. Các hàm nhớ mô-đun mà chúng được viết, vì vậy khi chúng được xuất sang các mô-đun khác, chúng vẫn tìm trong mô-đun mà chúng được tạo để tìm các biến toàn cục.

Biến cục bộ có cùng tên

Nếu bạn tạo một biến cục bộ có cùng tên, nó sẽ làm lu mờ một biến toàn cục:

def use_local_with_same_name_as_global():
    # bad name for a local variable, though.
    global_variable = 'Baz' 
    return global_variable + '!!!'

>>> use_local_with_same_name_as_global()
'Baz!!!'

Nhưng sử dụng biến cục bộ được đặt tên sai đó không làm thay đổi biến toàn cục:

>>> use_global_variable()
'Bar!!!'

Lưu ý rằng bạn nên tránh sử dụng các biến cục bộ có cùng tên với toàn cầu trừ khi bạn biết chính xác những gì bạn đang làm và có lý do rất chính đáng để làm như vậy. Tôi chưa gặp phải một lý do như vậy.

Chúng tôi có hành vi tương tự trong các lớp học

Theo dõi trên bình luận hỏi:

Phải làm gì nếu tôi muốn tạo một biến toàn cục bên trong một hàm bên trong một lớp và muốn sử dụng biến đó bên trong một hàm khác bên trong một lớp khác?

Ở đây tôi chứng minh chúng ta có hành vi tương tự trong các phương thức như chúng ta làm trong các hàm thông thường:

class Foo:
    def foo(self):
        global global_variable
        global_variable = 'Foo'

class Bar:
    def bar(self):
        return global_variable + '!!!'

Foo().foo()

Và bây giờ:

>>> Bar().bar()
'Foo!!!'

Nhưng tôi sẽ đề nghị thay vì sử dụng các biến toàn cục mà bạn sử dụng các thuộc tính lớp, để tránh làm lộn xộn không gian tên mô-đun. Cũng lưu ý rằng chúng tôi không sử dụng các selfđối số ở đây - đây có thể là các phương thức lớp (tiện dụng nếu thay đổi thuộc tính lớp từ clsđối số thông thường ) hoặc phương thức tĩnh (không selfhoặc cls).


Thật tuyệt, nhưng phải làm gì nếu tôi muốn tạo một biến toàn cục bên trong một hàm bên trong một lớp và muốn sử dụng biến đó bên trong một hàm khác bên trong một lớp khác? Kinda bị mắc kẹt ở đây
anonmanx

2
@anonmanx Tôi không biết tại sao bạn bị mắc kẹt, đó là hành vi tương tự trong một phương thức như trong một chức năng thông thường. Nhưng tôi sẽ cập nhật câu trả lời của tôi với nhận xét của bạn và một số mã demo, ok?
Aaron Hall

1
@anonmanx thế nào?
Aaron Hall

Được rồi hiểu rồi. Vì vậy, tôi sẽ phải gọi hàm đó một cách rõ ràng để sử dụng biến toàn cục đó.
anonmanx

47

Ngoài các câu trả lời đã có và làm cho điều này trở nên khó hiểu hơn:

Trong Python, các biến chỉ được tham chiếu bên trong một hàm là hoàn toàn toàn cục . Nếu một biến được gán một giá trị mới ở bất kỳ đâu trong thân hàm, thì nó được coi là cục bộ . Nếu một biến được gán một giá trị mới bên trong hàm, biến đó hoàn toàn cục bộ và bạn cần khai báo rõ ràng là 'toàn cầu'.

Mặc dù có một chút ngạc nhiên lúc đầu, sự cân nhắc của một khoảnh khắc giải thích điều này. Một mặt, yêu cầu toàn cầu cho các biến được chỉ định cung cấp một thanh chống lại các tác dụng phụ ngoài ý muốn. Mặt khác, nếu toàn cầu là bắt buộc đối với tất cả các tài liệu tham khảo toàn cầu, bạn sẽ sử dụng toàn cầu mọi lúc. Bạn phải khai báo là toàn cục mọi tham chiếu đến hàm tích hợp hoặc thành phần của mô-đun đã nhập. Sự lộn xộn này sẽ đánh bại tính hữu ích của tuyên bố toàn cầu để xác định các tác dụng phụ.

Nguồn: các quy tắc cho các biến cục bộ và toàn cầu trong Python là gì? .


34

Với thực thi song song, các biến toàn cục có thể gây ra kết quả không mong muốn nếu bạn không hiểu điều gì đang xảy ra. Dưới đây là một ví dụ về việc sử dụng biến toàn cục trong đa xử lý. Chúng ta có thể thấy rõ rằng mỗi quá trình hoạt động với bản sao của biến riêng:

import multiprocessing
import os
import random
import sys
import time

def worker(new_value):
    old_value = get_value()
    set_value(random.randint(1, 99))
    print('pid=[{pid}] '
          'old_value=[{old_value:2}] '
          'new_value=[{new_value:2}] '
          'get_value=[{get_value:2}]'.format(
          pid=str(os.getpid()),
          old_value=old_value,
          new_value=new_value,
          get_value=get_value()))

def get_value():
    global global_variable
    return global_variable

def set_value(new_value):
    global global_variable
    global_variable = new_value

global_variable = -1

print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after  set_value(), get_value() = [%s]' % get_value())

processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))

Đầu ra:

before set_value(), get_value() = [-1]
after  set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]

25

Những gì bạn đang nói là sử dụng phương pháp như thế này:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

Nhưng cách tốt hơn là sử dụng biến toàn cục như thế này:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

Cả hai đều cho cùng một đầu ra.


25

Hóa ra câu trả lời luôn đơn giản.

Đây là một mô-đun mẫu nhỏ với một cách đơn giản để hiển thị nó trong một mainđịnh nghĩa:

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation

def isTheNumber():
    return helper

Đây là cách thể hiện nó trong một mainđịnh nghĩa:

import TestPy

def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())

if __name__ == '__main__':
    main()

Mã đơn giản này hoạt động như vậy và nó sẽ thực thi. Tôi hy vọng nó sẽ giúp.


1
cảm ơn, tôi mới biết về python, nhưng biết một chút về java. những gì bạn nói đã làm việc cho tôi và viết toàn cầu <ENTER> trong lớp .. dường như có ý nghĩa với tôi hơn là trong chức năng viết 'toàn cầu' .. Tôi nhận thấy bạn không thể nói toàn cầu a = 4
barlop

2
Đây có lẽ là thủ thuật trăn đơn giản nhưng rất hữu ích đối với tôi. Tôi đặt tên cho mô-đun này global_varsvà khởi tạo dữ liệu init_global_vars, được gọi trong tập lệnh khởi động. Sau đó, tôi chỉ cần tạo phương thức accessor cho mỗi var toàn cầu được xác định. Tôi hy vọng tôi có thể nâng cấp này nhiều lần! Cảm ơn Peter!
swdev

1
Điều gì xảy ra nếu có nhiều biến toàn cục và tôi không muốn liệt kê từng biến một sau một tuyên bố toàn cầu?
jtlz2

23

Bạn cần tham chiếu biến toàn cục trong mọi chức năng bạn muốn sử dụng.

Như sau:

var = "test"

def printGlobalText():
    global var #wWe are telling to explicitly use the global version
    var = "global from printGlobalText fun."
    print "var from printGlobalText: " + var

def printLocalText():
    #We are NOT telling to explicitly use the global version, so we are creating a local variable
    var = "local version from printLocalText fun"
    print "var from printLocalText: " + var

printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""

3
'trong mọi chức năng bạn muốn sử dụng' là không chính xác, nên gần hơn với: 'trong mọi chức năng mà bạn muốn cập nhật '
spazm

21

Bạn không thực sự lưu trữ toàn cầu trong một biến cục bộ, chỉ tạo một tham chiếu cục bộ cho cùng một đối tượng mà tham chiếu toàn cầu ban đầu của bạn đề cập đến. Hãy nhớ rằng hầu hết mọi thứ trong Python là một tên liên quan đến một đối tượng và không có gì được sao chép trong hoạt động thông thường.

Nếu bạn không phải xác định rõ ràng khi nào một định danh được đề cập đến toàn cầu được xác định trước, thì có lẽ bạn phải xác định rõ ràng khi nào một định danh là một biến cục bộ mới thay thế (ví dụ, với một cái gì đó như lệnh 'var' thấy trong JavaScript). Do các biến cục bộ phổ biến hơn các biến toàn cục trong bất kỳ hệ thống nghiêm trọng và không tầm thường nào, nên hệ thống của Python có ý nghĩa hơn trong hầu hết các trường hợp.

Bạn có thể có một ngôn ngữ cố đoán, sử dụng biến toàn cục nếu nó tồn tại hoặc tạo biến cục bộ nếu không có ngôn ngữ. Tuy nhiên, điều đó sẽ rất dễ bị lỗi. Ví dụ: nhập một mô-đun khác có thể vô tình giới thiệu một biến toàn cục theo tên đó, thay đổi hành vi của chương trình của bạn.


17

Thử cái này:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7

15

Trong trường hợp bạn có một biến cục bộ có cùng tên, bạn có thể muốn sử dụng globals()hàm .

globals()['your_global_var'] = 42

14

Theo dõi và thêm vào, sử dụng một tệp để chứa tất cả các biến toàn cục được khai báo cục bộ và sau đó import as:

Tập tin initval.py :

Stocksin = 300
Prices = []

Tập tin getstocks.py :

import initval as iv

def getmystocks(): 
    iv.Stocksin = getstockcount()


def getmycharts():
    for ic in range(iv.Stocksin):

1
Lợi thế để di chuyển các biến toàn cầu sang một tập tin khác là gì? Có phải chỉ để nhóm các biến toàn cục trong một tệp nhỏ? Và tại sao sử dụng tuyên bố import ... as ...? Tại sao không chỉ import ...?
olibre

1
À ... cuối cùng tôi cũng đã hiểu được lợi thế: Không cần sử dụng từ khóa global:-) => +1 :-) Vui lòng chỉnh sửa câu trả lời của bạn để làm rõ những cuộc thẩm vấn này mà người khác cũng có thể có. Chúc mừng
olibre

13

Viết cho các yếu tố rõ ràng của một mảng toàn cầu dường như không cần khai báo toàn cầu, mặc dù viết cho nó "bán buôn" có yêu cầu đó:

import numpy as np

hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])

def func1():
    global hostValue    # mandatory, else local.
    hostValue = 2.0

def func2():
    global hostValue    # mandatory, else UnboundLocalError.
    hostValue += 1.0

def func3():
    global hostArray    # mandatory, else local.
    hostArray = np.array([14., 15.])

def func4():            # no need for globals
    hostArray[0] = 123.4

def func5():            # no need for globals
    hostArray[1] += 1.0

def func6():            # no need for globals
    hostMatrix[1][1] = 12.

def func7():            # no need for globals
    hostMatrix[0][0] += 0.33

func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix

7

Tôi đang thêm điều này vì tôi chưa thấy nó trong bất kỳ câu trả lời nào khác và nó có thể hữu ích cho ai đó đang vật lộn với điều gì đó tương tự. Các globals()chức năng trả về một thể thay đổi từ điển biểu tượng toàn cầu, nơi bạn có thể "kỳ diệu" làm cho có sẵn cho phần còn lại của mã của bạn dữ liệu. Ví dụ:

from pickle import load
def loaditem(name):
    with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
        globals()[name] = load(openfile)
    return True

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

Sẽ chỉ cho phép bạn kết xuất / tải các biến ra khỏi và vào không gian tên toàn cầu. Siêu tiện lợi, không ồn ào, không ồn ào. Khá chắc chắn đó chỉ là Python 3.


3
globals()luôn trả về các quả cầu có sẵn trong bối cảnh địa phương, do đó, một đột biến ở đây có thể không phản ánh trong một mô-đun khác.
Kiran Jonnalagadda

6

Tham chiếu không gian tên lớp nơi bạn muốn thay đổi hiển thị.

Trong ví dụ này, người chạy đang sử dụng tối đa từ cấu hình tệp. Tôi muốn thử nghiệm của mình thay đổi giá trị tối đa khi người chạy đang sử dụng nó.

chính / config.py

max = 15000

chính / á hậu

from main import config
def check_threads():
    return max < thread_count 

tests / runner_test.py

from main import runner                # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
   def test_threads(self):
       runner.max = 0                  # <----- 2. set global 
       check_threads()

1

Globals là tốt - Ngoại trừ với đa xử lý

Các quả cầu liên quan đến đa xử lý trên các nền tảng / môi trường khác nhau vì một bên là Windows / Mac OS và một bên là Linux thì thật rắc rối.

Tôi sẽ chỉ cho bạn điều này với một ví dụ đơn giản chỉ ra một vấn đề mà tôi gặp phải một thời gian trước đây.

Nếu bạn muốn hiểu, tại sao mọi thứ lại khác nhau trên Windows / MacO và Linux, bạn cần biết rằng, cơ chế mặc định để bắt đầu một quy trình mới trên ...

  • Windows / MacO là 'sinh sản'
  • Linux là 'ngã ba'

Chúng khác nhau trong việc cấp phát Bộ nhớ khởi tạo ... (nhưng tôi không đi sâu vào vấn đề này ở đây).

Chúng ta hãy xem xét vấn đề / ví dụ ...

import multiprocessing

counter = 0

def do(task_id):
    global counter
    counter +=1
    print(f'task {task_id}: counter = {counter}')

if __name__ == '__main__':

    pool = multiprocessing.Pool(processes=4)
    task_ids = list(range(4))
    pool.map(do, task_ids)

các cửa sổ

Nếu bạn chạy cái này trên Windows (Và tôi cũng cho rằng trên MacOS), bạn sẽ nhận được đầu ra sau ...

task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4

Linux

Nếu bạn chạy cái này trên Linux, bạn sẽ nhận được những thứ sau đây.

task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.