2011-10-13 41 views
6

Trình soạn thảo văn bản của tôi được lựa chọn có thể mở rộng thông qua các plugin trăn. Nó đòi hỏi tôi phải mở rộng các lớp và ghi đè lên các phương thức của nó. Cấu trúc chung trông giống đoạn mã dưới đây. Lưu ý rằng chữ ký hàm được cố định.Phạm vi thay đổi bên ngoài các lớp học

ftp_client được cho là được chia sẻ bởi các phiên bản của cả hai lớp.

ftp_client = None 

class FtpFileCommand(sublime_plugin.TextCommand): 
    def run(self, args): 
    global ftp_client # does it reference the variable of the outer scope? 
    self.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

class FtpFileEventListener(sublime_plugin.EventListener): 
    def run(self, args): 
    global ftp_client # same for this 
    self.ftp_client.quit() # 

Cả hai lớp này được cho là có một biến chung. Phương pháp hay nhất để chia sẻ các biến là gì?

Sửa dựa trên madjars trả lời:

FtpFileCommand.run được gọi là đầu tiên, instanciates ftp_client và hoạt động giống như một nét duyên dáng. FtpFileEventListener.run được gọi sau và có thể tham chiếu ftp_client hoàn hảo nhưng vẫn là None. Sử dụng từ khóa chung, nó có thêm biến làm thành viên vào self không?

+0

Để trả lời câu hỏi thứ hai trong chỉnh sửa của bạn: làm cho 'ftp_client' một thuộc tính thể hiện đánh bại mục đích sử dụng hình cầu. đối tượng 'FTP' mới sẽ được gán cho biến' ftp_client' sau khi khai báo nó là global trước tiên. sau đó, nó có thể được tham chiếu từ bất cứ đâu mà không cần khai báo nó là toàn cầu, ví dụ: 'ftp_client.quit()'. – ekhumoro

Trả lời

5

Đúng, đó chính xác là cách hoạt động của global.

Dường như với tôi bạn đang làm đúng, vì nó được thực hiện theo cách này trong một số mô-đun của thư viện chuẩn python (ví dụ: fileinput).

+1

Tôi đã chỉnh sửa câu hỏi dựa trên câu trả lời của bạn, vui lòng xem :) – fjdumont

+1

Sau khi thực hiện 'global ftp_client', bạn có thể truy cập nó bằng cách sử dụng' ftp_client'. Hãy cẩn thận, vì 'self.ftp_client' sẽ tham chiếu đến thuộc tính của cá thể, khác với' ftp_client' toàn cục. – madjar

+0

Cảm ơn bạn đã trả lời nhanh chóng. Thành thật mà nói, nghiên cứu các tài liệu cũng có thể giúp tôi. Lười biếng tôi ... – fjdumont

0

Bạn có thể thêm một hàm tạo cho mỗi lớp sau đó vượt qua ftp_client làm đối số không?

class FtpFileCommand(sublime_plugin.TextCommand): 
    ... 
    def __init__(self, ftp_client): 
     self.ftp_client = ftp_client 
    ... 

class FtpFileEventListener(sublime_plugin.EventListener): 
    ... 
    def __init__(self, ftp_client): 
     self.ftp_client = ftp_client 
    ... 
+0

Tôi e rằng hệ thống plugin có thể không chấp nhận pzarameters cho các plugin –

+0

Xavier Combelle: chính xác, cấu trúc được đưa ra trong bài đăng của tôi là cố định và tôi không được phép ghi đè lên các nhà xây dựng. – fjdumont

3

Nếu chỉ có một biến chia sẻ duy nhất thì toàn cầu là giải pháp đơn giản nhất. Nhưng lưu ý rằng một biến chỉ cần được khai báo với global khi nó được gán cho. Nếu biến toàn cục là một đối tượng, bạn có thể gọi các phương thức của nó, sửa đổi các thuộc tính của nó, vv mà không khai báo nó như là toàn cục trước tiên.

Một giải pháp thay thế cho việc sử dụng các biến toàn cầu là sử dụng các thuộc tính lớp được truy cập bằng cách sử dụng classmethods. Ví dụ:

class FtpFile(object): 
    _client = None 

    @classmethod 
    def client(cls): 
     return cls._client 

    @classmethod 
    def setClient(cls, client): 
     cls._client = client 

