Saya mencoba untuk membagi kelas besar saya menjadi dua; baik, pada dasarnya ke dalam kelas "utama" dan campuran dengan fungsi tambahan, seperti:
main.py
mengajukan:
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
mymixin.py
mengajukan:
class MyMixin(object):
def func2(self: Main, xxx): # <--- note the type hint
...
Sekarang, sementara ini berfungsi dengan baik, petunjuk jenis MyMixin.func2
tentu saja tidak dapat berfungsi. Saya tidak bisa mengimpor main.py
, karena saya mendapatkan impor siklik dan tanpa petunjuk, editor saya (PyCharm) tidak tahu apaself
itu.
Saya menggunakan Python 3.4, bersedia pindah ke 3.5 jika solusi tersedia di sana.
Adakah cara untuk membagi kelas saya menjadi dua file dan menyimpan semua "koneksi" sehingga IDE saya masih menawarkan penyelesaian otomatis & semua hal lain yang berasal darinya dengan mengetahui jenisnya?
self
, karena ini akan selalu menjadi subclass dari kelas saat ini (dan sistem pengecekan tipe apa pun harus dapat mengetahuinya sendiri). Apakahfunc2
mencoba meneleponfunc1
, yang tidak ditentukan dalamMyMixin
? Mungkin harus (sebagaiabstractmethod
, mungkin)?class Main(MyMixin, SomeBaseClass)
sehingga metode dari kelas yang lebih spesifik dapat menimpa yang dari kelas dasarJawaban:
Sayangnya, tidak ada cara yang sangat elegan untuk menangani siklus impor secara umum. Pilihan Anda adalah mendesain ulang kode Anda untuk menghapus ketergantungan siklik, atau jika tidak memungkinkan, lakukan sesuatu seperti ini:
The
TYPE_CHECKING
konstan selaluFalse
pada saat runtime, sehingga impor tidak akan dievaluasi, tapi mypy (dan jenis-memeriksa alat-alat lain) akan mengevaluasi isi dari blok itu.Kita juga perlu membuat
Main
anotasi tipe menjadi string, yang secara efektif meneruskan mendeklarasikannya karenaMain
simbol tidak tersedia pada waktu proses.Jika Anda menggunakan Python 3.7+, setidaknya kita dapat melewati keharusan memberikan anotasi string eksplisit dengan memanfaatkan PEP 563 :
The
from __future__ import annotations
impor akan membuat semua petunjuk jenis be string dan melewatkan mengevaluasi mereka. Ini dapat membantu membuat kode kami di sini sedikit lebih ergonomis.Semua yang mengatakan, menggunakan mixin dengan mypy kemungkinan akan membutuhkan lebih banyak struktur daripada yang Anda miliki saat ini. Mypy merekomendasikan pendekatan yang pada dasarnya
deceze
mendeskripsikan - untuk membuat ABC yang diwarisi oleh AndaMain
danMyMixin
kelas. Saya tidak akan terkejut jika Anda akhirnya perlu melakukan hal serupa untuk membuat pemeriksa Pycharm senang.sumber
typing
, tetapi PyCharm juga cukup senangif False:
.__init__
typing. TYPE_CHECKING
: python.org/dev/peps/pep-0484/#runtime-or-type-checkingUntuk orang-orang yang berjuang dengan impor siklik saat mengimpor kelas hanya untuk pemeriksaan Jenis: Anda mungkin ingin menggunakan Referensi Teruskan (PEP 484 - Petunjuk Jenis):
Jadi, alih-alih:
Anda melakukan:
sumber
File -> Invalidate Caches
?if False:
Anda juga bisafrom typing import TYPE_CHECKING
danif TYPE_CHECKING:
.Masalah yang lebih besar adalah tipe Anda tidak waras untuk memulai.
MyMixin
membuat asumsi hardcode bahwa itu akan dicampurMain
, sedangkan itu bisa dicampur ke sejumlah kelas lain, dalam hal ini mungkin akan rusak. Jika mixin Anda di-hardcode untuk dicampur ke dalam satu kelas tertentu, Anda juga dapat menulis metode langsung ke dalam kelas itu alih-alih memisahkannya.Untuk melakukan ini dengan benar dengan pengetikan yang waras,
MyMixin
harus dikodekan dengan antarmuka , atau kelas abstrak dalam bahasa Python:sumber
Ternyata upaya awal saya cukup dekat dengan solusinya juga. Inilah yang saya gunakan saat ini:
Perhatikan pernyataan import dalam
if False
yang tidak pernah diimpor (tetapi IDE mengetahuinya) dan menggunakanMain
kelas sebagai string karena tidak dikenal pada waktu proses.sumber
Saya pikir cara terbaik adalah dengan mengimpor semua kelas dan dependensi dalam sebuah file (seperti
__init__.py
) dan kemudianfrom __init__ import *
di semua file lainnya.Dalam hal ini Anda
sumber
import *
, namun Anda tetap dapat memanfaatkan pendekatan yang mudah ini