2013-05-16 33 views
5

Tại sao các hàm phải được khai báo bên ngoài lớp mà chúng được sử dụng trong Python?Lợi thế để xác định một số hàm trong lớp trong chương trình python

Ví dụ: following project on Github thực hiện điều này với các chức năng _hash, _task_from_taskline_tasklines_from_tasks. Định dạng giống như sau:

class UnknownPrefix(Exception): 
"""Raised when trying to use a prefix that does not match any tasks.""" 
def __init__(self, prefix): 
    super(UnknownPrefix, self).__init__() 
    self.prefix = prefix 


def _hash(text): 

    return hashlib.sha1(text).hexdigest() 

def _task_from_taskline(taskline): 
    """ 
    snipped out actual code 
    """ 
    return task 

def _tasklines_from_tasks(tasks): 
    """Parse a list of tasks into tasklines suitable for writing.""" 


    return tasklines 

Nhưng tôi nghĩ các hàm này có liên quan với lớp TaskDict.

Tại sao đưa chúng ra khỏi lớp học? Lợi thế của việc họ tuyên bố bên ngoài lớp học là gì?

+1

Bật nó xung quanh: Điều gì sẽ lợi thế là đặt chúng trong lớp để thay thế? –

+0

@MartijnPieters Encapsulation. –

+0

@GeorgeStocker: điều gì sẽ xảy ra nếu các hàm không mang về trạng thái cá thể? –

Trả lời

3

Stop Writing Classes PyCon nói không chính xác về chủ đề này nhưng bao gồm những gì tôi cảm thấy là bài học liên quan ở đây: về cơ bản, ý tưởng là các lớp học để tạo đối tượng. Tất cả các thuộc tính, các phương thức mẫu và các phương thức lớp nên thêm mục tiêu của việc tạo các đối tượng hoặc làm cho các đối tượng hoạt động. Các lớp không dành cho tổ chức mã (theo lý thuyết này) - đó là những mô-đun dành cho.

Đây là một chiến lược rất có ý kiến ​​và không phải ai cũng đồng ý với nó. Nhưng nếu bạn nghĩ về ví dụ của bạn trong bối cảnh này, rõ ràng lý do các hàm không phải là một phần của lớp là mặc dù các hàm được sử dụng bởi lớp, chúng không thực sự hoạt động trên bất kỳ đối tượng nào hoặc tạo thêm của bất kỳ đối tượng trực tiếp. Chúng chỉ là các hàm tiện ích không bị ràng buộc với bất kỳ lớp cụ thể nào và về mặt lý thuyết có thể được sử dụng ở nơi khác trong thư viện.

Vậy tại sao hoặc tại sao không đưa chúng vào lớp học? Nó tóm tắt cho dù bạn tin rằng các lớp học nên được sử dụng cho tổ chức mã hay không. Trong trường hợp này, tác giả dường như đã mua vào ý tưởng rằng đó là các mô-đun dành cho tổ chức mã, không phải các lớp.

0

Thông thường, khi quyết định vị trí đặt hàm, điều quan trọng là phải nhận ra những gì sẽ sử dụng các hàm. Nếu họ là nội bộ của lớp và sẽ không được sử dụng bởi các phần khác của chương trình của bạn, bạn nên đặt chúng vào lớp học. Nhưng nếu các phần khác rất có thể sẽ sử dụng chúng, chúng phải ở cấp mô-đun.

+0

có, tôi đã nghĩ rằng, tôi nghĩ rằng các chức năng thuộc về lớp học, và sẽ không được sử dụng bu những người khác ra khỏi lớp. Vì vậy, tôi nghi ngờ tại sao xác định ra khỏi lớp – poleworld

1

Nếu các hàm được xác định tất cả hoạt động trên dữ liệu trong đối tượng, sẽ chỉ có ý nghĩa để đóng gói các hàm cho cấp lớp. Ngoài ra, nhìn thấy lớp học là điều duy nhất gọi những chức năng đó, nó sẽ có ý nghĩa để đặt chúng trong lớp.

Ưu điểm duy nhất của việc đặt chúng bên ngoài lớp là nếu bạn có mã khác sẽ sử dụng các hàm này không liên quan đến chính lớp đó. Hoặc nếu bạn đang xây dựng một số chức năng trợ giúp sẽ được sử dụng bởi các mô-đun khác.

3
  1. Họ là dễ dàng hơn để nhập khẩu và có tên ngắn hơn so với hàm thành viên
  2. Thậm chí nếu bạn đặt chúng trong lớp, họ đang có lẽ sẽ trở thành một classmethod/staticmethod anyway.
  3. Mã Pythonic sử dụng kiểu gõ vịt; một phương thức có nghĩa là nó chỉ có thể được sử dụng với lớp đó, trong khi trên thực tế, mã có thể chung chung hơn.
  4. Tùy chọn cá nhân. Một số người thích tách biệt giữa "mô hình miền" và "logic nghiệp vụ".

Cuối cùng, đối với chương trình cụ thể này, thực sự không có lợi ích cũng như bất lợi khi thực hiện theo cách này.

+0

Vâng, với tôi. Tôi sẽ đặt chúng trong lớp và định nghĩa là staticmethod. – poleworld

1

chức năng có hiệu suất nhỏ lợi thế

>>> import timeit 
>>> timeit.Timer('foo()', 'def foo(): return 1').timeit() 
0.09944701194763184 
>>> timeit.Timer('A.foo()', ''' 
... class A(object): 
...  @staticmethod 
...  def foo(): 
...   return 1''').timeit() 
0.12048101425170898 
Các vấn đề liên quan