2014-10-28 80 views
0

因此,我編寫了一個模塊,其中包含一組函數,以便與子進程輕鬆交互。這個子進程有一大堆設置可以讓你改變它的格式和行爲。我意識到,有一個便利的類可以用作處理程序來存儲您喜歡使用的設置並將它們傳遞給模塊級功能,這樣會很好。這裏的示例代碼我在做測試用:python:以編程方式爲方便類生成方法

import inspect 

class MyHandler(object): 

    def __init__(self): 
     self.format_string='class format string' 
     self.database='class database' 
     self.mode = "class mode" 

    def rename(self, *args, **kwargs): 
     self._pass_to_function(rename, *args, **kwargs) 

    def _pass_to_function(self, function, *overrided_args, **overrided_kwargs): 
     # get the function's remaining arguments with the inspect module 
     functon_kwargs = inspect.getargspec(function)[0][len(overrided_args):] 

     handler_vars = vars(self) 
     kwargs_to_pass = {} 
     for arg in functon_kwargs: 
      if arg in handler_vars: 
       kwargs_to_pass[arg] = handler_vars[arg] 
     for arg in overrided_kwargs: 
      kwargs_to_pass[arg] = overrided_kwargs[arg] 

     return function(*overrided_args, **kwargs_to_pass) 


def rename(targets, format_string=None, database=None, mode=None, 
      not_in_class='None'): 
    print 'targets = {}'.format(targets) 
    print 'format_string = {}'.format(format_string) 
    print 'database = {}'.format(database) 
    print 'mode = {}'.format(mode) 
    print 'not_in_class = {}\n'.format(not_in_class) 
    return 

我喜歡這個解決辦法的事情是,它使用存儲在類的屬性,但你可以通過簡單地將它們添加到方法調用覆蓋它們如果你想要一次性使用不同的設置。要做到這一點,我把_pass_to_function作爲一種包裝函數來解析和填寫所需的設置和覆蓋。下面是它的外觀:

>>> import argstest 
>>> argstest.rename('some_file.avi', database='some database') 
targets = some_file.avi 
format_string = None 
database = some database 
mode = None 
not_in_class = None 

>>> tst = argstest.MyHandler() 
>>> tst.rename('some_file.avi') 
targets = some_file.avi 
format_string = class format string 
database = class database 
mode = class mode 
not_in_class = None 

>>> tst.rename('some_file.avi', 'one off format string', not_in_class=True) 
targets = some_file.avi 
format_string = one off format string 
database = class database 
mode = class mode 
not_in_class = True 

現在我真正的模塊我有幾十個模塊級的功能,我想從處理程序類來訪問。理想情況下,它們將根據模塊中的功能自動生成。看到所有的方法只是將所有的東西都傳遞給_pass_to_function,我感覺這應該不是很困難,但我很難弄清楚如何。

我讀過關於使用type來生成元類,但我沒有看到我將如何在這種情況下使用它。我沒有看到我可以如何使用type?我是否應該使用某種模塊級別的腳本來添加setattr的功能?我做的是做得更好還是更清晰?

任何和所有的意見,將不勝感激。

+0

你想做什麼? – OozeMeister 2014-10-28 04:23:41

+0

我想基於模塊中找到的其他功能爲MyHandler生成成員函數。這就是上面的代碼所做的,但它在一定程度上不夠優雅。 – Laharah 2014-10-28 04:41:43

+0

好的。我仍然試圖理解*你爲什麼要這樣做。您是否嘗試創建可在類和便利模塊級功能中訪問的相同功能?查看一下Python的記錄器模塊。 – OozeMeister 2014-10-28 14:44:18

回答

0

好的,我想我現在已經回答了我自己的問題。這是模塊的外觀:

import inspect 
import sys 
from types import MethodType 


class MyHandler(object): 

    def __init__(self): 
     self.format_string = 'class format string' 
     self.database = 'class database' 
     self.mode = "class mode" 
     self._populate_methods() 

    def _populate_methods(self): 
     to_add = inspect.getmembers(sys.modules[__name__], inspect.isfunction) 
     to_add = [x[0] for x in to_add if not x[0].startswith('_')] 
     for func_name in to_add: 
      func = getattr(sys.modules[__name__], func_name) # strings to functions 
      self._add_function_as_method(func_name, func) 

    def _add_function_as_method(self, func_name, func): 
     def f(self, *args, **kwargs): # the template for the method we'll add 
      return self._pass_to_function(func, *args, **kwargs) 
     setattr(MyHandler, func_name, MethodType(f, None, MyHandler)) 

    def _pass_to_function(self, function, *overrided_args, **overrided_kwargs): 
     functon_kwargs = inspect.getargspec(function)[0][len(overrided_args):] 
     handler_vars = vars(self) 
     kwargs_to_pass = {} 

     for arg in functon_kwargs: 
      if arg in handler_vars: 
       kwargs_to_pass[arg] = handler_vars[arg] 
     for arg in overrided_kwargs: 
      kwargs_to_pass[arg] = overrided_kwargs[arg] 

     return function(*overrided_args, **kwargs_to_pass) 


def rename(targets, format_string=None, database=None, mode=None, 
      not_in_class='None'): 
    print 'targets = {}'.format(targets) 
    print 'format_string = {}'.format(format_string) 
    print 'database = {}'.format(database) 
    print 'mode = {}'.format(mode) 
    print 'not_in_class = {}\n'.format(not_in_class) 
    return 


def something_else(): 
    print "this function should become a method" 


def _not_a_member(): 
    print "this function should not become a method" 

我已經添加了_populate_methods_add_function_as_method成員函數。 _populate_methods函數獲取模塊中所有「公共」函數的名稱,將它們解除引用到它們的函數,並通過_add_function_as_method傳遞每個函數的名稱。所有這些方法都是使用內部函數來捕獲參數並將它們發送到_pass_to_function,並使用setattr將該函數設置爲一個方法。

所以它的工作原理,但我還是想知道,如果沒有完成這件事更清晰或更多直接的方式。如果任何人能聽到,我會非常感激。