2009-05-03 36 views
19

Tôi muốn tái cấu trúc hàm Python lớn thành các hàm nhỏ hơn. Ví dụ: hãy xem xét đoạn mã sau đây:Python: tránh cảnh báo pylint về quá nhiều đối số

x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 

Tất nhiên, đây là một ví dụ nhỏ. Trong thực tế, mã này phức tạp hơn. Quan điểm của tôi là nó chứa nhiều biến phạm vi địa phương sẽ phải được chuyển đến hàm được trích xuất, có thể trông giống như:

def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9): 
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    return x 

Vấn đề là pylint sẽ kích hoạt cảnh báo về quá nhiều đối số. tôi có thể tránh được những cảnh báo bằng cách làm một cái gì đó như:

def mysum(d): 
    x1 = d['x1'] 
    x2 = d['x2'] 
    ... 
    x9 = d['x9'] 
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    return x 

def mybigfunction(): 
    ... 
    d = {} 
    d['x1'] = x1 
    ... 
    d['x9'] = x9 
    x = mysum(d) 

nhưng cách tiếp cận này Loos xấu xí với tôi, nó đòi hỏi viết nhiều mã mà thậm chí còn không cần thiết.

Có cách nào tốt hơn để làm điều đó không?

+1

Tôi tin rằng mysum() có thể được đơn giản hóa thành: 'trả lại tổng (d.values ​​())' hoặc ít nhất là 'tổng trở lại ([d [foo] cho foo trong (' x1 ',' x2 ', .. ., 'x9')]) '. Tôi có quá hài lòng về danh sách không? – MatrixFrog

+1

Các mysum() chỉ là một trừu tượng, trong các kịch bản thực sự mã cần được trích xuất phức tạp hơn nhiều. Quan điểm của tôi là phải chuyển nhiều biến cho hàm được trích xuất và tránh cảnh báo pylint nếu có thể (không làm cho pylint rõ ràng chỉ bỏ qua cảnh báo đó). – Anonymous

Trả lời

5

Đơn giản hóa hoặc phá vỡ chức năng sao cho nó không yêu cầu chín đối số (hoặc bỏ qua pylint, nhưng dodges giống như những cái bạn đang đề xuất đánh bại mục đích của một công cụ lint).

EDIT: nếu đó là một biện pháp tạm thời, vô hiệu hóa các cảnh báo cho các chức năng cụ thể trong câu hỏi bằng một lời nhận xét như mô tả ở đây: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html

Sau đó, bạn có thể grep cho tất cả những lời cảnh báo người tàn tật.

+0

Mục tiêu của tôi là phá vỡ hàm lớn trước tiên. Sau đó, tôi có thể tiến hành phá vỡ các phần nhỏ hơn nữa. Nhưng tôi muốn tránh cảnh báo pylint cụ thể này trong quá trình tái cấu trúc, nếu điều này là có thể. – Anonymous

12

Bạn có thể thử sử dụng tính năng Python's variable arguments:

def myfunction(*args): 
    for x in args: 
     # Do stuff with specific argument here 
+1

Giống như sử dụng danh sách, xem bên dưới. – Anonymous

6

Có lẽ bạn có thể biến một số các đối số vào các biến thành viên. Nếu bạn cần nhiều trạng thái, một lớp học có vẻ như là một ý tưởng hay đối với tôi.

+0

Không hoạt động nếu tôi cần cấu trúc lại một phương thức lớp và các biến được truyền là cục bộ cho phương thức được cấu trúc lại lớn và không được sử dụng trong toàn bộ lớp. – Anonymous

+3

Không, nhưng nếu bạn trích xuất một loại mới thay vào đó bạn có thể biến một số trạng thái thành các biến thành viên. –

0

Python có một số công cụ lập trình chức năng tốt đẹp có khả năng phù hợp với nhu cầu của bạn. Hãy xem lambda functionsmap. Ngoài ra, bạn đang sử dụng dicts khi nó có vẻ như bạn muốn được phục vụ tốt hơn với danh sách. Đối với ví dụ đơn giản bạn đã cung cấp, hãy thử thành ngữ này. Lưu ý đồ đó sẽ là tốt hơn và nhanh hơn nhưng có thể không phù hợp với nhu cầu của bạn:

