2009-06-25 26 views
29

Hãy xem xét đoạn mã này:Nhận một dict của tất cả các biến hiện nay trong phạm vi và giá trị của họ

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(**VARS_IN_SCOPE) 

myfunc(123) 

đâu VARS_IN_SCOPE là dict tôi sau đó sẽ chứa globalVar, paramVarlocalVar, trong số những thứ khác.

Tôi muốn cơ bản có thể tham chiếu tất cả các biến hiện đang nằm trong phạm vi bên trong chuỗi. Do đó sản lượng dự kiến ​​sẽ là:

Vars: 25, 123, 30

tôi có thể đạt được điều này bằng cách thông qua **dict(globals().items() + locals().items())-format(). Điều này luôn đúng hay có một số trường hợp góc mà biểu thức này sẽ xử lý không chính xác?

Được viết lại để làm rõ câu hỏi.

+0

Tại sao bạn muốn làm điều đó? Rất có thể, có một cách tốt hơn để làm bất cứ điều gì bạn đang cố gắng làm. –

+0

Tôi nghĩ đoạn trích sẽ rõ ràng. Tôi muốn nội suy các biến bên trong chuỗi. Bằng mọi cách, có thể có một cách tốt hơn. Xin vui lòng đề nghị một câu trả lời. –

+0

Xin lỗi, đoạn mã không giải thích được ** tại sao ** bạn cần một thứ như vậy. Ngoài ra, các tham số đơn giản là cục bộ - nó không phải là một phạm vi riêng biệt. –

Trả lời

32

Cách tốt nhất để nhập hai dấu gạch ngang khi bạn đang thực hiện (với địa phương ghi đè hình cầu) là dict(globals(), **locals()).

Cách tiếp cận của việc kết hợp các hình cầu và địa phương bị thiếu là (a) nội trang (tôi tưởng tượng đó là cố ý, nghĩa là bạn không nghĩ rằng nội trang là "biến" ... nhưng, có thể là, nếu bạn chọn ! -), và (b) nếu bạn đang sử dụng chức năng lồng nhau, bất kỳ biến nào là địa phương cho các hàm kèm theo (không có cách thực sự tốt để có được một mệnh đề với tất cả những người đó, cộng - chỉ những người được truy cập rõ ràng trong hàm lồng nhau, tức là "biến tự do" của chúng, vẫn tồn tại dưới dạng các ô trong một bao đóng).

Tôi tưởng tượng những vấn đề này không phải là vấn đề lớn đối với mục đích sử dụng của bạn, nhưng bạn đã đề cập đến "trường hợp góc" ;-). Nếu bạn cần trang trải chúng, có nhiều cách để có được các built-in (dễ dàng) và (không dễ dàng) tất cả các ô (các biến từ các hàm kèm theo mà bạn đề cập rõ ràng trong hàm lồng nhau - thefunction.func_code.co_freevars để lấy tên, thefunction.func_closure để nhận các ô, cell_contents trên mỗi ô để lấy giá trị của ô). (Nhưng, hãy nhớ, những người đó sẽ chỉ là các biến từ các hàm kèm theo được truy cập rõ ràng trong mã của hàm lồng nhau của bạn!).

+0

Thật lạ khi bạn không thể lấy tất cả các biến từ bên trong một hàm lồng nhau. Bất cứ ai biết tại sao 'người dân địa phương()' sẽ không hoạt động? Có vẻ như nó nên! – sudo

7

Điều này có làm những gì bạn dự định không?

d = dict(globals()) 
d.update(locals()) 

Nếu tôi đọc tài liệu một cách chính xác, bạn tạo một bản sao của globals() dict, sau đó bạn ghi đè lên bất kỳ bản sao mục mới chèn từ locals() dict (kể từ khi locals() nên có ưu tiên trong phạm vi của mình, dù sao).


tôi đã không có bất kỳ may mắn trong việc một chức năng thích hợp để trả lại từ điển đầy đủ các biến trong phạm vi của gọi chức năng. Dưới đây là đoạn code (tôi chỉ sử dụng pprint để định dạng đầu ra độc đáo cho SO):

from pprint import * 

def allvars_bad(): 
    fake_temp_var = 1 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

def foo_bad(): 
    x = 5 
    return allvars_bad() 

def foo_good(): 
    x = 5 
    fake_temp_var = "good" 
    d = dict(globals()) 
    d.update(locals()) 
    return d 

pprint (foo_bad(), width=50) 
pprint (foo_good(), width=50) 

