2015-08-16 20 views
5

İşlevlerimin çoğunun gerçekleştirdiği kodu azaltmak için dekoratör veya başka bir Pythonic yolu kullanmayı denemem gerektiğini belirlemeye çalışıyorum. Bu işlevlerin, her bir fonksiyonun başlangıcında sadece bir başka işlevi çağırmasını veya her bir fonksiyonun başlangıcını "bir şekilde" "dekore etmesini" istiyorum. Daha önce hiç dekoratör kullanmamıştım ve her bir işlevdeki ortak paylaşım kodunu azaltmak için bu dekorasyon fikrini pythonic bir şekilde uygulamakta zorlanıyorum.Bir işlevi süslemeli miyim?

İşlev başlangıcında aynı adımları gerçekleştirecek birçok işlev var. Ancak, zor bu "dekoratör" fikrini yapar ortak kod bazı yapı endişeler vardır:

  • fonksiyonları tüm bir üst sınıfın alt sınıfında bulunmaktadır.

  • işlevleri arasında ortak komutları fonksiyonu (ancak işlev adı bir alt kümesi) özgü değişken isimleri referans.

  • Genel komutlar, belirli bir koşul karşılanırsa, arayan kişiye geri dönmeli ve herhangi bir çocuk işlevinin daha fazlasını yürütmemelidir. ("Jobj eğer:" örnek kod bloğu) değişkeni için

/örnekler bağlıyor, çocuk fonksiyonu get_nas_server (öz) kod ortak setinde "nas_server" değişken varyantları kullanacak. Get_ işlev adından çıkarıldığında, ortak kod kümesinde kullanılacak değişken adının tabanı ortaya çıkar. "Get_nas_server" fonksiyonu addan Örnek değişkenler isim ve nesne özellikleri:

nas_server
nas_server.json
self.nas_server (özellik)
Burada

işlevlerinden biri tarafından yaygın kodudur:

 #################################################################### 
     def get_nas_server(self): 
     #################################################################### 
      """\nGets COMMAND nas_server and places data into self.nas_server""" 

      try: 
       self.nas_server 
       return self.nas_server 
      except AttributeError: 
       pass 
      self.get_file_cmd('nas_server') 
      jobj = self.fresh_json('nas_server.json') 
      if jobj : 
       self.nas_server = jobj 
       return self.nas_server 
      self.get_file_cmd('get_nas_server') 

İşlevdeki yukarıdaki kodun altındaki her şey, işlev amacına özeldir ve burada tartışmaya uygun değildir. Temel olarak, yukarıdaki tüm kodları işlevlerimde yeniden kullanılabilir hale getirmeye çalışıyorum, ancak kodun işlev adına bağlı olarak değişkenlere ve özniteliklere sahip olması gerekir.

Şimdiye kadar aldığınız için teşekkür ederiz ve tüm yardımlarınız için teşekkürler. Bu pasajı gösteren

class Parent(object): 
    def _get_something(name): 
     try: 
      return getattr(self, name) 
     except AttributeError: 
      pass 
     self.get_file_cmd(name) 
     jobj = self.fresh_json(name+'.json') 
     if jobj : 
      setattr(self, name, jobj) 
      return jobj 
     self.get_file_cmd('get_'+name) 

olarak, nesne adıyla niteliklerini başvurmak için getattr(), setattr() ve hasattr() işlevleri kullanabilirsiniz:

cevap

2

Üst sınıfta bir yardımcı yöntem olarak tanımlayabiliriz şey gibi görünüyor.

+0

Teşekkür: Burada

########################################################################### def get_stub(self,fcmd): ########################################################################### try: return getattr(self, fcmd) except AttributeError: pass jobj = self.fresh_json(fcmd + '.json') if jobj : setattr(self, fcmd, jobj) return jobj if not self.get_file_cmd(fcmd): self.log.error("{} not found".format(fcmd)) return False 

çocuk yöntem bu ana yöntemini kullanır şekli: İşte

Augurar önerdi çoğunlukla olarak üst sınıf yöntemidir. Varolan işleve eklenecek kod, özgün koşullara geri dönebilmeli ve belirli koşullar yerine getirildiyse artık kod yürütmemelidir. Durum gereksinimi bir yardımcı yöntemle mümkün görünmüyorsa bu "dönüş". – Fragtzack

+0

@Fragtzack Doğru, ancak bunu yardımcı olarak çağıran birkaç satırda yapabilirsiniz. – augurar

+0

tamam, bunu deneyecek. Bu yardımcıyı çağıran fonksiyonda, bu yardımcıyı sadece bir self._get_something ('nas_server') olarak adlandırıyorum? – Fragtzack

1

İlk defter tutma maddeleri bu sınıfa çok özgüyse, sınıfınızın içinde bir dekoratör kullanabilirsiniz. Her zaman bir sınıf yönteminin içinde bu ilk kontrolü yapmanız gerekiyorsa, bunu aşağıda eklediğim auto_nas dekoratör ile kolayca dekore edebilirsiniz. Bu sarıcının kapsamının, tek başına bu sınıfa özgü olduğunu varsayıyorum. Aksi takdirde, bunu genel olarak sınıfın dışına taşıyabilirsiniz, ancak bunu yapacaksanız (self=None)'u değiştirmeyi unutmayın.

da
class YourMainClass(): 
    # This is your main class inside which all the methods are defined. 

    def auto_nas(func): 
     # This wrapper function will be called instead of your class methods. 
     def wrap(self): 
      # All your bookkeeping stuff goes here. 
      try: 
       self.nas_server 
       return self.nas_server 
      except AttributeError: 
       pass 
      self.get_file_cmd('nas_server') 
      jobj = self.fresh_json('nas_server.json') 
      if jobj : 
       self.nas_server = jobj 
       return self.nas_server 
      self.get_file_cmd('get_nas_server') 
      # Things went well - we shall call the actual method. 
      return func(self) 
     return wrap 

    @auto_nas 
    def get_nas_server(self): 
     # This is one of your methods that require bookkeeping 
     pass 

, sarıcı işlevi içinde self edin. Python tarafından otomatik olarak bir argüman olarak iletilir ve böylece o dekoratörün içinden tüm örneğe özel niteliklere erişebilirsiniz. Bir kez daha, dekoratörünüz sınıfınızın her bir örneğine özgü işler yapması gerektiğinde bu uygundur. Durum böyle değilse, tüm bu kodu bir işlev içine koyabilirsiniz ve her seferinde istediğiniz zaman arayabilirsiniz.

0

Doğru yönde işaret etmek için Augurar'a teşekkürler. Sonunda ana sınıfta bir stub yöntemi oluşturdum. Sadece ana yöntemi "genişletmek" için uygun teknikle yöntemi çağırmak gerekiyordu. Sonra bu sınıflandırma yöntemini super() ile alt sınıftan çağırmak Bu teknik için uygun bir ad olmalı? yöntem geçersiz kılma? yöntem uzar? girişi için

#################################################################### 
def get_nas_server(self): 
#################################################################### 
    super().get_stub('nas_server') 
    #bunch of child method specific code below here 
İlgili konular