2010-11-17 7 views
133

Tôi đã có một số trợ giúp thực sự tuyệt vời về các câu hỏi trước đây của mình for detecting pawstoes within a paw, nhưng tất cả các giải pháp này chỉ hoạt động cho một phép đo tại một thời điểm.Làm cách nào để thiết kế một lớp bằng Python?

Now I have data mà bao gồm off:

  • khoảng 30 con chó;
  • mỗi số có 24 phép đo (được chia thành nhiều phân nhóm);
  • mỗi lần đo có ít nhất 4 địa chỉ liên lạc (một cho mỗi chân) và
    • từng tiếp xúc được chia thành 5 bộ phận và
    • có một số thông số như thời gian tiếp xúc, vị trí, tổng lực, vv

alt text

Rõ ràng gắn bó tất cả mọi thứ vào một đối tượng lớn sẽ không cắt nó, vì vậy tôi figured tôi cần ed để sử dụng các lớp thay vì hàng loạt chức năng hiện tại. Nhưng mặc dù tôi đã đọc chương Learning Python về lớp học, tôi thất bại trong việc áp dụng nó vào mã của riêng tôi (GitHub link)

Tôi cũng cảm thấy như đó là khá lạ để xử lý tất cả các dữ liệu mỗi lần tôi muốn ra khỏi một số thông tin. Một khi tôi biết vị trí của mỗi chân, không có lý do gì để tôi tính toán lại lần nữa. Hơn nữa, tôi muốn so sánh tất cả các bàn chân của cùng một con chó để xác định liên lạc thuộc về chân nào (trước/sau, trái/phải). Điều này sẽ trở thành một mớ hỗn độn nếu tôi tiếp tục chỉ sử dụng các chức năng.

Vì vậy, bây giờ tôi đang tìm lời khuyên về cách tạo các lớp sẽ cho phép tôi xử lý dữ liệu của mình (link to the zipped data of one dog) theo cách hợp lý.

+4