và đầu ra:

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093748>, 
'fake_temp_var': 1, 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>} 
{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'allvars_bad': <function allvars_bad at 0xb7d32b1c>, 
'd': <Recursion on dict with id=3084093884>, 
'fake_temp_var': 'good', 
'foo_bad': <function foo_bad at 0xb7d329cc>, 
'foo_good': <function foo_good at 0xb7d32f0c>, 
'isreadable': <function isreadable at 0xb7d32c34>, 
'isrecursive': <function isrecursive at 0xb7d32c6c>, 
'pformat': <function pformat at 0xb7d32bc4>, 
'pprint': <function pprint at 0xb7d32b8c>, 
'saferepr': <function saferepr at 0xb7d32bfc>, 
'x': 5} 

Lưu ý rằng trong đầu ra thứ hai, chúng tôi đã ghi đè fake_temp_var, và x là hiện tại; đầu ra đầu tiên chỉ bao gồm các vars cục bộ trong phạm vi allvars_bad.

Vì vậy, nếu bạn muốn truy cập phạm vi biến hoàn toàn, bạn không thể đặt người dân địa phương() bên trong một hàm khác.


Tôi đã nghi ngờ có một số loại đối tượng khung hình, tôi không biết (tìm nơi) tìm kiếm.

này hoạt động để spec của bạn, tôi tin rằng:

def allvars_good(offset=0): 
    frame = sys._getframe(1+offset) 
    d = frame.f_globals 
    d.update(frame.f_locals) 
    return d 


def foo_good2(): 
    a = 1 
    b = 2 
    return allvars_good() 

->

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d6474c>, 
'__builtins__': <module '__builtin__' (built-in)>, 
'__doc__': None, 
'__file__': 'temp.py', 
'__name__': '__main__', 
'__package__': None, 
'a': 1, 
'allvars_bad': <function allvars_bad at 0xb7d65b54>, 
'allvars_good': <function allvars_good at 0xb7d65a04>, 
'b': 2, 
'foo_bad': <function foo_bad at 0xb7d65f44>, 
'foo_good': <function foo_good at 0xb7d65f7c>, 
'foo_good2': <function foo_good2 at 0xb7d65fb4>, 
'isreadable': <function isreadable at 0xb7d65c6c>, 
'isrecursive': <function isrecursive at 0xb7d65ca4>, 
'pformat': <function pformat at 0xb7d65bfc>, 
'pprint': <function pprint at 0xb7d65bc4>, 
'saferepr': <function saferepr at 0xb7d65c34>, 
'sys': <module 'sys' (built-in)>} 
+0

Để trả lời câu hỏi của bạn, tôi không biết :) Đây thực sự là những gì tôi muốn tìm hiểu - cho dù chỉ kết hợp cả hai là điều đúng đắn để làm. –

+0

Vâng, rất tiếc người dân địa phương() phải ở ngay đó. Tương tự với globals() - nó phải nằm trong cùng một module để làm việc. Tôi tự hỏi nếu một số thủ thuật sys._getframe() có thể được sử dụng thay thế. –

2

Bạn có thể làm của riêng bạn:

allvars = dict() 
allvars.update(globals()) 
allvars.update(locals()) 

hoặc kết hợp hai dòng đầu tiên:

allvars = dict(globals()) 
allvars.update(locals()) 
1

Nội suy thành chuỗi hoạt động theo cách đơn giản nhất có thể. Chỉ cần liệt kê các biến của bạn. Python kiểm tra người dân địa phương và globals cho bạn.

globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    print "Vars: %d, %d, %d!" % (globalVar, paramVar, localVar) 

myfunc(123) 
+0

Đó không phải là nội suy. http://en.wikipedia.org/wiki/Variable_(computer_science)#Interpolation - Python không có nó như vậy, nhưng với hàm .format() bạn có thể nhận được khá gần. –

+0

Và trong trường hợp bạn tự hỏi tại sao tôi không thích% - hãy suy nghĩ về điều gì đó như thế này: in "{path} /myscript.py --input {path}/file1 --output {path}/file2" .format (** người dân địa phương ()) - với "%" tôi sẽ cần phải vượt qua con đường ba lần. Với rất nhiều biến số này trở thành một cơn ác mộng hoàn chỉnh để duy trì. –

+0

@romkyns: Không phải vậy. Toán tử chuỗi '%' có thể lấy đối số dict mà không cần giải nén nó bằng '**' như 'định dạng' làm: in"% (đường dẫn) s/myscript.py --input% (đường dẫn) s/file1 --output% (path) s/file2 "% locals() –

2
globalVar = 25 

def myfunc(paramVar): 
    localVar = 30 
    all_vars = locals.copy() 
    all_vars.update(globals()) 
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(all_vars) 

myfunc(123) 
Các vấn đề liên quan