Saya memiliki kelas, yang menampung beberapa anggota x (katakanlah, beberapa data yang dibutuhkan oleh semua instance, tetapi tidak bergantung pada mereka):

class Foo(object):
    x = 23

    # some more code goes here    

Sekarang, prosedur penentuan x menjadi lebih kompleks ditambah saya ingin dapat "menyegarkan" x pada waktu-waktu tertentu, jadi saya memutuskan untuk menulis fungsi tambahan untuk itu

class Foo(object):
    @classmethod
    def generate_x(cls):
        cls.x = 23

    # some more code goes here

Namun, definisi kelas ini tidak memiliki panggilan inisialisasi generate_x.

Apa yang saya coba sejauh ini:

Ini tidak bekerja:

class Foo(object):

    # generate_x()     # NameError: name 'generate_x' is not defined
    # Foo.generate_x() # NameError: name 'Foo' is not defined

    @classmethod
    def generate_x(cls):
        cls.x = 23

Ini berfungsi tetapi kurang jelas, karena kode digunakan di luar definisi kelas

class Foo(object):

    @classmethod
    def generate_x(cls):
        cls.x = 23

    # ...
Foo.generate_x()

Apakah ada alternatif yang lebih baik untuk ini? Apakah menggunakan @classmethod pendekatan terbaik di sini? Apa yang saya cari adalah kelas yang setara dengan __init__.

Mempertimbangkan kejelasan kode, apakah ada cara yang lebih baik daripada yang terakhir untuk membuat instance Foo.x secara otomatis menggunakan suatu fungsi?

4
flonk 8 Agustus 2017, 14:26

2 jawaban

Jawaban Terbaik

Salah satu cara untuk mencapai ini adalah dengan menggunakan dekorator:

def with_x(cls):
   cls.generate_x()
   return cls

@with_x
class Foo(object):
   @classmethod
   def generate_x(cls):
      cls.x = 23

(Yang mengatakan, saya pribadi hanya akan memanggil Foo.generate_x secara eksplisit setelah deklarasi kelas, dan menghindari semua keajaiban sama sekali.)

1
NPE 8 Agustus 2017, 11:43

Gunakan deskriptor.

class Complicated:
    def __init__(self, location, get_value):
        self.location =location 
        self.get_value = staticmethod(get_value)
    def __get__(self, obj, owner):
        try:
            a = getattr(owner, self.location)
        except AttributeError:
            a = self.get_value()
            setattr(owner, self.location, a)
        return a

class My class:
     x = Complicated ('_x', get_x)
0
Rick supports Monica 8 Agustus 2017, 12:34