Tôi đang cố gắng chạy một đoạn mã python bằng cách sử dụng exec.globals và locals trong python exec()
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
mà kết quả trong đầu ra sau đây
locals: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 9, in B
NameError: name 'A' is not defined
Tuy nhiên, nếu tôi thay đổi mã này -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(A):
pass
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
sau đó nó hoạt động tốt - đưa ra các kết quả như sau -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'A': <class 'A'>, 'B': <class 'B'>}
Rõ ràng A được đặt trước ent và có thể truy cập - những gì đang xảy ra trong đoạn mã đầu tiên? Tôi đang sử dụng 2.6.5, cổ vũ,
Colin
* CẬP NHẬT 1 *
Nếu tôi kiểm tra người dân địa phương() bên trong lớp -
my_code = """
class A(object):
pass
print 'locals: %s' % locals()
print 'A: %s' % A
class B(object):
print locals()
a_ref = A
"""
global_env = {}
local_env = {}
my_code_AST = compile(my_code, "My Code", "exec")
exec(my_code_AST, global_env, local_env)
print local_env
Sau đó, nó trở thành rõ ràng rằng người dân địa phương() không giống nhau ở cả hai địa điểm -
locals: {'A': <class 'A'>}
A: <class 'A'>
{'__module__': '__builtin__'}
Traceback (most recent call last):
File "python_test.py", line 16, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 8, in <module>
File "My Code", line 10, in B
NameError: name 'A' is not defined
Tuy nhiên, nếu tôi làm điều này, không có vấn đề -
def f():
class A(object):
pass
class B(object):
a_ref = A
f()
print 'Finished OK'
* CẬP NHẬT 2 *
ok, vì vậy các tài liệu ở đây - http://docs.python.org/reference/executionmodel.html
'Một định nghĩa lớp là một thực thi tuyên bố có thể sử dụng và xác định tên. Các tham chiếu này tuân theo các quy tắc thông thường để phân giải tên. Không gian tên của định nghĩa lớp trở thành từ điển thuộc tính của lớp. Các tên được định nghĩa ở phạm vi lớp không hiển thị trong các phương thức. ' Có vẻ như với tôi rằng 'A' nên có sẵn như là một biến miễn phí trong câu lệnh thực thi là định nghĩa của B, và điều này xảy ra khi chúng ta gọi f() ở trên, nhưng không phải khi chúng ta sử dụng exec (). Điều này có thể dễ dàng hơn hiển thị với những điều sau đây -
my_code = """
class A(object):
pass
print 'locals in body: %s' % locals()
print 'A: %s' % A
def f():
print 'A in f: %s' % A
f()
class B(object):
a_ref = A
"""
mà kết quả đầu ra
locals in body: {'A': <class 'A'>}
A: <class 'A'>
Traceback (most recent call last):
File "python_test.py", line 20, in <module>
exec(my_code_AST, global_env, local_env)
File "My Code", line 11, in <module>
File "My Code", line 9, in f
NameError: global name 'A' is not defined
Vì vậy, tôi đoán câu hỏi mới là - tại sao không phải là những người dân địa phương được tiếp xúc như biến miễn phí trong các chức năng và định nghĩa lớp - nó có vẻ giống như một kịch bản đóng cửa khá chuẩn.
Tốt. Không bao giờ để ý điều đó. – zefciu
Có vẻ như vấn đề tương tự như trong câu hỏi này: http://stackoverflow.com/questions/2749655/why-are-closures-broken-within-exec – interjay
cảm ơn con trỏ - Tôi không phải là một guru trăn, nhưng có vẻ như khi tôi in các locals(), A * đã * được biên dịch thành một biến cục bộ - nghĩa là nó không biết phải làm gì với nó. Câu trả lời trong câu hỏi bạn đánh dấu là - 'Không có cách nào để biên dịch biết rằng đó là freevar, do đó nó biên dịch nó thành tham chiếu toàn cầu' Vấn đề ở đây có vẻ là người dân địa phương() được định nghĩa lại bên trong cơ thể của B khi sử dụng exec, nhưng không phải khi sử dụng một chức năng (xem cập nhật trong câu hỏi)? Có thể dễ dàng là sự hiểu lầm của tôi về hàm ý của câu trả lời đó ... – hawkett