Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 动态更改模块和类的定义,而不直接更改模块代码_Python_Dynamic - Fatal编程技术网

Python 动态更改模块和类的定义,而不直接更改模块代码

Python 动态更改模块和类的定义,而不直接更改模块代码,python,dynamic,Python,Dynamic,我甚至不确定,以下是否可能。 下面的代码很容易描述我的问题 我的模块定义为 asdf = 5 class MyClass: def myfct(self): return asdf 我有一个模块,它定义了一个复杂的类。 它使用它所在模块的定义。 这里我称之为asdf。 实际上,asdf本身就是一个类定义,为了简单起见,我这里把它作为一个整数 我想将asdf作为成员从模块中删除,但仍有课堂作业。 因此,在将其从模块中删除之前,我首先在加载模块后将其动态写入定义MyClas

我甚至不确定,以下是否可能。 下面的代码很容易描述我的问题

我的模块定义为

asdf = 5
class MyClass:
    def myfct(self):
        return asdf
我有一个模块,它定义了一个复杂的类。 它使用它所在模块的定义。 这里我称之为
asdf
。 实际上,
asdf
本身就是一个类定义,为了简单起见,我这里把它作为一个整数

我想将
asdf
作为成员从模块中删除,但仍有课堂作业。 因此,在将其从模块中删除之前,我首先在加载模块后将其动态写入定义
MyClass
,然后将其从模块中删除

import mymodule

MyClass.asdf = asdf
del sys.modules['mymodule'].asdf
asdf = 5
class MyClass:
    def myfct(self, test=1):
        return asdf

MyClass.asdf = asdf
MyClass.myfct_original = MyClass.myfct

del sys.modules[__name__].asdf
delattr(MyClass, 'myfct')

def newmyfct(self, *args, **kwargs):
    setattr(sys.modules[__name__], 'asdf', MyClass.asdf)
    result = MyClass.myfct_original(self, *args, **kwargs)
    del sys.modules[__name__].asdf
    return result

setattr(MyClass, 'myfct', newmyfct)

myobj = MyClass()
myobj.myfct()
最后,我使用它来实例化新类

myobj = mymodule.MyClass()
myobj.myfct()
但当然,这会带来错误

NameError:未定义名称“asdf”

如何在不更改类的代码的情况下使类正常工作,即不将
return asdf
更改为
return self.asdf
,但仍然从模块中删除
asdf
(并且不添加其他模块属性)。但是,我可以在导入mymodule后动态更改函数

请记住,函数定义非常复杂,因此不能使用
exec
()再次编写函数定义

我的一个想法是动态地更改方法的签名,以便它接收可选参数
asdf
。这样,里面的代码就可以使用这个变量,但我不知道怎么做。可能的帮助信息可能是Byteplay/元类:


    • 下面的答案是可行的,但是半好的。 基本上,我们将原始方法保存在一个虚拟变量中
      myfct\u original
      。 然后我们重新定义我们的函数,以便将变量
      MyClass.asdf
      复制到模块中,应用原始方法,并从模块中删除变量-因此在短时间内它在模块中可用

      import mymodule
      
      MyClass.asdf = asdf
      del sys.modules['mymodule'].asdf
      
      asdf = 5
      class MyClass:
          def myfct(self, test=1):
              return asdf
      
      MyClass.asdf = asdf
      MyClass.myfct_original = MyClass.myfct
      
      del sys.modules[__name__].asdf
      delattr(MyClass, 'myfct')
      
      def newmyfct(self, *args, **kwargs):
          setattr(sys.modules[__name__], 'asdf', MyClass.asdf)
          result = MyClass.myfct_original(self, *args, **kwargs)
          del sys.modules[__name__].asdf
          return result
      
      setattr(MyClass, 'myfct', newmyfct)
      
      myobj = MyClass()
      myobj.myfct()
      

      也许有人能做得更好(见问题的结尾)。

      下面的答案是可行的,但是半好的。 基本上,我们将原始方法保存在一个虚拟变量中
      myfct\u original
      。 然后我们重新定义我们的函数,以便将变量
      MyClass.asdf
      复制到模块中,应用原始方法,并从模块中删除变量-因此在短时间内它在模块中可用

      import mymodule
      
      MyClass.asdf = asdf
      del sys.modules['mymodule'].asdf
      
      asdf = 5
      class MyClass:
          def myfct(self, test=1):
              return asdf
      
      MyClass.asdf = asdf
      MyClass.myfct_original = MyClass.myfct
      
      del sys.modules[__name__].asdf
      delattr(MyClass, 'myfct')
      
      def newmyfct(self, *args, **kwargs):
          setattr(sys.modules[__name__], 'asdf', MyClass.asdf)
          result = MyClass.myfct_original(self, *args, **kwargs)
          del sys.modules[__name__].asdf
          return result
      
      setattr(MyClass, 'myfct', newmyfct)
      
      myobj = MyClass()
      myobj.myfct()
      

      也许有人可以做得更好(见问题的结尾)。

      首先需要删除
      mymodule.asdf
      ?不删除它,只让模块按原样工作有什么错?首先需要删除
      mymodule.asdf
      ?不删除它,只让模块按原样工作,有什么不对?