def mysum(d): 
    s = 0 
    for x in d: 
     s += x 
    return s 

def mybigfunction(): 
    d = (x1, x2, x3, x4, x5, x6, x7, x8, x9) 
    return mysum(d) 

Bạn nói có rất nhiều biến cục bộ, nhưng thẳng thắn mà nói nếu bạn đang làm việc với các danh sách (hoặc các tuple), bạn nên sử dụng danh sách và đưa ra tất cả các biến cục bộ đó trong thời gian dài.

+0

Tôi không thể sử dụng danh sách. Trong ví dụ tầm thường của tôi, các biến được truyền của tôi đóng vai trò giống nhau. Nhưng trong một kịch bản phức tạp, các biến có ý nghĩa khác nhau, do đó thay thế tên của chúng (mang ý nghĩa logic) với các mục danh sách được truy cập theo chỉ mục sẽ phá hủy hoàn toàn khả năng đọc của mã. – Anonymous

+2

Bạn sẽ phải sử dụng lệnh dict sau đó. Điều đó nói rằng, bạn sẽ không thể làm sạch nhiều thứ trừ khi bạn thay đổi một số yêu cầu của bạn. Hoặc bạn có thể định nghĩa một lớp cho tất cả các công cụ này và sau đó đẩy logic vào các phương thức lớp khác nhau. có lẽ sạch hơn một cây lớn nếu sau đó dựa trên một dict, ít nhất! – easel

55

Thứ nhất, một trong những Perlis's epigrams:

"Nếu bạn có một thủ tục với 10 thông số, bạn có thể bỏ lỡ một số."

Một số trong 10 đối số có lẽ là có liên quan. Nhóm chúng thành một đối tượng và thay vào đó.

Làm một ví dụ lên, bởi vì không có đủ thông tin trong câu hỏi để trả lời trực tiếp:

class PersonInfo(object): 
    def __init__(self, name, age, iq): 
    self.name = name 
    self.age = age 
    self.iq = iq 

Sau đó, chức năng 10 Lập luận của bạn:

def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7): 
    ... 

trở thành:

def f(personinfo, x1, x2, x3, x4, x5, x6, x7): 
    ... 

và người gọi thay đổi thành:

personinfo = PersonInfo(name, age, iq) 
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7) 
+3

Tôi thích câu trả lời này vì nó chỉ ra cách suy nghĩ về vấn đề này! –

24

Bạn có muốn có cách tốt hơn để chuyển đối số hay chỉ là cách để ngăn chặn pylint gây khó khăn cho bạn? Nếu sau này, tôi dường như nhớ lại rằng bạn có thể ngăn chặn sự dai dẳng bằng cách đặt pylint comments -controlling trong mã của bạn dọc theo dòng:

#pylint: disable-msg=R0913 

hay:

#pylint: disable-msg=too-many-arguments 

nhớ để biến chúng trở lại càng sớm càng tốt.

Theo tôi, không có gì vốn sai với đi qua rất nhiều tranh cãi và giải pháp ủng hộ gói tất cả chúng lên trong một số lập luận chứa không thực sự giải quyết bất kỳ vấn đề, trừ dừng pylint từ cằn nhằn bạn :-).

Nếu bạn cần vượt qua hai mươi đối số, sau đó vượt qua chúng. Nó có thể là điều này là cần thiết bởi vì chức năng của bạn đang làm quá nhiều và tái bao thanh toán có thể hỗ trợ ở đó, và đó là một cái gì đó bạn nên xem xét. Nhưng đó không phải là quyết định chúng tôi thực sự có thể thực hiện trừ khi chúng tôi thấy mã 'thực' là gì.

+3

