2011-02-01 32 views
8

Possible Duplicate:
How to programmatically set a global (module) variable?lập trình tạo ra các biến bằng Python

Tôi có một lớp được gọi là biến được định nghĩa như vậy:

class Variable(): 
    def __init__(self, name): 
     self.name = name 
     self._value = None 
    def value(self): 
     return self._value 
    def __repr__(self): 
     return self.name 

Tôi muốn tạo ra trường hợp 26 vốn đơn thư biến như thế này:

A = Variable('A') 
B = Variable('B') 
... 
Z = Variable('Z') 

Cho đến nay tôi đã thử các giải pháp khác nhau và tốt nhất tôi đã đưa ra là:

from string import uppercase 
for char in uppercase: 
    exec "%s = %s" % (char, Variable(str(char))) in None 

Tuy nhiên, điều này không chạy và mang lại cho tôi lỗi này:

Traceback (most recent call last): 
    File "C:\Users\Administrator\Dev\python\truthtable\truthtable.py", line 7, in <module> 
    exec "%s = %s" % (char, Variable(str(char))) in None 
    File "<string>", line 1, in <module> 
NameError: name 'A' is not defined 

Tôi đang làm gì sai?

+8

Khác với việc cố gắng tạo biến động? –

+0

Er, tên câu hỏi là một chút hào nhoáng, tôi không quá clued vào các loại ngữ nghĩa. – deeb

+1

@deeb - Tôi không nghĩ Ignacio đang đề cập đến danh hiệu của bạn. – senderle

Trả lời

15
from string import uppercase 
_g = globals() 
for char in uppercase: 
    _g[char] = Variable(char) 

Cho dù đây là một tốt ý tưởng vẫn còn đáng ngờ :)

này chỉ làm việc cho globals() (tức là mô-đun tập level), như định nghĩa ngôn ngữ một cách rõ ràng rằng sửa đổi từ điển được trả về bởi locals() có thể không thực sự thay đổi giá trị của bất kỳ biến cục bộ nào.

Bạn cũng có thể làm điều gì đó tương tự với __dict__ của một lớp hoặc một cá thể.

+0

Sửa đổi globals() không phải là một ý tưởng hay: không có đảm bảo chính thức rằng tác vụ này: "Điều này có thể thất bại:" không có bảo đảm tài liệu rằng thay đổi globals() sẽ thực sự tồn tại những thay đổi cho mô-đun cơ bản. Nó hoạt động ngày hôm nay, có thể phá vỡ vào ngày mai. ”(Alex Martelli) – EOL

+1

Điều đó không đúng - mà caveat áp dụng * chỉ * đối với người dân địa phương(). Globals() được đảm bảo hoạt động chính xác theo đặc tả ngôn ngữ – ncoghlan

+0

@ncoghian: Đây là bản gốc bình luận của Alex, người được cho là một lập trình viên Python dày dạn kinh nghiệm: http://stackoverflow.com/questions/1429814/how-to-programmatically-set-a-global-module-variable :) – EOL

0
from string import uppercase 
for c in uppercase: 
    locals()[c] = Variable(c) 
print A 

Tôi không chắc chắn lý do bạn muốn thực hiện việc này.

+2

Điều này có thể chính thức thất bại: "Nội dung của từ điển này không nên sửa đổi, thay đổi có thể không ảnh hưởng đến giá trị của các biến địa phương và miễn phí được sử dụng bởi trình thông dịch." (từ tài liệu). – EOL

4

Vâng, nó không đẹp nhưng bạn có thể truy cập vào globals() từ điển trực tiếp:

for c in 'ABC': 
    globals()[c] = Variable(c) 
+1

