Saya sedang menulis algoritme pencarian ruang keadaan AI, dan saya memiliki kelas generik yang dapat digunakan untuk mengimplementasikan algoritma pencarian dengan cepat. Subclass akan mendefinisikan operasi yang diperlukan, dan algoritma melakukan sisanya.
Di sinilah saya macet: Saya ingin menghindari regenerasi negara induk berulang-ulang, jadi saya memiliki fungsi berikut, yang mengembalikan operasi yang dapat diterapkan secara hukum ke keadaan apa pun:
def get_operations(self, include_parent=True):
ops = self._get_operations()
if not include_parent and self.path.parent_op:
try:
parent_inverse = self.invert_op(self.path.parent_op)
ops.remove(parent_inverse)
except NotImplementedError:
pass
return ops
Dan fungsi invert_op melempar secara default.
Apakah ada cara yang lebih cepat untuk memeriksa untuk melihat apakah fungsi tidak didefinisikan daripada menangkap pengecualian?
Saya sedang memikirkan sesuatu untuk memeriksa apakah ada dir, tapi itu sepertinya tidak benar. hasattr diimplementasikan dengan memanggil getattr dan memeriksa apakah itu memunculkan, yang bukan yang saya inginkan.
has_op = lambda obj, op: callable(getattr(obj, op, None))
hasattr(connection, 'invert_opt')
.Jawaban:
Ya, gunakan
getattr()
untuk mendapatkan atribut, dancallable()
untuk memverifikasi itu adalah metode:Perhatikan bahwa
getattr()
biasanya melempar pengecualian ketika atribut tidak ada. Namun, jika Anda menentukan nilai default (None
, dalam hal ini), itu akan mengembalikannya.sumber
getattr
dalam hal ini menangkap pengecualian secara diam-diam dan mengembalikan nilai default sebagai gantinya, sepertihasattr
halnya yang dilakukan OP karena alasan tertentu.Ia bekerja di kedua Python 2 dan Python 3
hasattr
kembaliTrue
jika objek koneksi memiliki fungsi yanginvert_opt
ditentukan. Ini adalah dokumentasi untuk Anda makanhttps://docs.python.org/2/library/functions.html#hasattr https://docs.python.org/3/library/functions.html#hasattr
sumber
connection.invert_opt = 'foo'
.Mengapa kamu menentang itu? Dalam kebanyakan kasus Pythonic, lebih baik meminta maaf daripada izin. ;-)
Lagi-lagi mengapa itu? Berikut ini adalah Pythonic:
Atau,
Namun, perlu diketahui bahwa hal
getattr(obj, attr, default)
itu pada dasarnya dilaksanakan dengan menangkap pengecualian juga. Tidak ada yang salah dengan itu di tanah Python!sumber
Respons di sini memeriksa apakah string adalah nama atribut objek. Langkah ekstra (menggunakan callable) diperlukan untuk memeriksa apakah atribut adalah metode.
Jadi intinya adalah: apa cara tercepat untuk memeriksa apakah objek obj memiliki atribut atribut. Jawabannya adalah
Ini karena dict memiliki kunci-kuncinya sehingga memeriksa keberadaan kunci itu cepat.
Lihat perbandingan waktu di bawah ini.
sumber
__slots__
.__slots__
membantu mempercepat akses atribut hingga ~ 10%. stackoverflow.com/a/14119024/1459669Saya suka jawaban Nathan Ostgard dan saya memilihnya. Tapi cara lain Anda bisa menyelesaikan masalah Anda adalah dengan menggunakan dekorator memoizing, yang akan men-cache hasil panggilan fungsi. Jadi, Anda dapat melanjutkan dan memiliki fungsi mahal yang menemukan sesuatu, tetapi kemudian ketika Anda menyebutnya berulang-ulang panggilan cepat; versi memoized dari fungsi mencari argumen dalam dict, menemukan hasil dict dari ketika fungsi aktual menghitung hasilnya, dan mengembalikan hasilnya segera.
Ini adalah resep untuk dekorator memoizing bernama "lru_cache" oleh Raymond Hettinger. Versi ini sekarang menjadi standar dalam modul functools dengan Python 3.2.
http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/
http://docs.python.org/release/3.2/library/functools.html
sumber
Seperti apa pun di Python, jika Anda berusaha cukup keras, Anda bisa mendapatkan nyali dan melakukan sesuatu yang sangat jahat. Sekarang, inilah bagian jahatnya:
Tolong bantu kami, terus lakukan apa yang Anda miliki di pertanyaan Anda dan JANGAN pernah menggunakan ini kecuali Anda berada di tim PyPy meretas ke dalam juru bahasa Python. Apa yang Anda miliki di sana adalah Pythonic, apa yang saya miliki di sini adalah JAHAT murni .
sumber
co_names
sama dengan('NotImplementedError',)
. Saya tidak yakin apakah ini membuatnya lebih atau kurang jahat.Anda juga dapat membahas kelas:
sumber
Meskipun memeriksa atribut dalam properti __dict__ sangat cepat, Anda tidak dapat menggunakan ini untuk metode, karena mereka tidak muncul dalam hash __dict__. Namun Anda dapat menggunakan solusi peretasan di kelas Anda, jika kinerjanya sangat penting:
Kemudian periksa metode sebagai:
Perbandingan waktu dengan
getattr
:Bukannya saya mendorong pendekatan ini, tetapi tampaknya berhasil.
[EDIT] Peningkatan kinerja bahkan lebih tinggi ketika nama metode tidak ada di kelas yang diberikan:
sumber
__dict__
bisa ditimpa. Itu tidak bisa dipercaya.