Tại sao pycharm đề xuất thay đổi phương thức thành tĩnh


153

Bản phát hành pycharm mới (phiên bản cộng đồng 3.1.3) đề xuất chuyển đổi các phương thức không hoạt động với trạng thái của đối tượng hiện tại thành tĩnh.

nhập mô tả hình ảnh ở đây

Lý do thực tế cho điều đó là gì? Một số loại hiệu suất vi mô (-or-memory) -optimization?


3
Bạn đã bấm "thêm ..."? Bạn có tham khảo selfbất cứ nơi nào trong phương pháp? (Nếu câu hỏi thực sự là "tại sao các nhà thiết kế của PyCharm lại thiết kế theo cách này ... bạn sẽ phải hỏi họ chứ không phải SO ...)
Wooble

7
@Wooble: có return 1một cách thực hiện một dòng duy nhất của phương thức. "Khác" không chứa bất cứ điều gì hữu ích
zerkms

Câu trả lời:


188

PyCharm "nghĩ" rằng bạn có thể muốn có một phương thức tĩnh, nhưng bạn đã quên khai báo nó là tĩnh (sử dụng trình @staticmethodtrang trí).

PyCharm đề xuất điều này bởi vì phương thức này không sử dụng self trong phần thân của nó và do đó không thực sự thay đổi thể hiện của lớp . Do đó phương thức có thể là tĩnh, tức là có thể gọi được mà không cần truyền một thể hiện của lớp hoặc thậm chí không tạo ra một thể hiện của lớp.


4
Vì vậy, nhiều người đã trả lời với phản ứng hương vị này. Mặc dù vậy, tôi sẽ nói thêm, nếu bạn biết chắc chắn đó sẽ không phải là một phương thức tĩnh, thì hãy bao gồm một "throw NotImcellenceedError" trong khi bạn chắc chắn rằng bạn không sử dụng nó mà không hoàn thành nó.
Richard Green

1
Có thể có trường hợp cảnh báo của PyCharm không chính đáng ở chỗ chúng tôi không muốn một phương thức tĩnh cũng như không thay đổi trạng thái. Mặt khác, nếu phương thức này chưa được thực hiện, có vẻ như luôn luôn là một ý tưởng tốt để nâng cao a NotImplementedError.
jolvi

3
Tôi có trường hợp việc triển khai mặc định của tôi trả về một hằng số, nhưng các lớp con của tôi được phép trả về một giá trị tùy thuộc vào self. Trong trường hợp này, cảnh báo là không thể bỏ qua, và tôi đánh dấu nó bằng # noinspection PyMethodMayBeStatic. Thật đáng tiếc khi IntelliJ IDEA không cung cấp thêm nhận xét vô hiệu hóa này trong các menu ngữ cảnh cho cảnh báo này.
Alfe

Tôi đề nghị thay đổi mức độ nghiêm trọng của kiểm tra PyCharm này từ "Cảnh báo" thành "Không tô sáng, chỉ sửa chữa" trong tùy chọn của PyCharm. (Nó tạo ra nhiều kết quả dương tính giả đối với tôi.)
maciek

50

Đồng ý với @jolvi, @ArundasR và những người khác, cảnh báo xảy ra đối với chức năng thành viên không sử dụng self.

Nếu bạn chắc chắn rằng PyCharm sai, thì chức năng đó không phải là một @staticmethodvà nếu bạn coi trọng các cảnh báo bằng 0, bạn có thể khiến điều này biến mất theo hai cách khác nhau:

Giải pháp số 1

def bar(self):
    self.is_not_used()
    doing_something_without_self()

def is_not_used(self):
    pass

Giải pháp số 2 [Cảm ơn @ DavidPärsson ]

# noinspection PyMethodMayBeStatic
def bar(self):
    doing_something_without_self()

Ứng dụng tôi có cho việc này (lý do tôi không thể sử dụng @staticmethod) là trong việc tạo một bảng các hàm xử lý để đáp ứng với trường con giao thức. Tất cả các trình xử lý phải là cùng một dạng của khóa học (tĩnh hoặc không tĩnh). Nhưng một số đã không xảy ra để làm bất cứ điều gì với ví dụ. Nếu tôi tạo các tĩnh đó, tôi sẽ nhận được đối tượng "TypeError: 'staticmethod' không thể gọi được".

Để hỗ trợ cho bản dựng của OP, đề nghị bạn thêm tĩnh bất cứ khi nào bạn có thể, đi ngược lại với nguyên tắc là làm cho mã ít bị hạn chế hơn về sau, hơn là làm cho nó trở nên tĩnh hơn - làm cho phương thức tĩnh trở nên hạn chế hơn, vì bạn có thể gọi class.f () thay vì instance.f ().

Đoán xem tại sao cảnh báo này tồn tại:

  • quảng cáo tĩnh . Nó làm cho các nhà phát triển nhận thức được một cái gì đó họ có thể có ý định.
  • Như @ JohnWorrall chỉ ra, nó thu hút sự chú ý của bạn khi bản thân vô tình rời khỏi chức năng.
  • Đó là một gợi ý để suy nghĩ lại về mô hình đối tượng; có lẽ chức năng này không thuộc về lớp này.

1
"Làm cho một phương thức tĩnh làm cho nó ít hạn chế hơn bây giờ" --- nó hoàn toàn không. Ví dụ: phương pháp đa hình
zerkms

Tôi nghĩ rằng điểm cuối cùng lặp đi lặp lại: "tại sao bạn biến nó thành một phương thức, khi nó rõ ràng là một hàm?" Giữ những thứ thực sự cần một cá thể tách biệt với những thứ cấu trúc liên quan đến một số khía cạnh. Sau đó bạn có thể dễ dàng chia nó thành các mô-đun riêng biệt.
dhill

@dhill Rules là những thứ đẹp đẽ cho đến ngày bạn nghĩ ra một ngoại lệ hợp lý. Tôi đã mô tả một, một danh sách các cuộc gọi lại.
Bob Stein

7
Việc thêm vào # noinspection PyMethodMayBeStaticbên trên phương thức hoặc lớp sẽ loại bỏ cảnh báo và theo ý kiến ​​của tôi tốt hơn là gọi một phương thức rỗng.
David Pärsson

1
@Talha: hoàn toàn selfkhông bị xóa trong Python3.
Junuxx

12

Tôi nghĩ rằng lý do cho cảnh báo này là cấu hình trong Pycharm. Bạn có thể bỏ chọn Phương thức lựa chọn có thể tĩnh trong Trình chỉnh sửa-> Kiểm tra


12
Câu hỏi của tôi là tại sao một cuộc kiểm tra như vậy thậm chí còn tồn tại. Tôi hiểu tôi có thể tắt nó đi. Xin lỗi, không phải là một câu trả lời.
zerkms

8

Tôi đồng ý với các câu trả lời được đưa ra ở đây (phương pháp không sử dụng selfvà do đó có thể được trang trí bằng @staticmethod).

Tôi muốn thêm rằng bạn có thể muốn di chuyển phương thức sang hàm cấp cao nhất thay vì phương thức tĩnh bên trong một lớp. Để biết chi tiết, hãy xem câu hỏi này và câu trả lời được chấp nhận: python - tôi nên sử dụng các phương thức tĩnh hoặc các hàm cấp cao nhất

Di chuyển phương thức sang một hàm cấp cao nhất cũng sẽ sửa cảnh báo PyCharm.


Câu trả lời thực sự hữu ích - có lẽ PyCharm nên đổi tên cảnh báo thành 'phương thức có thể là chức năng tĩnh hoặc cấp cao nhất'. Khi tái cấu trúc một phương thức, pycharm sẽ tạo ra một hàm cấp cao nhất và không phải là một phương thức tĩnh, nếu selfkhông phải là một tham số.
Suzana

@tlo +1 để đề cập đến trang trí. Tôi có một lớp với một phương thức không sử dụng selfvà do đó có thể là cấp cao nhất, tuy nhiên, điều này không hợp lý khi nhìn vào phương thức này làm gì - vì cấp cao nhất nó trông giống phương thức toàn cầu hơn, trong khi nó là trong thực tế, một phương thức trợ giúp nhỏ cho các thể hiện được tạo từ lớp đó. Vì vậy, để giữ cho mã của tôi được tổ chức hợp lý, trang trí là giải pháp hoàn hảo.
kasimir

7

Tôi có thể tưởng tượng những lợi thế sau của việc có một phương thức lớp được định nghĩa là phương thức tĩnh:

  • bạn có thể gọi phương thức chỉ bằng cách sử dụng tên lớp, không cần khởi tạo nó.

lợi thế còn lại có lẽ là cận biên nếu có ở tất cả:

  • có thể chạy nhanh hơn một chút
  • tiết kiệm một chút bộ nhớ

Vâng. Nhưng vấn đề là - tôi không sử dụng nó như một phương thức tĩnh. Nếu không thì nó đã là tĩnh. Vì vậy, PyCharm khuyên nên làm điều đó mà không có lý do chính đáng (?). "những lợi thế còn lại có lẽ chỉ là cận biên nếu có ở tất cả" --- chính xác. Nhưng nếu đó là trường hợp - đó là một lời khuyên ngớ ngẩn từ PyCharm
zerkms

1
@zerkms đây là cách nó diễn ra với một số trường hợp quyến rũ :-)
Jan Vlcinsky