"Phân bổ thuộc tính cập nhật từ điển không gian tên của mô-đun, ví dụ: m.x = 1 tương đương với m .__ dict __ [" x "] = 1." (từ http://docs.python.org/reference/datamodel.html) – ncoghlan

3

Bạn không cần phải sử dụng exec cho điều này, như là câu trả lời khác hiển thị, nhưng đây là vấn đề với ban đầu của bạn mã:

for char in uppercase: 
    exec "%s = %s" % (char, Variable(str(char))) in None 

này sẽ exec A = A, B = B, vv trong khi điều này có thể rất thú vị nếu bạn là một tín đồ cuồng nhiệt của chủ nghĩa khách quan, trăn sẽ không quan tâm quá nhiều cho nó.

Bạn muốn có những thứ Variable() bên trong exec cho nó quan trọng:

for char in uppercase: 
    exec "%s = Variable('%s')" % (char, char) 

Trong tương lai, nếu bạn đang cố gắng sử dụng exec, đầu tiên cố gắng không để. Thứ hai, in những gì bạn đang thực hiện - điều đó sẽ giúp gỡ lỗi.

+0

Không có downvote, nhưng có một cách sạch hơn (và có thể là cách nhanh hơn, nếu điều đó quan trọng), như đã nêu rõ trong câu trả lời của tôi. – EOL

+0

Tất nhiên có, tôi nói không làm theo cách này trong câu trả lời của tôi. Đây là phiên bản cố định của mã gốc thực sự sử dụng 'exec'. – tkerwin

7

Phương pháp sạch cho đến nay mà tôi đã từng gặp là để trực tiếp thêm biến (tức là thuộc tính) để chương trình của bạn (tức là chính mô-đun), như đã trả lời trong another question on StackOverflow:

import sys 
from string import ascii_uppercase 

this_module = sys.modules[__name__] 
for char in ascii_uppercase: 
    setattr(this_module, char, Variable(char)) 

print A # Works! 

PS: Python lõi các nhà phát triển đã làm việc chăm chỉ để có thể sửa đổi globals() có thể (xem nhận xét về câu trả lời của ncoghlan). Vì vậy, sửa đổi globals() là một thay thế.Tôi không chắc chắn tại sao nhiều người cảm thấy rằng nó không phải là quá sạch sẽ, mặc dù (có thể bởi vì thực tế là globals() có thể được sửa đổi không phải là rõ ràng tài liệu?).

2

Đừng cố gắng gắn kết điều này vào biến toàn cục. Thật kinh khủng. Làm điều này để thay thế.

import string 

variables = {} 
for x in string.ascii_uppercase: 
    variables[x] = Variable(x) 

Bạn truy cập từ variables['Q'], ví dụ:

Nếu bạn muốn thuộc tính truy cập bạn có thể làm:

class Variables(object): pass 

variables = Variables() 
for x in string.ascii_uppercase: 
    setattr(variables, x) = Variable(x) 

Nhưng trong trường hợp đó tôi thà tạo cho họ động trong một lớp học Biến chứa.

import string 

class Variable(object): 
    def __init__(self, value): 
     self.value = value 
    def __repr__(self): 
     return "<Variable %s>" % self.value 

class Variables(object): 
    def __getattr__(self, n): 
     if n in string.ascii_uppercase: 
      v = Variable(n) 
      setattr(self, n, v) 
      return v 
     raise AttributeError("Variables instance has no attribute %s" % n) 

Cách sử dụng:

>>> v = Variables() 
>>> v.G 
<Variable G> 
>>> v.Y 
<Variable Y> 
>>> v.G is v.G 
True 

đơn giản và sạch sẽ, không có hacks xấu xí (tốt, ngoại trừ một getattr, và nó không phải là xấu xí), và bạn thậm chí không cần phải thực hiện các biến bạn don không cần.

+0

Mặc dù tôi đồng ý rằng đây thường là cách để đi, chắc chắn có trường hợp sử dụng để thêm nhiều đối tượng trực tiếp vào không gian tên cục bộ, ví dụ: cho toán học. x == sin (w) * (y + exp (-z)) là thế giới tốt hơn v.x == m.sin (v.w) * (v.y + m.exp (-v.z)). – DSM

+0

Vâng, tôi nghĩ rằng các nhà toán học ám ảnh với một chữ cái tên biến dài là một sai lầm ở nơi đầu tiên. :) Nó hữu ích khi bạn thực hiện các phép tính trên giấy, hoặc đơn giản hóa/mở rộng các công thức. Nhưng trong việc thực hiện thực tế của một công thức trong một ngôn ngữ lập trình? Nyaaahhhh tôi hoài nghi ... :-) –

+2

Có thể bạn ngay lập tức xóa tất cả "v." và M." trong biểu hiện thứ hai của tôi và nhìn thấy biểu thức đầu tiên, nhưng tôi phải so sánh chúng gần như ký tự theo ký tự để chắc chắn chúng giống nhau. Một chữ cái bổ sung cho mỗi biến và hàm, và một dấu chấm làm cho tôi nghĩ phép nhân. Tôi có nhiều khả năng bỏ lỡ một lỗi rõ ràng ở dạng thứ hai, vì tôi phải vượt qua nhiều năm kinh nghiệm đọc mẫu chuẩn mà không có các nhân vật không liên quan. Tính dễ đọc, khi tôi nghe ai đó nói ở đâu đó ;-), và nguyên tắc đó không phải lúc nào cũng nghiêng về lợi thế của nhiều nhân vật hơn. – DSM

Các vấn đề liên quan