在访问对象时运行 python 命令

Posted

技术标签:

【中文标题】在访问对象时运行 python 命令【英文标题】:Run python commands upon accessing an object 【发布时间】: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() 我不希望他们必须创建某种类或调用不同于他们习惯的方法。 谢谢!

【问题讨论】:

【参考方案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 嘿,周日看看这个。

以上是关于在访问对象时运行 python 命令的主要内容,如果未能解决你的问题,请参考以下文章

pySerial 运行命令列出端口

Python 设计模式——命令模式

设计模式——行为型模式(责任链,命令,解释器,迭代器,中介者,备忘录,观察者,状态,空对象,策略,模板,访问者)

如何在 Windows 7 上使用命令 CMD 从 python django 访问和配置 postgresql 数据库

emacs中解释器中的命令历史记录

无法在 databricks 运行时版本 7 中使用 shell 命令访问 /dbfs/FileStore