2017-09-14 63 views
1

在Ruby中,可以創建在方法的對象上定義爲回調:方法添加在Python

module Chatty 
    def self.method_added(method_name) 
    puts "Adding #{method_name.inspect}" 
    end 
    def self.some_class_method() end 
    def some_instance_method() end 
end 
# => Adding :some_instance_method 

確實的Python有任何類似的回調?

+2

不適用於課程創建期間添加的方法。之後它就像'__setattr__'一樣任何其他屬性。 – jonrsharpe

+0

你可以用元類來做到這一點。 –

+0

該功能的良好用例是什麼?我認爲如果你提供了一些動機也會很酷。 –

回答

6

在Python中,方法只是屬性碰巧可以調用*。您必須掛鉤設置的屬性才能查看添加到類中的新方法。

你必須使用一個metaclass攔截被添加到一個類的新屬性:

import types 

class NewMethodAlerter(type): 
    def __setattr__(self, name, obj): 
     if isinstance(obj, types.FunctionType): 
      print(f'New method {name} added!') 
     super().__setattr__(name, obj) 


class Demo(metaclass=NewMethodAlerter): 
    def existing_method(self): 
     pass 

def new_method(self): pass 
Demo.new_method = new_method 

然後看起來是這樣的:

>>> class Demo(metaclass=NewMethodAlerter): 
...  def existing_method(self): 
...   pass 
... 
>>> def new_method(self): pass 
>>> Demo.new_method = new_method 
New method new_method added! 

如果你想了解初始的屬性集合,執行class正文的結果,那麼你有兩個選擇:使用元類,或在Python 3.6及以上,__init_subclass__ method。無論是一個被稱爲創造新的類,可用於檢查屬性:

class InitialMethodAlerter(type): 
    def __new__(typ, name, bases, attrs): 
     for name, obj in attrs.items(): 
      if isinstance(obj, types.FunctionType): 
       print(f'Method {name} defined!') 
     return super().__new__(typ, name, bases, attrs) 

class Demo(metaclass=InitialMethodAlerter): 
    def existing_method(self): 
     pass 

__init_subclass__方法:

class InitialMethodAlerter: 
    @classmethod 
    def __init_subclass__(cls, **kwargs): 
     for name, obj in vars(cls).items(): 
      if isinstance(obj, types.FunctionType): 
       print(f'Method {name} defined!') 

class Demo(InitialMethodAlerter): 
    def existing_method(self): 
     pass 

你可能想在What is a metaclass in Python?

上元類閱讀起來

*那麼,屬性是函數執行盟友。函數是descriptor objects,這使得它們在通過實例訪問時被綁定。該綁定過程會生成一個方法對象,當被調用時會使用原始函數並傳入綁定的實例。

+0

因此,無法攔截類定義中定義的方法? – fny

+0

@faraz:你想在這裏做什麼?我可能誤解了。元類也*被告知關於該類的所有初始屬性,因爲該類是創建的。 –

+0

我希望在定義類之後出現'New method existing_method added!'。 – fny