2014-04-01 28 views
6

dụ MinimalPython vấn đề Phạm vi với sự hiểu biết từ điển bên trong mã cấp lớp

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     # works 
     print({e : loadings[e] for e in loadings}) 
     # NameError global name 'loadings' not defined 

tôi đã cố gắng tham khảo không gian tên lớp cũng nhưng không hoạt động hoặc

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     #works 
     print({e : foo.loadings[e] for e in foo.loadings}) 
     #NameError: name 'foo' is not defined 

Và dĩ nhiên, hoạt động như mong đợi

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 

print({e : foo.loadings[e] for e in foo.loadings}) 

I w kiến để hiểu lý do tại sao vấn đề phạm vi này xảy ra sau đó, nếu tôi đang cố gắng làm điều gì đó điên rồ hiểu cách tốt nhất để làm điều đó bằng cách khác. Cảm giác của tôi là snip mã đầu tiên đã hoạt động như cũ, nhưng tất nhiên là nó không có.

Mục tiêu

tôi đang tạo ra một DataManager lớp/mô-đun cho một số tập tin csv/json cùng với truy vấn cơ sở dữ liệu đóng hộp, một một cửa cho chương trình của tôi và các dữ liệu thu thập. Có một số dữ liệu tĩnh và một số dữ liệu động vì vậy nó có vẻ giống như việc sử dụng tuyệt vời các thành viên dữ liệu tĩnh và không tĩnh trong cùng một lớp. Mặc dù tôi hiểu rằng đây có thể là các biến cấp mô-đun, nhưng tôi thích khái niệm có các thành viên dữ liệu lớp tĩnh (có thể do sự thiên vị từ Java). Bất kỳ sự giúp đỡ được nhiều đánh giá

Giải pháp của tôi (bây giờ)

tôi đã kết thúc giăng danh sách hiểu ở lại phạm vi lớp học, ở trên nó sẽ trở thành một cái gì đó như thế này

class foo: 
    loadings = dict(hi=1) 
    temp = dict() 
    for e in loadings: 
     temp[e] = loadings[e] # keep in mind this is a minimal example, I probably wouldn't do (just) this 
    print(temp) # works 
    del temp 

Nó không phải là đẹp, nhưng nó hoạt động cho bây giờ

+0

Bạn nên làm tất cả những gì bên trong một hàm init .... –

+0

Tôi nghĩ nó cũng thú vị để lưu ý rằng 'in ({k: v cho k, v trong loadings.items()}) 'không hoạt động.Vì vậy, 'tải' là ít nhất là kinda nhìn thấy trong dict comprehension – cmd

+0

Điều này đã không được thực hiện trong hàm init vì đây là dữ liệu tĩnh cho lớp được nạp một lần. Tôi có thể có một số lá cờ như 'runonce' hoặc một cái gì đó nhưng có vẻ như mã cấp lớp là có cho một lý do. – user25064

Trả lời

4

Mỗi Name and Binding docs:

Phạm vi của các tên được xác định trong một khối lớp được giới hạn trong lớp khối; nó không mở rộng đến các khối mã của các phương thức - này bao gồm các sự hiểu biết và các biểu thức của trình tạo từ khi chúng được thực hiện bằng cách sử dụng phạm vi chức năng. Điều này có nghĩa rằng sau đây sẽ thất bại:

class A: 
    a = 42 
    b = list(a + i for i in range(10)) 

Xem this answer để biết thêm chi tiết.


Trong python2, nó có thể sử dụng comprehensions danh sách, vì họ đã được thực hiện mà không cần sử dụng một phạm vi chức năng:

dict([(e,loadings[e]) for e in loadings]) 

Nhưng mã này sẽ phá vỡ nếu chạy trong Python3. Vì vậy, đây là một cách giải quyết khác mà có thể làm việc trong python2 và Python3:

class Foo: 
    def loadings(): 
     load = dict(hi=1) 
     if 'hi' in load: 
      print(load['hi']) 
      print({e:load[e] for e in load}) 
     return load 
    loadings = loadings() 

print(Foo.loadings) 
+0

Cảm ơn bạn rất nhiều vì đã giải thích rõ ràng và súc tích! Tôi muốn chỉ ra cho bạn rằng ý định của tôi là thay thế hai dòng cuối cùng của khối mã cuối cùng của bạn bằng một cái gì đó như 'print (Foo.loadings)' và sử dụng nó như một thành viên dữ liệu tĩnh. – user25064

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