Sedikit kode ini memungkinkan Anda membuat kelas baru dengan nama dinamis dan nama parameter. Verifikasi parameter __init__
tidak mengizinkan parameter yang tidak diketahui, jika Anda memerlukan verifikasi lain, seperti tipe, atau wajib, cukup tambahkan logika di sana:
class BaseClass(object):
def __init__(self, classtype):
self._type = classtype
def ClassFactory(name, argnames, BaseClass=BaseClass):
def __init__(self, **kwargs):
for key, value in kwargs.items():
if key not in argnames:
raise TypeError("Argument %s not valid for %s"
% (key, self.__class__.__name__))
setattr(self, key, value)
BaseClass.__init__(self, name[:-len("Class")])
newclass = type(name, (BaseClass,),{"__init__": __init__})
return newclass
Dan ini berfungsi seperti ini, misalnya:
>>> SpecialClass = ClassFactory("SpecialClass", "a b c".split())
>>> s = SpecialClass(a=2)
>>> s.a
2
>>> s2 = SpecialClass(d=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __init__
TypeError: Argument d not valid for SpecialClass
Saya melihat Anda meminta untuk memasukkan nama dinamis dalam lingkup penamaan - sekarang, itu tidak dianggap sebagai praktik yang baik dengan Python - Anda memiliki nama variabel, yang dikenal pada waktu pengkodean, atau data - dan nama yang dipelajari dalam runtime lebih banyak " data "daripada" variabel "-
Jadi, Anda bisa menambahkan kelas Anda ke kamus dan menggunakannya dari sana:
name = "SpecialClass"
classes = {}
classes[name] = ClassFactory(name, params)
instance = classes[name](...)
Dan jika desain Anda benar-benar membutuhkan nama yang akan dimasukkan dalam cakupan, lakukan hal yang sama, tetapi gunakan kamus yang ditampilkan oleh globals()
panggilan alih-alih kamus acak:
name = "SpecialClass"
globals()[name] = ClassFactory(name, params)
instance = SpecialClass(...)
(Memang mungkin bagi fungsi pabrik kelas untuk memasukkan nama secara dinamis pada cakupan global pemanggil - tetapi itu praktik yang lebih buruk lagi, dan tidak kompatibel di seluruh implementasi Python. Cara melakukannya adalah dengan mendapatkan pemanggil bingkai eksekusi, melalui sys._getframe (1) dan menetapkan nama kelas dalam kamus global bingkai dalam f_globals
atributnya).
update, tl; dr: Jawaban ini telah menjadi populer, masih sangat spesifik untuk badan pertanyaan. Jawaban umum tentang bagaimana
"secara dinamis membuat kelas turunan dari kelas dasar"
dengan Python adalah panggilan sederhana untuk type
meneruskan nama kelas baru, tupel dengan baseclass (es) dan __dict__
tubuh untuk kelas baru -seperti ini:
>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})
memperbarui
Siapa pun yang membutuhkan ini juga harus memeriksa proyek dill - ia mengklaim dapat membuat kelas acar dan membongkar seperti yang dilakukan acar pada objek biasa, dan telah hidup untuk itu dalam beberapa pengujian saya.
a
itu akan selaluMyClass
danTestClass
tidak akan pernah mengambila
? Mengapa tidak mendeklarasikan semua 3 argumenBaseClass.__init__()
tetapi default semuanyaNone
?def __init__(self, a=None, b=None, C=None)
?