Câu trả lời này khuyến khích thói quen thực sự xấu - đọc bây giờ trong năm 2015. 1) vô hiệu hóa kiểm tra với số lượng của họ - các phiên bản pylint hiện đại hỗ trợ mô tả mang tính biểu tượng, nhiều hơn nữa để giảng giải 2) vô hiệu hóa một cái gì đó nên cũng đã bình luận với một lời giải thích của lý do tại sao nó bị vô hiệu hóa 3) chỉ nên có một chỉ thị trên mỗi dòng, được cân bằng bằng cách bật lại tương ứng 4) Thông thường giá trị không có điểm. Mã xung đột với các giới hạn đó có thể không đọc được/không thể duy trì. 5) Thay vì truyền một loạt các tham số, tốt hơn hết là sử dụng từ điển hoặc một bộ dữ liệu có tên. –

+3

Igor, đó là lý do tại sao tôi nói "dọc theo dòng". Bằng mọi cách, hãy sử dụng các ký hiệu thay vì số, hoặc một dòng trên mỗi dòng hoặc nhận xét lý do tại sao hoặc kích hoạt lại (mặc dù bạn nên xem xét điều đó có nghĩa là nếu nó bị vô hiệu hóa trước đó - tốt hơn là phương pháp lưu/tắt/khôi phục).Không ai trong số đó thay đổi tiện ích của câu trả lời chính nó, đó là để nói với pylint để ngăn chặn cảnh báo về một vấn đề người dùng _knows_ họ không muốn nghe về (và chấp nhận hậu quả). – paxdiablo

+2

Người dùng có nhiều khả năng thường tự mâu thuẫn: pylint không phải là công cụ rõ ràng nhất theo nghĩa đó, nhưng các cảnh báo được đưa ra thường có phạm vi tiếp cận sâu hơn nhiều so với thông điệp dường như đưa ra. Vì vậy, người dùng có thể * nghĩ * để biết hậu quả được chấp nhận, nhưng (s) anh ta không hoàn toàn đánh giá cao các tác động. –

14

Bạn có thể dễ dàng thay đổi số lượng đối số tối đa cho phép trong pylint. Chỉ cần mở tập tin của bạn pylintrc (tạo ra nó nếu bạn chưa có) và thay đổi:

max-args = 5

tới:

max-args = 6 # hoặc bất kỳ giá trị mà bộ quần áo bạn

Từ pylint của manual

Xác định tất cả các tùy chọn phù hợp cho thiết lập của bạn và tiêu chuẩn mã hóa có thể TEDI ous, do đó, có thể sử dụng tệp rc để chỉ định giá trị mặc định . Pylint tìm kiếm/etc/pylintrc và ~/.pylintrc. Tùy chọn --generate-rcfile sẽ tạo ra tệp cấu hình đã nhận xét theo cấu hình hiện tại trên đầu ra và thoát ra tiêu chuẩn tiêu chuẩn. Bạn có thể đặt các tùy chọn khác trước tùy chọn này để sử dụng chúng trong cấu hình hoặc bắt đầu với các giá trị mặc định và điều chỉnh cấu hình .

3

Bình luận về bài trả lời paxdiablo của - như tôi không có đủ uy tín để bình luận có trực tiếp: -/

tôi không thích đề cập đến số lượng, tên sybolic là nhiều hơn nữa ý nghĩa và tránh phải thêm một nhận xét có thể trở nên lỗi thời theo thời gian.

Vì vậy, tôi thà làm:

#pylint: disable-msg=too-many-arguments 

Và tôi cũng muốn giới thiệu để không để lại nó treo lủng lẳng ở đó: nó sẽ ở lại hoạt động cho đến khi kết thúc tập tin hoặc nó bị vô hiệu hóa, nào đến trước.

Vì vậy, tốt hơn thực hiện:

#pylint: disable-msg=too-many-arguments 
code_which_would_trigger_the_msg 
#pylint: enable-msg=too-many-arguments  

Tôi cũng muốn giới thiệu bật/tắt một đơn cảnh báo/báo lỗi trên mỗi dòng.

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