【问题标题】:Run python commands upon accessing an object在访问对象时运行 python 命令
【发布时间】:2018-09-28 10:17:57
【问题描述】:

我有以下命令:

a = imp.load_source("a", r"some_path\some_source.py")

a 是一个模块对象,我可以从中访问和运行 some_source.py 中的所有函数。我在 python 中有一种方法可以在使用 some_source 的任何函数之前运行附加功能,但 无需更改 some_source.py? 例如,如果 some_source.py 具有函数 foo1、foo2...foo100,那么我要命令

a.foo5() 

实际执行:

imp.reload(a)
a.foo(5)

这应该应用于所有 100 个 foo 函数。

编辑:为了清楚起见,我希望通过运行与我团队中的每个人都习惯的相同命令来实现添加的功能 - a.foo5() 我不希望他们必须创建某种类或调用不同于他们习惯的方法。 谢谢!

【问题讨论】:

    标签: python python-2.7 python-module


    【解决方案1】:

    你可以尝试这样装饰你的模块:

    class ReloadingModule:
        def __init__(self, module):
            self.module = module
    
        def __getattr__(self, attr):
            print("reloading {}...".format(self.module.__name__))
            imp.reload(self.module)
            return getattr(self.module, attr)
    
    
    import this
    this = ReloadingModule(this)
    
    print('\n\n',this.c, '\n\n')
    print('\n\n',this.s, '\n\n')
    

    输出:

    reloading this...
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.
    Explicit is better than implicit.
    [...]
    
    
     97 
    
    
    reloading this...
    The Zen of Python, by Tim Peters
    
    Beautiful is better than ugly.
    Explicit is better than implicit.
    [...]
    
     Gur Mra bs Clguba, ol Gvz Crgref
    
    Ornhgvshy vf orggre guna htyl.
    Rkcyvpvg vf orggre guna vzcyvpvg.
    Fvzcyr vf orggre guna pbzcyrk.
    [...]
    

    有一些数学:

    import math
    math = ReloadingModule(math)
    
    print(math.pi)
    print(math.sin(math.pi/2))
    

    输出:

    reloading math...
    3.141592653589793
    reloading math...
    reloading math...
    1.0
    

    【讨论】:

      【解决方案2】:

      您可以执行以下操作:

      选项 A:

      class example:
          def __init__(self):
              self.a = 2
              self.b = 3
      
          def some_func(self, argument_a):
              print(argument_a)
      
          def some_func_2(self, argument_b):
              print(argument_b)
      
      
      def make_method(method_name):
          def _method(self, *args):
              # Insert what ever extra stuff you want to do here ...
              function_to_call = getattr(self.class_reference, method_name)
              function_to_call(self, *args)
          return _method
      
      
      class a_class:
          def __init__(self, class_reference):
              self.class_reference = class_reference
              object_method_list = [func for func in dir(object) if callable(getattr(object, func))]
              method_list = [func for func in dir(class_reference) if callable(getattr(class_reference, func))]
              for method_name in method_list:
                  if method_name in object_method_list:
                      continue
      
                  _method = make_method(method_name)
                  setattr(type(self), method_name, _method)
      
      
      module_class = a_class(example)
      module_class.some_func()
      

      这创建了一个类,该类从一个动态创建所有函数(带有额外的东西)。

      选项 B:

      def do_func_with_extra(function_to_do, *args):
          # Do something extra...
          function_to_do(*args)
      do_func_with_extra(a.some_func, argument0, argument1, ..)
      

      选项 B 并不完全符合您的要求,但也可以。

      我也很确定有更好的方法。 但我现在想不出一个。让我知道它是否适合你。

      【讨论】:

      • 感谢您的回复!我不确定这些选项是否适合我,因为它们都需要改变我使用 a 的方式,对吧?对于选项 A,我需要从 a 创建一个类,然后使用该类,对于选项 B,我需要每次都使用 do_func_with_extra。最终目标是继续使用相同的方式:a.foo5()
      • @felisimo 不适用于选项 A,如果您甚至不想更改 a 的名称,您可以执行以下操作:a = a_class(a),什么都不应该真正改变。
      • @felisimo 对于选项 A,如果你调用新的类 a,你仍然可以以完全相同的方式调用你的函数,尽管我认为我不诚实并且建议使用他们的答案它更好更简单。
      • 我知道已经有一段时间了,但这个主题再次变得相关。实际上,我更喜欢您的选项 A 而不是他们的答案,因为您的答案创建了一个与模块具有相同属性的类,因此我得到了自动完成,这很重要。无论如何,我尝试了选项 A,但在创建方法列表时出现以下错误: Traceback (last recent call last): File "", line 1, in File "", line 4 , 在 init AttributeError: 'namespace#' 对象的属性 'call' 是只读的
      • @felisimo 嘿,周日看看这个。
      猜你喜欢
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 2021-06-06
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多