Misalkan saya memiliki kelas dengan konstruktor (atau fungsi lain) yang mengambil sejumlah variabel argumen dan kemudian menetapkannya sebagai atribut kelas secara kondisional.
Saya dapat mengaturnya secara manual, tetapi tampaknya parameter variabel cukup umum di python sehingga harus ada idiom umum untuk melakukan ini. Tapi saya tidak yakin bagaimana melakukan ini secara dinamis.
Saya punya contoh menggunakan eval, tapi itu hampir tidak aman. Saya ingin tahu cara yang tepat untuk melakukan ini - mungkin dengan lambda?
class Foo:
def setAllManually(self, a=None, b=None, c=None):
if a!=None:
self.a = a
if b!=None:
self.b = b
if c!=None:
self.c = c
def setAllWithEval(self, **kwargs):
for key in **kwargs:
if kwargs[param] != None
eval("self." + key + "=" + kwargs[param])
pip install attrs
, hiasi kelas Anda dengan@attr.s
, dan setel argumen sebagaia = attr.ib(); b = attr.ib()
dll. Baca lebih lanjut di sini .Jawaban:
Anda dapat memperbarui
__dict__
atribut (yang mewakili atribut kelas dalam bentuk kamus) dengan argumen kata kunci:maka kamu bisa:
dan dengan sesuatu seperti:
Anda bisa menyaring kunci terlebih dahulu (gunakan
iteritems
bukanitems
jika Anda masih menggunakan Python 2.x).sumber
self.__dict__.update(locals())
untuk menyalin juga argumen posisi.kwargs[0]
bukan hanyakwargs
?kwargs
Bahkan dapat memiliki kunci integer? Saya cukup yakin mereka harus string.Anda dapat menggunakan
setattr()
metode ini:Ada analoginya
getattr()
metode untuk mengambil atribut.sumber
.getattr()
? Atau dapatkah Anda mengakses atribut denganFoo.key
?Foo.attrname
. Saya pikir saya hanya menunjukkan fakta bahwagetattr
metode itu ada. Ini juga berguna jika Anda ingin memberikan nilai default ketika atribut bernama tidak tersedia.Sebagian besar jawaban di sini tidak mencakup cara yang baik untuk menginisialisasi semua atribut yang diizinkan menjadi hanya satu nilai default. Jadi, untuk menambah jawaban yang diberikan oleh @fqxp dan @mmj :
sumber
False
. Poin bagus!Saya mengusulkan variasi jawaban fqxp , yang, selain atribut yang diizinkan , memungkinkan Anda menetapkan nilai default untuk atribut:
Ini adalah kode Python 3.x, untuk Python 2.x Anda membutuhkan setidaknya satu penyesuaian,
iteritems()
sebagai gantinyaitems()
.sumber
Namun varian lain berdasarkan jawaban luar biasa oleh mmj dan fqxp . Bagaimana jika kita mau
Yang saya maksud dengan "langsung" adalah menghindari
default_attributes
kamus asing .Bukan terobosan besar, tapi mungkin berguna bagi seseorang ...
EDIT: Jika kelas kita menggunakan
@property
dekorator untuk merangkum atribut "dilindungi" dengan getter dan setter, dan jika kita ingin dapat mengatur properti ini dengan konstruktor kita, kita mungkin ingin memperluasallowed_keys
daftar dengan nilai daridir(self)
, sebagai berikut:Kode di atas tidak termasuk
dir()
(pengecualian berdasarkan keberadaan "__"), dandir()
yang namanya tidak ditemukan di akhir nama atribut (dilindungi atau sebaliknya) dari__dict__.keys()
, sehingga kemungkinan hanya menyimpan metode dekorasi @property.Hasil edit ini kemungkinan hanya valid untuk Python 3 dan yang lebih baru.
sumber
Saya memanggil kelas
SymbolDict
karena pada dasarnya itu adalah kamus yang beroperasi menggunakan simbol, bukan string. Dengan kata lain, yang Anda lakukanx.foo
bukannyax['foo']
tetapi di balik selimut itu benar-benar terjadi hal yang sama.sumber
Solusi berikut
vars(self).update(kwargs)
atauself.__dict__.update(**kwargs)
tidak kuat, karena pengguna dapat memasukkan kamus apa pun tanpa pesan kesalahan. Jika saya perlu memeriksa apakah pengguna memasukkan tanda tangan berikut ('a1', 'a2', 'a3', 'a4', 'a5') solusinya tidak berfungsi. Selain itu, pengguna harus dapat menggunakan objek dengan melewatkan "parameter posisi" atau "parameter pasangan nilai kay".Jadi saya menyarankan solusi berikut dengan menggunakan metaclass.
sumber
Mereka mungkin solusi yang lebih baik tetapi yang terlintas dalam pikiran saya adalah:
sumber
yang ini paling mudah melalui larsks
contoh saya:
sumber
kwargs
adalah kamus argumen kata kunci, danitems()
merupakan metode yang mengembalikan salinan daftar(key, value)
pasangan kamus .Saya curiga akan lebih baik dalam banyak kasus untuk menggunakan args bernama (untuk kode pendokumentasian diri yang lebih baik) sehingga mungkin terlihat seperti ini:
sumber
for key, value in (a, b, c)