1
Phương pháp tĩnh là kẻ thù để xây dựng phần mềm tốt. Chúng vô hiệu hóa nhiều nguyên tắc vì vậy việc bitchạy nhanh hơn không phải là vấn đề (vì chúng chạy trong ram rất nhanh trong cả hai trường hợp) và như bạn biết máy tính bây giờ có bunchbộ nhớ nên không còn là vấn đề nữa. Cũng lưu ý suy nghĩ đầu tiên của bạn: Đó là một hành vi thủ tục không phải là một đối tượng hướng đối tượng.
AmirHossein

4

Vì bạn không tham khảo selftrong phần barthân phương thức, PyCharm đang hỏi liệu bạn muốn tạo bartĩnh không. Trong các ngôn ngữ lập trình khác, như Java, có những lý do rõ ràng để khai báo một phương thức tĩnh. Trong Python, lợi ích thực sự duy nhất cho một phương thức tĩnh (AFIK) là có thể gọi nó mà không cần một thể hiện của lớp. Tuy nhiên, nếu đó là lý do duy nhất của bạn, có lẽ bạn nên sử dụng chức năng cấp cao nhất - như lưu ý ở đây .

Nói tóm lại, tôi không chắc chắn một trăm phần trăm tại sao nó ở đó. Tôi đoán họ có thể sẽ loại bỏ nó trong một bản phát hành sắp tới.