class FtpFileCommand(FtpFile, sublime_plugin.TextCommand): 
    def run(self, args): 
     client = self.client() 

class FtpFileEventListener(FtpFile, sublime_plugin.EventListener): 
    def run(self, args): 
     client = self.client() 
+0

Bây giờ đó là một giải pháp thông minh! Cảm ơn bạn đã làm rõ rằng 'global' chỉ được yêu cầu trong quá trình gán. Tôi chỉ + 1'd câu trả lời của bạn bởi vì tôi cảm thấy nghịch ngợm loại bỏ các giải pháp đánh dấu từ madjars câu trả lời ... – fjdumont

4

Trong mã này:

global ftp_client # does it reference the variable of the outer scope? 
self.ftp_client = ftplib.FTP('foo') 

bạn khai báo ftp_client như là một biến toàn cầu. Điều này có nghĩa là nó sống ở cấp mô-đun (ví dụ như các lớp của bạn).

Dòng thứ hai là sai. Bạn muốn gán cho biến toàn cầu nhưng thay vào đó bạn đặt một thuộc tính thể hiện cùng tên.

Nó nên là:

global ftp_client 
ftp_client = ftplib.FTP('foo') 

Nhưng hãy để tôi đề nghị một cách tiếp cận khác nhau. Một thực tế phổ biến là đưa những thứ như vậy vào trong lớp, vì nó được chia sẻ bởi tất cả các cá thể của lớp này.

class FtpFileCommand(sublime_plugin.TextCommand): 
    ftp_client = None 

    def run(self, args): 
    FtpFileCommand.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

Chú ý rằng phương pháp này không sử dụng self vì thế nó cũng có thể là một phương pháp lớp:

class FtpFileCommand(sublime_plugin.TextCommand): 
    ftp_client = None 

    @classmethod 
    def run(cls, args): 
    cls.ftp_client = ftplib.FTP('foo') 
    # login and stuff 

Bằng cách này bạn sẽ nhận được lớp như là đối số đầu tiên và bạn có thể sử dụng nó để truy cập máy khách FTP mà không cần sử dụng tên lớp.

0

Yak ... CẢM ƠN QUÝ VỊ NHƯ THẾ NÀY !!!

Bạn khai báo ftp_client làm biến toàn cục. Điều này có nghĩa là nó sống ở mức cấp độ mô-đun (ví dụ như các lớp của bạn).

Tôi đã gặp khó khăn khi cố gắng viết chương trình "đúng" nơi tôi đang sử dụng các lớp và chức năng và không thể gọi bất kỳ biến nào. Tôi nhận ra rằng toàn cầu sẽ làm cho nó có sẵn bên ngoài lớp học. Khi tôi đọc mà tôi nghĩ ... Nếu nó sống bên ngoài của lớp sau đó biến tôi cần phải lấy từ kịch bản py rằng tôi đang nhập khẩu mô-đun từ sẽ là:

module.variable 

Và sau đó trong mô-đun , tôi tuyên bố một biến toàn cục để gọi nó là từ kịch bản chính ... do đó, ví dụ ...

#Main Script main.py 
import moduleA 

print(moduleA.moduleA.variable) 


#ModuleA code moduleA.py 
import moduleB 

class classA(): 

    def functionA(): 

     global moduleA_variable 
     call.something.from.moduleB.classB.functionB() 
     moduleA_variable = moduleB.moduleB_variable 

ModuleB đang moduleB.py

class classB(): 

    def functionB(): 

     global moduleB_variable 
     moduleB_variable = retrieve.tacos() 

tôi hy vọng lời giải thích của tôi cũng giúp một ai đó. Tôi là một người mới bắt đầu với python và đấu tranh với điều này trong một thời gian. Trong trường hợp nó không rõ ràng ... Tôi đã có các mô-đun tùy chỉnh riêng biệt được tạo thành từ một vài tệp .py khác nhau. Main đang gọi moduleA và moduleA đang gọi moduleB. Tôi đã phải trả biến lên chuỗi thành kịch bản chính. Điểm tôi làm theo cách này, là giữ cho kịch bản chính sạch sẽ cho hầu hết các phần, và tự thiết lập để thực hiện các tác vụ lặp đi lặp lại mà không cần phải viết các trang của crap. Về cơ bản cố gắng sử dụng lại các chức năng thay vì viết một cuốn sách.

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