Mengapa pycharm mengusulkan untuk mengubah metode menjadi statis

154

Rilis pycharm baru (edisi komunitas 3.1.3) mengusulkan untuk mengubah metode yang tidak berfungsi dengan keadaan objek saat ini menjadi statis.

masukkan deskripsi gambar di sini

Apa alasan praktis untuk itu? Semacam optimasi kinerja mikro (-atau-memori)?

zerkms
sumber
3
Apakah Anda mengklik "lagi ..."? Apakah Anda referensi di selfmana saja di dalam metode ini? (Jika pertanyaannya benar-benar adalah "mengapa desainer PyCharm mendesain seperti ini ... Anda harus bertanya kepada mereka, bukan SO ...)
Wooble
7
@ Wooble: ada return 1sebagai implementasi garis tunggal dari metode ini. "Lebih banyak" tidak mengandung sesuatu yang berguna
zerkms

Jawaban:

189

PyCharm "berpikir" bahwa Anda mungkin ingin memiliki metode statis, tetapi Anda lupa menyatakannya sebagai statis (menggunakan @staticmethoddekorator).

PyCharm mengusulkan ini karena metode ini tidak digunakan self dalam tubuhnya dan karenanya tidak benar-benar mengubah instance kelas . Karenanya metode ini bisa statis, yaitu callable tanpa melewati instance kelas atau bahkan tanpa membuat instance kelas.

Jolvi
sumber
4
Begitu banyak orang menjawab dengan tanggapan rasa ini. Saya akan menambahkan, jika Anda tahu itu pasti tidak akan menjadi metode statis, kemudian sertakan "throw NotImplementedError" saat Anda di sana untuk memastikan Anda tidak menggunakannya tanpa menyelesaikannya.
Richard Green
1
Mungkin ada kasus di mana peringatan PyCharm tidak dapat dibenarkan karena kita tidak menginginkan metode statis atau mengubah keadaan. Di sisi lain, jika metode ini belum diimplementasikan, sepertinya selalu merupakan ide yang baik untuk memunculkan NotImplementedError.
jolvi
3
Saya memiliki kasus implementasi standar saya mengembalikan konstanta, tetapi subkelas saya diizinkan untuk mengembalikan nilai tergantung pada self. Dalam hal ini peringatannya dapat diabaikan, dan saya menandainya # noinspection PyMethodMayBeStatic. Sangat disayangkan IntelliJ IDEA tidak menawarkan penambahan komentar penonaktifan ini dalam menu konteks untuk peringatan ini.
Alfe
Saya menyarankan perubahan tingkat keparahan pemeriksaan PyCharm ini dari "Peringatan" menjadi "Tidak menyoroti, hanya memperbaiki" di preferensi PyCharm. (Ini menghasilkan banyak positif palsu bagi saya.)
maciek
51

Setuju dengan @jolvi, @ArundasR, dan lainnya, peringatan tersebut terjadi pada fungsi anggota yang tidak digunakan self.

Jika Anda yakin PyCharm salah, bahwa fungsinya seharusnya tidak menjadi @staticmethod, dan jika Anda menghargai peringatan nol, Anda bisa membuat yang ini menghilangkan dua cara berbeda:

Solusi # 1

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

def is_not_used(self):
    pass

Penanganan masalah # 2 [Terima kasih @ DavidPärsson ]

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

Aplikasi yang saya miliki untuk ini (alasan saya tidak bisa menggunakan @staticmethod) adalah membuat tabel fungsi handler untuk menanggapi bidang subtipe protokol. Semua penangan harus berbentuk kursus yang sama (statis atau tidak statis). Tetapi beberapa tidak melakukan apa-apa dengan instance. Jika saya membuat yang statis saya akan mendapatkan "TypeError: objek 'staticmethod' tidak bisa dipanggil".

Untuk mendukung kekuatiran OP, menyarankan Anda menambahkan metode statis kapan pun Anda bisa, bertentangan dengan prinsip bahwa lebih mudah membuat kode menjadi tidak terlalu ketat nanti, daripada membuatnya lebih banyak - membuat metode statis membuatnya kurang ketat sekarang, karena Anda dapat panggil class.f () alih-alih instance.f ().

Tebak mengapa peringatan ini ada:

  • Ini mengiklankan metode statis . Itu membuat pengembang menyadari sesuatu yang mungkin mereka maksudkan.
  • Seperti yang ditunjukkan oleh @ JohnWorrall, itu menarik perhatian Anda ketika diri Anda secara tidak sengaja dihilangkan dari fungsi tersebut.
  • Ini adalah isyarat untuk memikirkan kembali model objek; mungkin fungsinya tidak termasuk dalam kelas ini sama sekali.
Bob Stein
sumber
1
"membuat metode statis membuatnya kurang ketat sekarang" --- tidak sama sekali. Contoh: metode polimorfik
zerkms
Saya pikir poin terakhir diulang: "mengapa Anda menjadikannya sebuah metode, ketika itu jelas sebuah fungsi?" Simpan barang-barang yang benar-benar membutuhkan contoh terpisah dari barang-barang struktural yang berhubungan dengan beberapa aspek. Anda kemudian dapat dengan mudah membaginya menjadi modul terpisah.
dhill
@dhill Rules adalah hal-hal yang indah sampai hari Anda memikirkan pengecualian yang masuk akal. Saya jelaskan satu, daftar panggilan balik.
Bob Stein
7
Menambahkan # noinspection PyMethodMayBeStaticmetode atau kelas di atas menekan peringatan, dan menurut saya lebih baik daripada memanggil metode kosong.
David Pärsson
1
@ Talha: selftidak dihapus sama sekali di Python3.
Junuxx
12

Saya pikir alasan untuk peringatan ini adalah konfigurasi di Pycharm. Anda dapat menghapus centang pada pilihan Metode mungkin statis di Editor-> Inspeksi

mincom
sumber
12
Pertanyaan saya adalah mengapa inspeksi seperti itu ada. Saya mengerti saya bisa mematikannya. Maaf, bukan jawaban.
zerkms
9

Saya setuju dengan jawaban yang diberikan di sini (metode tidak digunakan selfdan karenanya dapat dihiasi dengan @staticmethod).

Saya ingin menambahkan bahwa Anda mungkin ingin memindahkan metode ke fungsi tingkat atas daripada metode statis di dalam kelas. Untuk detail, lihat pertanyaan ini dan jawaban yang diterima: python - haruskah saya menggunakan metode statis atau fungsi tingkat atas

Memindahkan metode ke fungsi tingkat atas akan memperbaiki peringatan PyCharm juga.

tlo
sumber
Jawaban yang sangat membantu - mungkin PyCharm harus mengubah nama peringatan menjadi 'metode mungkin fungsi statis atau tingkat atas'. Ketika refactoring keluar metode, pycharm akan membuat fungsi level atas dan bukan metode statis, jika selfbukan parameter.
Suzana
@ juga +1 untuk menyebutkan dekorator. Saya memiliki kelas dengan metode yang tidak digunakan selfdan karena itu bisa menjadi tingkat atas, namun, ini tidak terasa logis ketika melihat apa yang dilakukan metode ini - karena tingkat atas akan terlihat lebih dari metode global, sementara itu adalah sebenarnya metode pembantu kecil untuk instance yang dibuat dari kelas itu. Jadi untuk menjaga kode saya terorganisir secara logis, dekorator adalah solusi sempurna.
kasimir
7

Saya bisa membayangkan keuntungan berikut memiliki metode kelas yang didefinisikan sebagai metode statis:

  • Anda dapat memanggil metode hanya menggunakan nama kelas, tidak perlu instantiate.

keuntungan yang tersisa mungkin marjinal jika ada sama sekali:

  • mungkin berjalan sedikit lebih cepat
  • menghemat sedikit memori
Jan Vlcinsky
sumber
Ya. Tapi masalahnya - saya tidak menggunakannya sebagai metode statis. Kalau tidak, itu sudah statis. Jadi PyCharm menyarankan untuk melakukannya tanpa alasan (?). "Keuntungan yang tersisa mungkin marjinal jika ada sama sekali" --- ya, tepatnya. Tetapi jika itu masalahnya - ini saran konyol dari PyCharm
zerkms
1
@zerkms begini caranya dengan beberapa contoh menarik :-)
Jan Vlcinsky
2
Metode statis adalah musuh untuk membangun perangkat lunak yang baik. Mereka membatalkan banyak prinsip sehingga bitmenjalankan lebih cepat bukan intinya (karena mereka berjalan di ram begitu cepat dalam kedua kasus) dan seperti yang Anda tahu komputer sekarang memiliki bunchmemori sehingga tidak menjadi masalah lagi. Perhatikan juga pemikiran pertama Anda: Itu adalah perilaku prosedural bukan yang berorientasi objek.
AmirHossein
4