3

Thông báo lỗi này chỉ giúp tôi rất nhiều, vì tôi đã không nhận ra rằng mình đã vô tình viết chức năng của mình bằng trình phát ví dụ thử nghiệm

my_player.attributes[item] 

thay vì cách chính xác

self.attributes[item]

1

Nó có thể hơi lộn xộn, nhưng đôi khi bạn không cần truy cập self, nhưng bạn muốn giữ phương thức trong lớp và không làm cho nó tĩnh. Hoặc bạn chỉ muốn tránh thêm một loạt các trang trí khó coi. Dưới đây là một số cách giải quyết tiềm năng cho tình huống đó.

Nếu phương pháp của bạn chỉ có tác dụng phụ và bạn không quan tâm đến những gì nó trả về:

def bar(self):
    doing_something_without_self()
    return self

Nếu bạn cần giá trị trả về:

def bar(self):
    result = doing_something_without_self()
    if self:
        return result

Bây giờ phương pháp của bạn đang sử dụng self, và cảnh báo biến mất!


0

Lý do tại sao Pycharm đưa ra như một cảnh báo vì Python sẽ tự vượt qua như là đối số đầu tiên khi gọi một phương thức tĩnh (không thêm @staticmethod). Pycharm biết điều đó.

Thí dụ:

class T:
    def test():
        print "i am a normal method!"

t = T()
t.test()
output:
Traceback (most recent call last):
  File "F:/Workspace/test_script/test.py", line 28, in <module>
    T().test()
TypeError: test() takes no arguments (1 given)

Tôi đến từ Java, trong "cái tôi" của Java được gọi là "cái này", bạn không cần phải tự viết (hoặc cái này) làm đối số trong phương thức lớp. Bạn chỉ có thể gọi tự khi bạn cần bên trong phương thức. Nhưng Python "phải" tự vượt qua như một đối số phương thức.

Bằng cách hiểu điều này, bạn không cần bất kỳ cách giải quyết nào như câu trả lời @BobStein.


Nó vượt qua selfđể làm gì?
zerkms

@zerkms '@staticmethod' không vượt qua 'bản thân'
Junyu Wu

Tôi vừa trích dẫn bạn: "Python sẽ vượt qua chính mình như là đối số đầu tiên ... Pycharm biết điều đó." Vậy thì sao? Pycharm biết điều đó, tôi biết điều đó. Lý do để đánh dấu phương pháp là gì?
zerkms

@zerkms vì Pycharm nghĩ rằng phương thức đầu tiên của bạn có thể không phải là "cái tôi". Thông thường ppl sẽ không thiết kế một phương thức param và không bao giờ sử dụng nó. Pycharm nghĩ rằng bạn đang tạo một phương thức tĩnh và không nhận ra rằng thông số đầu tiên không phải là "bản thân", do đó, nó đặt cảnh báo theo mặc định. Sự nhầm lẫn này gây ra bởi thiết kế ngôn ngữ lập trình. Tôi đề nghị bạn nên làm theo thiết kế lập trình (thậm chí nó có vẻ không phải là một mẫu tốt), thêm "staticmethod", để tránh nhầm lẫn. Sẽ hoàn toàn tốt nếu bạn thêm "cái tôi" thì không bao giờ sử dụng nó nếu bạn thích. Những gì tôi nói chỉ là một ý kiến ​​khác nhau bằng cách hiểu thiết kế lập trình.
Junyu Wu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.