Làm cách nào để gọi setattr () trên mô-đun hiện tại?


140

Làm gì để tôi chuyển làm tham số đầu tiên " object" cho hàm setattr(object, name, value), để đặt biến trên mô-đun hiện tại?

Ví dụ:

setattr(object, "SOME_CONSTANT", 42);

cho hiệu quả tương tự như:

SOME_CONSTANT = 42

trong mô-đun chứa các dòng này (với chính xác object).

Tôi đang tạo một số giá trị ở cấp mô-đun một cách linh hoạt và vì tôi không thể xác định __getattr__ở cấp mô-đun, đây là dự phòng của tôi.

Câu trả lời:


220
import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

hoặc, không sử dụng setattr(phá vỡ chữ cái của câu hỏi nhưng đáp ứng các mục đích thực tế tương tự ;-):

globals()[name] = value

Lưu ý : ở phạm vi mô-đun, cái sau tương đương với:

vars()[name] = value

ngắn gọn hơn một chút, nhưng không hoạt động trong một hàm ( vars()đưa ra các biến của phạm vi mà nó được gọi tại: các biến của mô-đun khi được gọi ở phạm vi toàn cầu, và sau đó sử dụng R / W, nhưng hàm này là OK các biến khi được gọi trong một hàm, và sau đó nó phải được coi là R / O - các tài liệu trực tuyến Python có thể hơi khó hiểu về sự khác biệt cụ thể này).


9
Các tài liệu đưa ra một cảnh báo về sửa đổi vars (). docs.python.org/l Library / fiances.html # volt . Khi nào thì ổn?
unutbu

2
@ ~ unutbu, tôi thực sự sẽ không nói rằng nó khá "ổn", nhưng nó sẽ hoạt động khi bạn gọi vars()ở phạm vi cấp mô-đun chứ không phải bên trong hàm.
Mike Graham

4
vars()tương đương với globals()ở phạm vi mô-đun (và do đó trả về một lệnh chính xác, có thể sửa đổi) nhưng locals()ở phạm vi chức năng (và do đó trả về một giả ngẫu nhiên không bao giờ được sửa đổi). Tôi sử dụng vars()ở phạm vi mô-đun vì nó lưu 3 ký tự, một âm tiết, so với từ đồng nghĩa của nó trong phạm vi đó globals();-)
Alex Martelli

14
Đúng, nó sẽ phá hủy tối ưu hóa quan trọng nhất mà trình biên dịch Python thực hiện: các biến cục bộ của hàm không được giữ trong một lệnh, chúng nằm trong một vectơ giá trị chặt chẽ và mỗi truy cập biến cục bộ sử dụng chỉ mục trong vectơ đó, không phải tra cứu tên. Để đánh bại việc tối ưu hóa, buộc dict bạn muốn tồn tại, hãy khởi động hàm bằng exec '': thời gian một hàm với một vài vòng lặp đáng kể mỗi cách và bạn sẽ thấy tầm quan trọng của tối ưu hóa cốt lõi này đối với hiệu suất của Python.
Alex Martelli

3
@msw, tôi nghĩ bạn đã quên "tính thực tế đánh bại sự thuần khiết" ;-).
Alex Martelli

6

Nếu bạn phải đặt các biến trong phạm vi mô-đun từ bên trong mô-đun, điều gì sai global?

# my_module.py

def define_module_scoped_variables():
    global a, b, c
    a, b, c = 'a', ['b'], 3

do đó:

>>> import my_module
>>> my_module.define_module_scoped_variables()
>>> a
NameError: name 'a' is not defined
>>> my_module.a
'a'
>>> my_module.b
['b']

1
Vâng, tôi đã luôn luôn (trong đó "luôn luôn" được định nghĩa là "vài tháng trước tôi đã học Python") thấy rằng global but not reallytuyên bố đó rất khó hiểu. Tôi cho rằng nó có thể là một di tích lịch sử có trước các không gian tên mô-đun.
msw

1
Câu hỏi ban đầu là hỏi làm thế nào để thiết lập một thuộc tính có tên được đặt bởi một chuỗi (điều tương tự mà tôi hiện đang tìm kiếm), vì vậy điều này sẽ không giúp ích gì.
Curt

6

Trong Python 3.7, bạn sẽ có thể sử dụng __getattr__ở cấp độ mô-đun ( câu trả lời liên quan ).

Mỗi PEP 562 :

def __getattr__(name):
    if name == "SOME_CONSTANT":
        return 42
    raise AttributeError(f"module {__name__} has no attribute {name}")

-1
  1. Bạn sẽ không. Bạn sẽ làmglobals()["SOME_CONSTANT"] = 42
  2. Bạn sẽ không. Bạn sẽ lưu trữ nội dung được tạo động ở một nơi khác ngoài mô-đun.

Đúng, SOME_CONSTANTtính toán trong thời gian chạy không chính xác không đổi. Và nếu globals()không có sẵn cho bạn thì bạn phải tiếp cận với một mô-đun khác để sửa đổi các thuộc tính của nó; đó là ràng buộc để làm cho mọi người tự hỏi.
msw

3
Liên tục và đột biến là loại trừ lẫn nhau. Liên tục và năng động tạo ra là không. Các giá trị tôi tạo ra luôn giống nhau và được xác định dựa trên các "hằng số" tiếp theo, để tiết kiệm số học và nhập vào phần của tôi.
Matt Joiner
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.