Bạn cũng có thể muốn xem xét sử dụng cơ sở dữ liệu (như sqlite: http://docs.python.org/library/sqlite3.html). Bạn có thể viết một chương trình đọc các tệp dữ liệu khổng lồ của bạn và chuyển đổi nó thành các hàng trong các bảng cơ sở dữ liệu. Sau đó, như là một giai đoạn thứ hai, bạn có thể viết các chương trình mà rút ra dữ liệu ra khỏi cơ sở dữ liệu để làm phân tích thêm. – unutbu

+0

[Ý bạn là một cái gì đó như tôi đã hỏi ở đây] (http://stackoverflow.com/questions/3738269/how-to-insert-arrays-into-a-database) @ubutbu? Tôi dự định sẽ làm điều đó, nhưng trước tiên tôi muốn có thể xử lý tất cả dữ liệu theo cách có tổ chức hơn –

Trả lời

423

Cách thiết kế lớp học.

  1. Viết ra các từ. Bạn bắt đầu làm điều này. Một số người không tự hỏi tại sao họ có vấn đề.

  2. Mở rộng tập hợp các từ thành các câu lệnh đơn giản về những gì các đối tượng này sẽ làm. Đó là để nói, viết ra các tính toán khác nhau bạn sẽ làm trên những điều này.Danh sách ngắn gồm 30 con chó, 24 số đo, 4 địa chỉ liên hệ và một vài "tham số" cho mỗi địa chỉ liên hệ thú vị, nhưng chỉ là một phần của câu chuyện. "Vị trí của mỗi chân" và "so sánh tất cả các chân của cùng một con chó để xác định liên hệ nào thuộc về chân nào" là bước tiếp theo trong thiết kế đối tượng.

  3. Gạch dưới danh từ. Nghiêm túc. Một số người tranh luận về giá trị của điều này, nhưng tôi thấy rằng đối với các nhà phát triển OO lần đầu nó giúp. Gạch chân các danh từ.

  4. Xem lại danh từ. Các danh từ chung chung như "tham số" và "đo lường" cần phải được thay thế bằng các danh từ cụ thể, cụ thể áp dụng cho vấn đề của bạn trong miền sự cố của bạn. Các chi tiết cụ thể giúp làm rõ vấn đề. Generics chỉ đơn giản là chi tiết elide.

  5. Đối với mỗi danh từ ("liên hệ", "chân", "chó", v.v.) ghi lại các thuộc tính của danh từ đó và các hành động mà đối tượng đó tham gia. Đừng cắt ngắn điều này. Mỗi thuộc tính. Ví dụ: "Tập dữ liệu chứa 30 chú chó" là quan trọng.

  6. Đối với mỗi thuộc tính, xác định xem đây có phải là mối quan hệ với danh từ được xác định hay một số loại dữ liệu "nguyên thủy" hoặc "nguyên tử" khác như chuỗi hoặc phao hay không thể làm được.

  7. Đối với mỗi hành động hoặc hoạt động, bạn phải xác định danh từ nào có trách nhiệm và danh từ nào chỉ tham gia. Đó là một câu hỏi về "sự biến đổi". Một số đối tượng được cập nhật, một số khác thì không. Các đối tượng có thể thay đổi phải sở hữu toàn bộ trách nhiệm đối với các đột biến của chúng.

  8. Tại thời điểm này, bạn có thể bắt đầu biến danh từ thành định nghĩa lớp. Một số danh từ tập thể là danh sách, từ điển, bộ dữ liệu, tập hợp hoặc tên đã đặt tên và bạn không cần phải làm nhiều việc. Các lớp khác phức tạp hơn, vì dữ liệu có nguồn gốc phức tạp hoặc do một số cập nhật/đột biến được thực hiện.

Đừng quên kiểm tra từng lớp trong sự cô lập bằng cách sử dụng không nhất thiết.

Ngoài ra, không có luật nào nói rằng các lớp học phải có thể thay đổi. Trong trường hợp của bạn, ví dụ, bạn hầu như không có dữ liệu có thể thay đổi. Những gì bạn có được bắt nguồn từ dữ liệu, được tạo ra bởi các hàm chuyển đổi từ tập dữ liệu nguồn.

3

Toàn bộ ý tưởng của thiết kế OO là làm cho bản đồ mã của bạn để vấn đề của bạn, vì vậy khi, ví dụ, bạn muốn bước chân đầu tiên của một con chó, bạn làm như sau:

dog.footstep(0) 

Bây giờ, nó có thể là trường hợp của bạn, bạn cần phải đọc trong tập tin dữ liệu thô của bạn và tính toán các vị trí bước chân. Tất cả điều này có thể được ẩn trong hàm footstep() để nó chỉ xảy ra một lần. Một cái gì đó như:

class Dog: 
    def __init__(self): 
    self._footsteps=None 
    def footstep(self,n): 
    if not self._footsteps: 
     self.readInFootsteps(...) 
    return self._footsteps[n] 

[Đây hiện là một loại mẫu đệm. Lần đầu tiên nó đi và đọc dữ liệu bước chân, lần sau nó chỉ nhận được dữ liệu từ self._footsteps.]

Nhưng có, nhận được quyền thiết kế OO có thể phức tạp. Hãy suy nghĩ thêm về những điều bạn muốn làm cho dữ liệu của bạn, và điều đó sẽ thông báo những phương pháp bạn sẽ cần để áp dụng cho các lớp học.

22

Các lời khuyên sau đây (tương tự như @ lời khuyên S. Lott của) là từ cuốn sách, Beginning Python: From Novice to Professional

  1. Viết ra một mô tả về vấn đề của bạn (những gì các vấn đề nên làm gì?). Gạch dưới tất cả các danh từ, động từ và tính từ.

  2. Đi qua danh từ, tìm kiếm các lớp tiềm năng.

  3. Đi qua động từ, tìm kiếm các phương pháp tiềm năng.

  4. Đi qua các tính từ, tìm kiếm tiềm năng thuộc tính

  5. Phân bổ các phương pháp và các thuộc tính đến các lớp học của bạn

Để tinh chỉnh các lớp học, cuốn sách cũng khuyên chúng ta có thể làm như sau:

  1. Viết xuống (hoặc ước mơ) một tập hợp các trường hợp sử dụng --- các tình huống về cách chương trình của bạn có thể được sử dụng. Cố gắng bao gồm tất cả các chức năng.

  2. Suy nghĩ từng bước sử dụng từng bước, đảm bảo rằng mọi thứ chúng tôi cần đều được đề cập đến.

13

Tôi thích cách tiếp cận TDD ... Vì vậy, bắt đầu bằng cách viết kiểm tra cho những gì bạn muốn hành vi. Và viết mã đi qua. Tại thời điểm này, đừng lo lắng quá nhiều về thiết kế, chỉ cần có bộ phần mềm thử nghiệm và phần mềm đi qua. Đừng lo lắng nếu bạn kết thúc với một lớp xấu lớn duy nhất, với các phương pháp phức tạp.

Đôi khi, trong quá trình ban đầu này, bạn sẽ tìm thấy một hành vi khó kiểm tra và cần được phân tích, chỉ để kiểm tra. Đây có thể là một gợi ý rằng một lớp riêng biệt được bảo đảm.

Sau đó, phần thú vị ... tái cấu trúc. Sau khi bạn có phần mềm làm việc, bạn có thể thấy các phần phức tạp. Thường thì các túi hành vi nhỏ sẽ trở nên rõ ràng, gợi ý một lớp mới, nhưng nếu không, chỉ cần tìm cách để đơn giản hóa mã. Trích xuất đối tượng dịch vụ và đối tượng giá trị. Đơn giản hóa các phương pháp của bạn.

Nếu bạn đang sử dụng git đúng cách (bạn đang sử dụng git, phải không?), Bạn có thể nhanh chóng thử nghiệm với một số phân hủy cụ thể trong quá trình tái cấu trúc, rồi từ bỏ nó và hoàn nguyên trở lại nếu nó không đơn giản hóa mọi thứ .

Bằng cách viết mã làm việc thử nghiệm trước tiên, bạn sẽ có được thông tin chi tiết thân mật về miền vấn đề mà bạn không thể dễ dàng có được với phương pháp tiếp cận thiết kế đầu tiên. Viết bài kiểm tra và mã đẩy bạn qua đó "nơi nào tôi bắt đầu" tê liệt.

+1

Tôi cũng đồng ý với câu trả lời này, mặc dù phá vỡ vấn đề và xác định các lớp có thể (tức là làm " chỉ cần đủ "kiến trúc phần mềm" có thể rất hữu ích nếu vấn đề sẽ được làm việc song song bởi một số thành viên trong nhóm. –

2

Viết ra danh từ, động từ, tính từ của bạn là một cách tiếp cận tuyệt vời, nhưng tôi thích nghĩ về thiết kế lớp học khi đặt câu hỏi dữ liệu nào cần được ẩn?

Hãy tưởng tượng bạn có một đối tượng Query và một đối tượng Database:

Đối tượng Query sẽ giúp bạn tạo và lưu trữ một truy vấn - cửa hàng, là chìa khóa ở đây, như một chức năng có thể giúp bạn tạo một giống như một cách dễ dàng . Có thể bạn có thể ở lại: Query().select('Country').from_table('User').where('Country == "Brazil"'). Nó không quan trọng chính xác cú pháp - đó là công việc của bạn! - chìa khóa là đối tượng đang giúp bạn ẩn nội dung nào đó, trong trường hợp này là dữ liệu cần thiết để lưu trữ và xuất một truy vấn. Sức mạnh của đối tượng xuất phát từ cú pháp của việc sử dụng nó (trong trường hợp này là một số chuỗi thông minh) và không cần biết những gì nó lưu trữ để làm cho nó hoạt động. Nếu được thực hiện ngay, đối tượng Query có thể xuất các truy vấn cho nhiều cơ sở dữ liệu sau đó. Nó trong nội bộ sẽ lưu trữ một định dạng cụ thể nhưng có thể dễ dàng chuyển đổi sang các định dạng khác khi xuất (Postgres, MySQL, MongoDB).

Bây giờ, hãy nghĩ qua đối tượng Database. Điều này ẩn và lưu trữ những gì?Rõ ràng nó không thể lưu trữ toàn bộ nội dung của cơ sở dữ liệu, vì đó là lý do tại sao chúng tôi có một cơ sở dữ liệu! Vậy vấn đề là gì? Mục tiêu là để ẩn cách cơ sở dữ liệu hoạt động từ những người sử dụng đối tượng Database. Các lớp học tốt sẽ đơn giản hóa lý luận khi thao tác trạng thái bên trong. Đối với đối tượng Database này, bạn có thể ẩn cách các cuộc gọi mạng hoạt động hoặc truy vấn hàng loạt hoặc cập nhật hoặc cung cấp lớp lưu trong bộ nhớ cache.

Vấn đề ở đây là đối tượng Database là HUGE. Nó đại diện cho cách truy cập một cơ sở dữ liệu, vì vậy dưới sự che chở nó có thể làm bất cứ điều gì và mọi thứ. Rõ ràng mạng, bộ nhớ đệm, và xử lý theo lô là khá khó để đối phó với tùy thuộc vào hệ thống của bạn, do đó, ẩn chúng đi sẽ rất hữu ích. Tuy nhiên, như nhiều người sẽ lưu ý, một cơ sở dữ liệu cực kỳ phức tạp, và hơn nữa từ các cuộc gọi DB thô bạn nhận được, thì càng khó điều chỉnh hiệu suất và hiểu cách mọi thứ hoạt động.

Đây là sự cân bằng cơ bản của OOP. Nếu bạn chọn sự trừu tượng đúng, nó làm cho việc mã hóa đơn giản hơn (String, Array, Dictionary), nếu bạn chọn một sự trừu tượng quá lớn (Database, EmailManager, NetworkingManager), nó có thể trở nên quá phức tạp để thực sự hiểu nó hoạt động như thế nào chờ đợi. Mục tiêu là để ẩn sự phức tạp, nhưng một số phức tạp là cần thiết. Một nguyên tắc nhỏ là bắt đầu tránh các đối tượng Manager và thay vào đó tạo các lớp giống như structs - tất cả những gì họ làm là giữ dữ liệu, với một số phương pháp trợ giúp để tạo/thao tác dữ liệu để giúp cuộc sống của bạn dễ dàng hơn. Ví dụ: trong trường hợp EmailManager, hãy bắt đầu bằng hàm có tên sendEmail có đối tượng Email. Đây là một điểm khởi đầu đơn giản và mã rất dễ hiểu.

Ví dụ của bạn, hãy suy nghĩ về dữ liệu nào cần phải ở bên nhau để tính toán những gì bạn đang tìm kiếm. Ví dụ, nếu bạn muốn biết con vật đang đi xa bao xa, bạn có thể có các lớp học AnimalStepAnimalTrip (bộ sưu tập của AnimalSteps). Bây giờ mỗi chuyến đi đều có tất cả các dữ liệu của Bước, sau đó nó sẽ có thể tìm hiểu về nó, có lẽ AnimalTrip.calculateDistance() có ý nghĩa.

2

Sau khi lướt qua mã được liên kết, có vẻ như với tôi rằng bạn nên tắt không thiết kế lớp Dog vào thời điểm này. Thay vào đó, bạn nên sử dụng Pandasdataframes. Một khung dữ liệu là một bảng có các cột. Bạn dataframe sẽ có các cột như: dog_id, contact_part, contact_time, contact_location vv Pandas sử dụng mảng NumPy đằng sau hậu trường, và nó có nhiều phương pháp thuận tiện cho bạn:

  • Chọn một con chó bằng cách ví dụ : my_measurements['dog_id']=='Charly'
  • lưu dữ liệu: my_measurements.save('filename.pickle')
  • Cân nhắc sử dụng pandas.read_csv() thay vì đọc thủ công tệp văn bản.