Karena Anda tidak merujuk selfpada barbadan metode, PyCharm bertanya apakah Anda mungkin ingin membuat barstatis. Dalam bahasa pemrograman lain, seperti Java, ada alasan yang jelas untuk mendeklarasikan metode statis. Dalam Python, satu-satunya manfaat nyata untuk metode statis (AFIK) adalah dapat memanggilnya tanpa turunan dari kelas. Namun, jika itu satu-satunya alasan Anda, Anda mungkin lebih baik menggunakan fungsi tingkat atas - seperti dicatat di sini .

Singkatnya, saya tidak seratus persen yakin mengapa itu ada di sana. Saya kira mereka mungkin akan menghapusnya dalam rilis mendatang.

Mengenakan
sumber
3

Pesan kesalahan ini hanya membantu saya banyak, karena saya tidak menyadari bahwa saya tidak sengaja menulis fungsi saya menggunakan contoh pemain pengujian saya

my_player.attributes[item] 

bukannya dengan cara yang benar

self.attributes[item]
John Worrall
sumber
1

Mungkin agak berantakan, tetapi kadang-kadang Anda tidak perlu mengaksesnya self, tetapi Anda lebih suka menyimpan metode di kelas dan tidak membuatnya statis. Atau Anda hanya ingin menghindari menambahkan dekorator yang tidak sedap dipandang. Berikut adalah beberapa solusi potensial untuk situasi itu.

