2012-05-01 31 views
15

Tôi khá mới để Python và có một câu hỏi liên quan đến lớp sau:Thực hành tốt nhất khi xác định các biến dụ

class Configuration: 
    def __init__(self): 
     parser = SafeConfigParser() 
     try: 
      if parser.read(CONFIG_FILE) is None: 
       raise IOError('Cannot open configuration file') 
     except IOError, error: 
      sys.exit(error) 
     else: 
      self.__parser = parser 
      self.fileName = CONFIG_FILE 

    def get_section(self): 
     p = self.__parser 
     result = [] 
     for s in p.sections(): 
      result.append('{0}'.format(s)) 
     return result 

    def get_info(self, config_section): 
     p = self.__parser 
     self.section = config_section 
     self.url = p.get(config_section, 'url') 
     self.imgexpr = p.get(config_section, 'imgexpr') 
     self.imgattr1 = p.get(config_section, 'imgattr1') 
     self.imgattr2 = p.get(config_section, 'imgattr2') 
     self.destination = p.get(config_section, 'destination') 
     self.createzip = p.get(config_section, 'createzip') 
     self.pagesnumber = p.get(config_section, 'pagesnumber') 

Is it OK để thêm các biến dụ hơn về chức năng khác, get_info trong ví dụ này, hoặc cách tốt nhất để xác định tất cả các biến mẫu trong hàm tạo? Nó không thể dẫn đến mã spaghetti nếu tôi định nghĩa các biến cá thể mới trên khắp nơi?

CHỈNH SỬA: Tôi đang sử dụng mã này với một hình ảnh scraper đơn giản. Qua get_section Tôi trả về tất cả các phần trong tệp cấu hình và sau đó lặp qua chúng để truy cập từng trang web mà tôi đang chụp ảnh. Đối với mỗi lần lặp, tôi thực hiện cuộc gọi đến get_section để nhận cài đặt cấu hình cho từng phần trong tệp cấu hình. Nếu bất cứ ai có thể đưa ra một cách tiếp cận khác, nó sẽ ổn thôi! Cảm ơn!

+0

http://stackoverflow.com/questions/2964230/python-how-should-i-make-instance-variables-available –

+0

Bản thân 'tự.__parser = None' nên được đặt ở đầu '__init __()'. Lý do là '__init __()' được gọi là một mentod đầu tiên của đối tượng * đã tồn tại *. Nếu trình phân tích cú pháp không đọc được tệp cấu hình và làm tăng ngoại lệ, ngoại lệ có thể do elswhere bị bắt (chương trình có thể không bị chấm dứt). Sau đó, đối tượng của lớp 'Configuration' vẫn còn tồn tại và sau đó' get_info() 'sẽ gây ra trường hợp * AttributeError: Configuration không có thuộc tính '__parser'. – pepr

+0

@pepr Tôi có nên đọc bạn trả lời cách tôi nên thêm 'self .__ parser = None' vào đầu' __init __. Py' hay bạn đề xuất chuyển khởi chạy phân tích cú pháp từ '__init __. Py' sang một hàm khác? – happygoat

Trả lời

11

Tôi chắc chắn sẽ công bố tất cả các biến dụ trong __init__. Để không làm như vậy dẫn đến tăng phức tạp và tiềm năng tác dụng phụ bất ngờ.

Để cung cấp quan điểm thay thế từ David Hall về quyền truy cập, điều này là từ Google Python style guide.

Access Control:

If an accessor function would be trivial you should use public variables instead of accessor functions to avoid the extra cost of function calls in Python. When more functionality is added you can use property to keep the syntax consistent

On the other hand, if access is more complex, or the cost of accessing the variable is significant, you should use function calls (following the Naming guidelines) such as get_foo() and set_foo(). If the past behavior allowed access through a property, do not bind the new accessor functions to the property. Any code still attempting to access the variable by the old method should break visibly so they are made aware of the change in complexity.

From PEP8

For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.

Note 1: Properties only work on new-style classes.

Note 2: Try to keep the functional behavior side-effect free, although side-effects such as caching are generally fine.

Note 3: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.

Python không phải là java/C#, và nó có ý tưởng rất mạnh mẽ về cách có thể nên xem xét và được viết. Nếu bạn đang mã hóa python nó làm cho tinh thần để làm cho nó trông và cảm thấy như python. Những người khác sẽ có thể hiểu mã của bạn dễ dàng hơn và bạn sẽ có thể hiểu được mã python khác tốt hơn.

+1

+1 vì tôi đồng ý với triết lý "Chúng tôi là tất cả người lớn ở đây" bằng Python. Thịt bò chính của tôi là với các lớp học mà bạn phải biết để gọi một hàm nhất định để đưa lớp đó vào trạng thái hợp lệ. –

+0

@DavidHall Có một cuộc nói chuyện thực sự thú vị trong những năm qua pycon "Ngừng viết các lớp", đây là chuỗi tin tức của hacker có một số thảo luận tốt về nó. Cả chuỗi và video đều đáng đọc. http://news.ycombinator.com/item?id=3717715 –

+0

Chúc mừng - Tôi sẽ xem xét. Như bạn có thể có thể nói với tôi là một nhà phát triển C++/C# người biết một số python để thảo luận như thế này là tuyệt vời để đọc. –

5

Tôi sẽ ưu tiên đặt tất cả các biến mẫu trong hàm khởi tạo để có các hàm như get_info() bắt buộc phải đặt lớp ở trạng thái hợp lệ.

Với các biến thể hiện công khai chỉ được thực hiện bằng các cuộc gọi đến các phương thức như get_info() bạn tạo một lớp mà một chút của một bãi chứa để sử dụng.

Nếu bạn lo lắng về việc có giá trị cấu hình nào đó không phải lúc nào cũng cần và tốn kém để tính toán (mà tôi đoán là tại sao bạn có get_info(), cho phép thực hiện trì hoãn), thì tôi sẽ xem xét tái cấu trúc tập hợp con đó của cấu hình vào lớp thứ hai hoặc giới thiệu properties hoặc các hàm trả về giá trị.

Với các thuộc tính hoặc nhận các chức năng phong cách, bạn khuyến khích người tiêu dùng của lớp trải qua một giao diện được xác định và cải thiện việc đóng gói .

Khi bạn đã đóng gói các biến cá thể, bạn cung cấp cho mình tùy chọn để thực hiện điều gì đó hơn là chỉ cần ném một ngoại lệ NameError - bạn có thể gọi tới số get_info() hoặc ném ngoại lệ tùy chỉnh.


1. Bạn không thể cung cấp 100% đóng gói với Python kể từ biến dụ tin biểu thị bằng dấu gạch dưới đôi hàng đầu chỉ tin theo quy ước

+0

Tôi không thấy lợi ích đối với các thuộc tính trên các biến mẫu công khai. Bạn có thể chỉ đơn giản là biến mọi thứ thành biến thể công khai và nếu sau này bạn cần nó để thực hiện một thứ gì đó khác ngoài việc thiết lập/nhận giá trị, bạn luôn có thể chuyển đổi nó thành thuộc tính. – interjay

+0

Điểm tốt - vấn đề chính của tôi với các biến cá thể công khai ở đây là khởi tạo chúng trong các hàm như get_info làm cho các lớp khó sử dụng không cần thiết. Nhưng bạn và Andrew Barret đã chuyển tôi để chỉnh sửa một câu trả lời của tôi, nhấn mạnh các nhà thầu. –

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