2012-04-30 30 views
21

Tôi đã đọc một lần (tôi nghĩ trên một trang từ Microsoft) rằng đó là một cách hay để sử dụng các lớp tĩnh, khi bạn KHÔNG CẦN hai hoặc nhiều phiên bản của một lớp.Các lớp tĩnh trong Python

Tôi đang viết chương trình bằng Python. Đó có phải là một phong cách xấu, nếu tôi sử dụng @classmethod cho mọi phương thức của một lớp học?

Trả lời

6

Trong kinh nghiệm của tôi, tạo ra một lớp học là một giải pháp rất tốt vì một số lý do. Một là bạn sử dụng lớp học như một lớp 'bình thường' (đặc biệt là tạo ra nhiều hơn một ví dụ) thường xuyên hơn bạn nghĩ. Nó cũng là một lựa chọn phong cách hợp lý để gắn bó với các lớp học cho everthing; điều này có thể giúp những người khác đọc/duy trì mã của bạn dễ dàng hơn, đặc biệt nếu họ rất OO - họ sẽ cảm thấy thoải mái với các lớp học. Như đã nói trong các bài trả lời khác, nó cũng hợp lý để chỉ sử dụng các hàm 'trần' để thực hiện. Bạn có thể bắt đầu với một lớp học và làm cho nó một mẫu đơn/Borg (rất nhiều ví dụ nếu bạn googlefor này); nó mang lại cho bạn sự linh hoạt để (lại) sử dụng lớp học để đáp ứng các nhu cầu khác. Tôi sẽ khuyên bạn nên chống lại cách tiếp cận 'lớp tĩnh' như là không thông thường và không phải Pythonic, mà làm cho nó khó đọc và duy trì.

+7

Hầu hết câu trả lời của bạn, ngoại lệ chính là câu thứ hai và câu cuối cùng, chỉ là đáng tranh cãi (và tôi có xu hướng không đồng ý) và bên cạnh vấn đề. Tôi muốn nói cắt tất cả các fluff về cách tuyệt vời các lớp học sẽ cải thiện nó, bạn nghĩ gì? – delnan

+0

Tôi đều đồng ý và không đồng ý với câu trả lời này cùng một lúc. Vì vậy, tôi không thể quyết định có nên nhấn nút lên hay xuống. Dù sao tôi đồng ý về việc làm cho các đối tượng làm cho mã dễ đọc và duy trì. Tôi không đồng ý về việc sử dụng mẫu đơn/borg http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Singleton.html. Nó không phải là một mô hình xấu; tuy nhiên, việc sử dụng các phương thức tĩnh với các biến lớp là cách dễ dàng hơn để duy trì và đọc trong một dự án mã cực kỳ phức tạp. Có điều này có thể không chính xác về mặt kỹ thuật nhưng các lập trình viên cấp cơ sở sẽ cảm ơn bạn. –

27

Thông thường, việc sử dụng như thế này được thực hiện tốt hơn bằng cách chỉ sử dụng các hàm trong mô-đun, không có lớp nào cả.

+8

+1. Tuyệt đối không cần phải tạo một lớp bằng Python nếu bạn không đóng gói bất kỳ dữ liệu nào. –

+1

Đôi khi tôi bắt đầu chỉ với các hàm nhưng sau đó nhận ra rằng, bởi vì tôi thích viết các hàm nhỏ, đôi khi tôi phải chuyển cùng một tham số giữa 3 hoặc 4 trong số chúng, tại thời điểm đó tôi bắt đầu muốn đóng gói tham số đó. Tôi vẫn chưa giải quyết được câu hỏi hóc búa này. Suy nghĩ? – Leonid

+0

@Leonid Tôi cho rằng nếu các chức năng của bạn độc lập nhưng vẫn muốn các tham số giữa chúng, chỉ cần vượt qua các tham số đó. Nếu bạn thấy bạn có rất nhiều cuộc gọi với cùng một tập hợp các paramteres, có thể tạo ra một 'namedtuple' hoặc một cái gì đó để vượt qua. Lưu trữ những thứ trong một lớp học chỉ để tránh đi qua chúng xung quanh thường là một ý tưởng tồi anyway - nó có thể dẫn đến các vấn đề. –

13

Đó là phong cách khủng khiếp, trừ khi bạn thực sự cần truy cập vào lớp học.

Phương thức tĩnh [...] không chuyển thành một lớp học Python. Oh chắc chắn, nó kết quả trong nhiều hay ít hiệu ứng tương tự, nhưng mục tiêu của một classmethod thực sự là để làm một cái gì đó mà thường thậm chí không thể [...] (giống như kế thừa một non-default constructor). Bản dịch thành ngữ của một phương thức tĩnh [...] thường là một hàm mức module, không phải là một classmethod hoặc staticmethod.

source

6

Có một vài phương pháp bạn có thể mất cho việc này. Như những người khác đã đề cập, bạn chỉ có thể sử dụng chức năng cấp mô-đun. Trong trường hợp này, chính mô đun là không gian tên chứa chúng lại với nhau. Một tùy chọn khác, có thể hữu ích nếu bạn cần theo dõi trạng thái, là định nghĩa một lớp với các phương thức bình thường (tự lấy), và sau đó xác định một cá thể chung duy nhất của nó và sao chép các phương thức cá thể của nó vào không gian tên mô-đun. Đây là phương pháp được thực hiện bởi mô-đun "ngẫu nhiên" của thư viện chuẩn - hãy xem lib/python2.5/random.py trong thư mục python của bạn. Ở phía dưới, nó có một cái gì đó như thế này:

# Create one instance, seeded from current time, and export its methods 
# as module-level functions. [...] 
_inst = Random() 
seed = _inst.seed 
random = _inst.random 
uniform = _inst.uniform 
... 

Hoặc bạn có thể đi tiếp cận cơ bản bạn mô tả (mặc dù tôi sẽ khuyên bạn sử dụng @staticmethod hơn @classmethod trong hầu hết các trường hợp).

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