Jika metode Anda hanya memiliki efek samping dan Anda tidak peduli dengan pengembaliannya:

def bar(self):
    doing_something_without_self()
    return self

Jika Anda membutuhkan nilai pengembalian:

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

Sekarang metode Anda gunakan self, dan peringatan itu hilang!

Junuxx
sumber
0

Alasan mengapa Pycharm menjadikannya sebagai peringatan karena Python akan menganggap diri sebagai argumen pertama ketika memanggil metode tidak ada statis (tidak menambahkan @staticmethod). Pycharm tahu itu.

Contoh:

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)

Saya dari Jawa, di Jawa "diri" disebut "ini", Anda tidak perlu menulis sendiri (atau ini) sebagai argumen dalam metode kelas. Anda bisa memanggil diri sendiri sesuai kebutuhan di dalam metode ini. Tapi Python "harus" lulus sebagai argumen metode.

Dengan memahami ini, Anda tidak memerlukan Penanganan Masalah karena jawaban @BobStein.

Junyu Wu
sumber
Lewat selfjadi apa?
zerkms
@zerkms '@staticmethod' tidak lulus 'diri'
Junyu Wu
Saya hanya mengutip Anda: "Python akan menganggap diri sebagai argumen pertama ... Pycharm mengetahuinya.". Terus? Pycharm tahu itu, aku tahu itu. Apa alasan untuk menandai metode ini?
zerkms
@zerkms karena Pycharm berpikir param metode pertama Anda mungkin bukan "diri". Biasanya ppl tidak akan merancang param metode dan tidak pernah menggunakannya. Pycharm berpikir Anda membuat metode statis dan tidak menyadari bahwa param pertama bukanlah "diri", sehingga menempatkan peringatan secara default. Kebingungan ini disebabkan oleh desain bahasa pemrograman. Saya sarankan Anda mengikuti desain pemrograman (meskipun tampaknya bukan pola yang baik), tambahkan "staticmethod", untuk menghindari kebingungan. Tidak apa-apa jika Anda menambahkan "diri" kemudian tidak pernah menggunakannya jika Anda mau. Apa yang saya katakan hanyalah pilihan berbeda dengan memahami desain pemrograman.
Junyu Wu