将方法添加到现有对象实例

我读到可以在Python中向现有对象(即不在类定义中)添加方法。

我知道这样做并不总是好的。但是如何才能做到这一点呢?

344091 次浏览

在Python中,monkeypatch通常通过用您自己的签名覆盖类或函数的签名来工作。下面是Zope Wiki中的一个示例:

from SomeOtherProduct.SomeModule import SomeClassdef speak(self):return "ook ook eee eee eee!"SomeClass.speak = speak

这段代码将覆盖/创建类中名为speak的方法。在Jeff Atwood的最近关于猴子补丁的帖子中,他展示了C#3.0中的一个示例,这是我当前用于工作的语言。

在Python中,函数和绑定方法是有区别的。

>>> def foo():...     print "foo"...>>> class A:...     def bar( self ):...         print "bar"...>>> a = A()>>> foo<function foo at 0x00A98D70>>>> a.bar<bound method A.bar of <__main__.A instance at 0x00A9BC88>>>>>

绑定方法已被“绑定”(如何描述性)到实例,并且每当调用该方法时,该实例将作为第一个参数传递。

但是,作为类(而不是实例)属性的可调用对象仍然是未绑定的,因此您可以随时修改类定义:

>>> def fooFighters( self ):...     print "fooFighters"...>>> A.fooFighters = fooFighters>>> a2 = A()>>> a2.fooFighters<bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>>>> a2.fooFighters()fooFighters

以前定义的实例也会更新(只要它们本身没有覆盖属性):

>>> a.fooFighters()fooFighters

当你想将方法附加到单个实例时,问题就来了:

>>> def barFighters( self ):...     print "barFighters"...>>> a.barFighters = barFighters>>> a.barFighters()Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: barFighters() takes exactly 1 argument (0 given)

该函数直接附加到实例时不会自动绑定:

>>> a.barFighters<function barFighters at 0x00A98EF0>

要绑定它,我们可以使用类型模块中的方法类型函数

>>> import types>>> a.barFighters = types.MethodType( barFighters, a )>>> a.barFighters<bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>>>> a.barFighters()barFighters

这次类的其他实例没有受到影响:

>>> a2.barFighters()Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: A instance has no attribute 'barFighters'

更多信息可以通过阅读描述符元类编程找到。

你要找的是setattr我相信。使用它来设置对象的属性。

>>> def printme(s): print repr(s)>>> class A: pass>>> setattr(A,'printme',printme)>>> a = A()>>> a.printme() # s becomes the implicit 'self' variable< __ main __ . A instance at 0xABCDEFG>

杰森·普拉特发布的内容是正确的。

>>> class Test(object):...   def a(self):...     pass...>>> def b(self):...   pass...>>> Test.b = b>>> type(b)<type 'function'>>>> type(Test.a)<type 'instancemethod'>>>> type(Test.b)<type 'instancemethod'>

正如您所看到的,Python并没有考虑b()与a()有任何不同。在Python中,所有方法都只是碰巧是函数的变量。

模块新的自python 2.6以来已弃用,并在3.0中删除,使用类型

http://docs.python.org/library/new.html

在下面的示例中,我故意从patch_me()函数中删除了返回值。我认为给出返回值可能会让人相信patch返回一个新对象,这不是真的-它修改了传入的对象。可能这可以促进更有纪律地使用monkeypatch。

import types
class A(object):#but seems to work for old style objects toopass
def patch_me(target):def method(target,x):print "x=",xprint "called from", targettarget.method = types.MethodType(method,target)#add more if needed
a = A()print a#out: <__main__.A object at 0x2b73ac88bfd0>patch_me(a)    #patch instancea.method(5)#out: x= 5#out: called from <__main__.A object at 0x2b73ac88bfd0>patch_me(A)A.method(6)        #can patch class too#out: x= 6#out: called from <class '__main__.A'>

我认为以上的回答没有抓住关键点。

让我们有一个带有方法的类:

class A(object):def m(self):pass

现在,让我们在ipython中使用它:

In [2]: A.mOut[2]: <unbound method A.m>

好的,所以m()不知何故变成了一个的一个未绑定方法。但是真的是这样吗?

In [5]: A.__dict__['m']Out[5]: <function m at 0xa66b8b4>

事实证明,m()只是一个函数,对它的引用被添加到一个类字典中——没有魔法。那为什么上午给了我们一个未绑定的方法?这是因为点没有被翻译成简单的字典查找。这实际上是对A.__class__的调用。__getattribute__(A,'m'):

In [11]: class MetaA(type):....:     def __getattribute__(self, attr_name):....:         print str(self), '-', attr_name
In [12]: class A(object):....:     __metaclass__ = MetaA
In [23]: A.m<class '__main__.A'> - m<class '__main__.A'> - m

现在,我不知道为什么最后一行打印了两次,但仍然很清楚那里发生了什么。

现在,默认__getattribute__所做的是检查属性是否是所谓的描述符,即它是否实现了一个特殊的__get__方法。如果它实现了那个方法,那么返回的是调用__get__方法的结果。回到我们一个类的第一个版本,这是我们所拥有的:

In [28]: A.__dict__['m'].__get__(None, A)Out[28]: <unbound method A.m>

由于Python函数实现了描述符协议,如果它们代表一个对象被调用,它们会在__get__方法中将自己绑定到该对象。

好的,那么如何向现有对象添加方法呢?假设你不介意修补类,它就像:

B.m = m

然后b. m“变成”了一个未绑定的方法,这要归功于描述符魔法。

如果你想只向单个对象添加一个方法,那么你必须自己使用类型来模拟机器。方法类型:

b.m = types.MethodType(m, b)

顺便说一句:

In [2]: A.mOut[2]: <unbound method A.m>
In [59]: type(A.m)Out[59]: <type 'instancemethod'>
In [60]: type(b.m)Out[60]: <type 'instancemethod'>
In [61]: types.MethodTypeOut[61]: <type 'instancemethod'>

整合Jason Pratt和社区wiki的答案,看看不同绑定方法的结果:

特别注意如何将绑定函数添加为类方法作品,但引用范围不正确。

#!/usr/bin/python -uimport typesimport inspect
## dynamically adding methods to a unique instance of a class

# get a list of a class's method type attributesdef listattr(c):for m in [(n, v) for n, v in inspect.getmembers(c, inspect.ismethod) if isinstance(v,types.MethodType)]:print m[0], m[1]
# externally bind a function as a method of an instance of a classdef ADDMETHOD(c, method, name):c.__dict__[name] = types.MethodType(method, c)
class C():r = 10 # class attribute variable to test bound scope
def __init__(self):pass
#internally bind a function as a method of self's class -- note that this one has issues!def addmethod(self, method, name):self.__dict__[name] = types.MethodType( method, self.__class__ )
# predfined function to compare withdef f0(self, x):print 'f0\tx = %d\tr = %d' % ( x, self.r)
a = C() # created before modified instnaceb = C() # modified instnace

def f1(self, x): # bind internallyprint 'f1\tx = %d\tr = %d' % ( x, self.r )def f2( self, x): # add to class instance's .__dict__ as method typeprint 'f2\tx = %d\tr = %d' % ( x, self.r )def f3( self, x): # assign to class as method typeprint 'f3\tx = %d\tr = %d' % ( x, self.r )def f4( self, x): # add to class instance's .__dict__ using a general functionprint 'f4\tx = %d\tr = %d' % ( x, self.r )

b.addmethod(f1, 'f1')b.__dict__['f2'] = types.MethodType( f2, b)b.f3 = types.MethodType( f3, b)ADDMETHOD(b, f4, 'f4')

b.f0(0) # OUT: f0   x = 0   r = 10b.f1(1) # OUT: f1   x = 1   r = 10b.f2(2) # OUT: f2   x = 2   r = 10b.f3(3) # OUT: f3   x = 3   r = 10b.f4(4) # OUT: f4   x = 4   r = 10

k = 2print 'changing b.r from {0} to {1}'.format(b.r, k)b.r = kprint 'new b.r = {0}'.format(b.r)
b.f0(0) # OUT: f0   x = 0   r = 2b.f1(1) # OUT: f1   x = 1   r = 10  !!!!!!!!!b.f2(2) # OUT: f2   x = 2   r = 2b.f3(3) # OUT: f3   x = 3   r = 2b.f4(4) # OUT: f4   x = 4   r = 2
c = C() # created after modifying instance
# let's have a look at each instance's method type attributesprint '\nattributes of a:'listattr(a)# OUT:# attributes of a:# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FD88>># addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FD88>># f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FD88>>
print '\nattributes of b:'listattr(b)# OUT:# attributes of b:# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FE08>># addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FE08>># f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FE08>># f1 <bound method ?.f1 of <class __main__.C at 0x000000000237AB28>># f2 <bound method ?.f2 of <__main__.C instance at 0x000000000230FE08>># f3 <bound method ?.f3 of <__main__.C instance at 0x000000000230FE08>># f4 <bound method ?.f4 of <__main__.C instance at 0x000000000230FE08>>
print '\nattributes of c:'listattr(c)# OUT:# attributes of c:# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002313108>># addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002313108>># f0 <bound method C.f0 of <__main__.C instance at 0x0000000002313108>>

就个人而言,我更喜欢外部ADDMETHOD函数路由,因为它允许我在迭代器中动态分配新方法名称。

def y(self, x):passd = C()for i in range(1,5):ADDMETHOD(d, y, 'f%d' % i)print '\nattributes of d:'listattr(d)# OUT:# attributes of d:# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002303508>># addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002303508>># f0 <bound method C.f0 of <__main__.C instance at 0x0000000002303508>># f1 <bound method ?.y of <__main__.C instance at 0x0000000002303508>># f2 <bound method ?.y of <__main__.C instance at 0x0000000002303508>># f3 <bound method ?.y of <__main__.C instance at 0x0000000002303508>># f4 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>

由于这个问题询问的是非Python版本,所以这里是JavaScript:

a.methodname = function () { console.log("Yay, a new method!") }

至少有两种方法可以将方法附加到不带types.MethodType的实例:

>>> class A:...  def m(self):...   print 'im m, invoked with: ', self
>>> a = A()>>> a.m()im m, invoked with:  <__main__.A instance at 0x973ec6c>>>> a.m<bound method A.m of <__main__.A instance at 0x973ec6c>>>>>>>> def foo(firstargument):...  print 'im foo, invoked with: ', firstargument
>>> foo<function foo at 0x978548c>

1:

>>> a.foo = foo.__get__(a, A) # or foo.__get__(a, type(a))>>> a.foo()im foo, invoked with:  <__main__.A instance at 0x973ec6c>>>> a.foo<bound method A.foo of <__main__.A instance at 0x973ec6c>>

2:

>>> instancemethod = type(A.m)>>> instancemethod<type 'instancemethod'>>>> a.foo2 = instancemethod(foo, a, type(a))>>> a.foo2()im foo, invoked with:  <__main__.A instance at 0x973ec6c>>>> a.foo2<bound method instance.foo of <__main__.A instance at 0x973ec6c>>

有用链接:
数据模型-调用描述符
描述符HowTo指南-调用描述符

如果有任何帮助,我最近发布了一个名为Gorilla的Python库,以使猴子补丁的过程更加方便。

使用函数needle()修补名为guineapig的模块如下:

import gorillaimport guineapig@gorilla.patch(guineapig)def needle():print("awesome")

但它也照顾到更有趣的用例,如留档中的FAQ所示。

代码在github上可用。

你可以使用lambda将方法绑定到实例:

def run(self):print self._instanceString
class A(object):def __init__(self):self._instanceString = "This is instance string"
a = A()a.run = lambda: run(a)a.run()

输出:

This is instance string

前言-关于兼容性的注释:其他答案可能只在Python 2中有效-这个答案应该在Python 2和3中很好地工作。如果只编写Python 3,你可能会省略显式继承object,但否则代码应该保持不变。

将方法添加到现有对象实例

我读到可以在Python中向现有对象(例如不在类定义中)添加方法。

我知道这样做并不总是一个好决定。但是,一个人怎么能做到这一点?

是的,这是可能的-但不推荐

我不建议这样做。这是个坏主意。不要这样做。

这里有几个原因:

  • 你将向执行此操作的每个实例添加一个绑定对象。如果你经常这样做,你可能会浪费大量内存。绑定方法通常仅在其调用的短时间内创建,然后当自动垃圾收集时它们就不再存在。如果你手动执行此操作,你将有一个引用绑定方法的名称绑定-这将阻止其垃圾回收机制的使用。
  • 给定类型的对象实例通常在该类型的所有对象上都有其方法。如果您在其他地方添加方法,一些实例将具有这些方法,而其他实例则没有。程序员不会期望这一点,并且您有违反最小意外规则的风险。
  • 因为还有其他很好的理由不这样做,如果你这样做,你会给自己一个糟糕的声誉。

因此,我建议你不要这样做,除非你有一个非常好的理由。在类定义中定义正确的方法要好得多更少最好直接对类进行猴子补丁,如下所示:

Foo.sample_method = sample_method

然而,由于它很有启发性,我将向您展示一些这样做的方法。

如何才能做到

这是一些设置代码。我们需要一个类定义。它可以被导入,但实际上无关紧要。

class Foo(object):'''An empty class to demonstrate adding a method to an instance'''

创建一个实例:

foo = Foo()

创建一个方法添加到它:

def sample_method(self, bar, baz):print(bar + baz)

方法零(0)-使用描述符方法,__get__

函数上的点查找使用实例调用函数的__get__方法,将对象绑定到方法,从而创建一个“绑定方法”。

foo.sample_method = sample_method.__get__(foo)

现在:

>>> foo.sample_method(1,2)3

方法一-类型。

首先,导入类型,我们将从中获取方法构造函数:

import types

现在我们将方法添加到实例中。为此,我们需要来自types模块(我们在上面导入的)的方法类型构造函数。

类型的参数签名。方法类型(在Python 3中)是(function, instance)

foo.sample_method = types.MethodType(sample_method, foo)

和用法:

>>> foo.sample_method(1,2)3

顺便说一句,在Python 2中,签名是(function, instance, class)

foo.sample_method = types.MethodType(sample_method, foo, Foo)

方法二:词汇绑定

首先,我们创建一个包装函数,将方法绑定到实例:

def bind(instance, method):def binding_scope_fn(*args, **kwargs):return method(instance, *args, **kwargs)return binding_scope_fn

用法:

>>> foo.sample_method = bind(foo, sample_method)>>> foo.sample_method(1,2)3

方法三:functools.partial

部分函数将第一个参数应用于函数(以及可选的关键字参数),稍后可以使用其余参数(以及覆盖关键字参数)调用。因此:

>>> from functools import partial>>> foo.sample_method = partial(sample_method, foo)>>> foo.sample_method(1,2)3

当您认为绑定方法是实例的部分函数时,这是有意义的。

未绑定函数作为对象属性-为什么这不起作用:

如果我们尝试以与将sample_method添加到类中相同的方式添加,它将不受实例的约束,并且不会将隐式self作为第一个参数。

>>> foo.sample_method = sample_method>>> foo.sample_method(1,2)Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: sample_method() takes exactly 3 arguments (2 given)

我们可以通过显式传递实例(或任何东西,因为此方法实际上不使用self参数变量)来使未绑定函数工作,但它不会与其他实例的预期签名一致(如果我们正在修补此实例):

>>> foo.sample_method(foo, 1, 2)3

结论

你现在知道几种方法可以这样做,但严肃地说-不要这样做。

这实际上是“Jason Pratt”答案的插件

虽然Jasons的回答是有效的,但只有在想向类添加函数时才有效。当我试图从. py源代码文件重新加载一个已经存在的方法时,它对我不起作用。

我花了很长时间才找到解决办法,但诀窍似乎很简单…1.st从源代码文件导入代码2.nd重新加载3.rd使用type. FunctionType(…)将导入和绑定的方法转换为函数您还可以传递当前的全局变量,因为重新加载的方法将位于不同的命名空间中4.th现在你可以按照"Jason Pratt"的建议继续使用类型。方法类型(…)

示例:

# this class resides inside ReloadCodeDemo.pyclass A:def bar( self ):print "bar1"        
def reloadCode(self, methodName):''' use this function to reload any function of class A'''import typesimport ReloadCodeDemo as ReloadMod # import the code as modulereload (ReloadMod) # force a reload of the modulemyM = getattr(ReloadMod.A,methodName) #get reloaded MethodmyTempFunc = types.FunctionType(# convert the method to a simple functionmyM.im_func.func_code, #the methods codeglobals(), # globals to useargdefs=myM.im_func.func_defaults # default values for variables if any)myNewM = types.MethodType(myTempFunc,self,self.__class__) #convert the function to a methodsetattr(self,methodName,myNewM) # add the method to the function
if __name__ == '__main__':a = A()a.bar()# now change your code and save the filea.reloadCode('bar') # reloads the filea.bar() # now executes the reloaded code

这个问题是几年前提出的,但是嘿,有一种简单的方法可以使用装饰器模拟函数与类实例的绑定:

def binder (function, instance):copy_of_function = type (function) (function.func_code, {})copy_of_function.__bind_to__ = instancedef bound_function (*args, **kwargs):return copy_of_function (copy_of_function.__bind_to__, *args, **kwargs)return bound_function

class SupaClass (object):def __init__ (self):self.supaAttribute = 42

def new_method (self):print self.supaAttribute

supaInstance = SupaClass ()supaInstance.supMethod = binder (new_method, supaInstance)
otherInstance = SupaClass ()otherInstance.supaAttribute = 72otherInstance.supMethod = binder (new_method, otherInstance)
otherInstance.supMethod ()supaInstance.supMethod ()

在那里,当你将函数和实例传递给绑定器装饰器时,它将创建一个新函数,其代码对象与第一个相同。然后,给定的类实例存储在新创建函数的属性中。装饰器返回一个(第三个)函数自动调用复制的函数,将实例作为第一个参数。

最后,你得到了一个模拟它绑定到类实例的函数。让原始函数保持不变。

我觉得奇怪的是,没有人提到上面列出的所有方法在添加的方法和实例之间创建了一个循环引用,导致对象是持久的,直到垃圾回收机制。有一个老技巧通过扩展对象的类来添加描述符:

def addmethod(obj, name, func):klass = obj.__class__subclass = type(klass.__name__, (klass,), {})setattr(subclass, name, func)obj.__class__ = subclass
from types import MethodType
def method(self):print 'hi!'

setattr( targetObj, method.__name__, MethodType(method, targetObj, type(method)) )

有了这个,你可以使用自我指针

除了其他人所说的,我发现__repr____str__方法不能在对象级别上进行monkeypatch,因为repr()str()使用类方法,而不是局部有界对象方法:

# Instance monkeypatch[ins] In [55]: x.__str__ = show.__get__(x)
[ins] In [56]: xOut[56]: <__main__.X at 0x7fc207180c10>
[ins] In [57]: str(x)Out[57]: '<__main__.X object at 0x7fc207180c10>'
[ins] In [58]: x.__str__()Nice object!
# Class monkeypatch[ins] In [62]: X.__str__ = lambda _: "From class"
[ins] In [63]: str(x)Out[63]: 'From class'

如何从类的实例中恢复类

class UnderWater:def __init__(self):self.net = 'underwater'
marine = UnderWater() # Instantiate the class
# Recover the class from the instance and add attributes to it.class SubMarine(marine.__class__):def __init__(self):super().__init__()self.sound = 'Sonar'    
print(SubMarine, SubMarine.__name__, SubMarine().net, SubMarine().sound)
# Output# (__main__.SubMarine,'SubMarine', 'underwater', 'Sonar')

感谢阿图罗!你的回答让我走上了正轨!

基于Arturo的代码,我写了一个小类:

from types import MethodTypeimport refrom string import ascii_letters

class DynamicAttr:def __init__(self):self.dict_all_files = {}
def _copy_files(self, *args, **kwargs):print(f'copy {args[0]["filename"]} {args[0]["copy_command"]}')
def _delete_files(self, *args, **kwargs):print(f'delete {args[0]["filename"]} {args[0]["delete_command"]}')
def _create_properties(self):for key, item in self.dict_all_files.items():setattr(self,key,self.dict_all_files[key],)setattr(self,key + "_delete",MethodType(self._delete_files,{"filename": key,"delete_command": f'del {item}',},),)setattr(self,key + "_copy",MethodType(self._copy_files,{"filename": key,"copy_command": f'copy {item}',},),)def add_files_to_class(self, filelist: list):for _ in filelist:attr_key = re.sub(rf'[^{ascii_letters}]+', '_', _).strip('_')self.dict_all_files[attr_key] = _self._create_properties()dy = DynamicAttr()dy.add_files_to_class([r"C:\Windows\notepad.exe", r"C:\Windows\regedit.exe"])
dy.add_files_to_class([r"C:\Windows\HelpPane.exe", r"C:\Windows\win.ini"])#outputprint(dy.C_Windows_HelpPane_exe)dy.C_Windows_notepad_exe_delete()dy.C_Windows_HelpPane_exe_copy()C:\Windows\HelpPane.exedelete C_Windows_notepad_exe del C:\Windows\notepad.execopy C_Windows_HelpPane_exe copy C:\Windows\HelpPane.exe

结果

此类允许您随时添加新属性和方法。

编辑:

这里有一个更通用的解决方案:

import inspectimport refrom copy import deepcopyfrom string import ascii_letters

def copy_func(f):if callable(f):if inspect.ismethod(f) or inspect.isfunction(f):g = lambda *args, **kwargs: f(*args, **kwargs)t = list(filter(lambda prop: not ("__" in prop), dir(f)))i = 0while i < len(t):setattr(g, t[i], getattr(f, t[i]))i += 1return gdcoi = deepcopy([f])return dcoi[0]

class FlexiblePartial:def __init__(self, func, this_args_first, *args, **kwargs):
try:self.f = copy_func(func)  # create a copy of the functionexcept Exception:self.f = funcself.this_args_first = this_args_first  # where should the other (optional) arguments be that are passed when the function is calledtry:self.modulename = args[0].__class__.__name__  # to make repr look goodexcept Exception:self.modulename = "self"
try:self.functionname = func.__name__  # to make repr look goodexcept Exception:try:self.functionname = func.__qualname__  # to make repr look goodexcept Exception:self.functionname = "func"
self.args = argsself.kwargs = kwargs
self.name_to_print = self._create_name()  # to make repr look good
def _create_name(self):stra = self.modulename + "." + self.functionname + "(self, "for _ in self.args[1:]:stra = stra + repr(_) + ", "for key, item in self.kwargs.items():stra = stra + str(key) + "=" + repr(item) + ", "stra = stra.rstrip().rstrip(",")stra += ")"if len(stra) > 100:stra = stra[:95] + "...)"return stra
def __call__(self, *args, **kwargs):newdic = {}newdic.update(self.kwargs)newdic.update(kwargs)if self.this_args_first:return self.f(*self.args[1:], *args, **newdic)
else:
return self.f(*args, *self.args[1:], **newdic)
def __str__(self):return self.name_to_print
def __repr__(self):return self.__str__()

class AddMethodsAndProperties:def add_methods(self, dict_to_add):for key_, item in dict_to_add.items():key = re.sub(rf"[^{ascii_letters}]+", "_", str(key_)).rstrip("_")if isinstance(item, dict):if "function" in item:  # for adding methodsif not isinstance(item["function"], str):  # for external functions that are not part of the classsetattr(self,key,FlexiblePartial(item["function"],item["this_args_first"],self,*item["args"],**item["kwargs"],),)
else:setattr(self,key,FlexiblePartial(getattr(self, item["function"]),  # for internal functions - part of the classitem["this_args_first"],self,*item["args"],**item["kwargs"],),)else:  # for adding propssetattr(self, key, item)

让我们测试一下:

class NewClass(AddMethodsAndProperties): #inherit from AddMethodsAndProperties to add the method add_methodsdef __init__(self):self.bubu = 5
def _delete_files(self, file): #some random methodsprint(f"File will be deleted: {file}")
def delete_files(self, file):self._delete_files(file)
def _copy_files(self, file, dst):print(f"File will be copied: {file} Dest: {dst}")
def copy_files(self, file, dst):self._copy_files(file, dst)
def _create_files(self, file, folder):print(f"File will be created: {file} {folder}")
def create_files(self, file, folder):self._create_files(file, folder)
def method_with_more_kwargs(self, file, folder, one_more):print(file, folder, one_more)return self

nc = NewClass()dict_all_files = {r"C:\Windows\notepad.exe_delete": {"function": "delete_files","args": (),"kwargs": {"file": r"C:\Windows\notepad.exe"},"this_args_first": True,},r"C:\Windows\notepad.exe_argsfirst": {"function": "delete_files","args": (),"kwargs": {"file": r"C:\Windows\notepad.exe"},"this_args_first": True,},r"C:\Windows\notepad.exe_copy": {"function": "copy_files","args": (),"kwargs": {"file": r"C:\Windows\notepad.exe","dst": r"C:\Windows\notepad555.exe",},"this_args_first": True,},r"C:\Windows\notepad.exe_create": {"function": "create_files","args": (),"kwargs": {"file": r"C:\Windows\notepad.exe", "folder": "c:\\windows95"},"this_args_first": True,},r"C:\Windows\notepad.exe_upper": {"function": str.upper,"args": (r"C:\Windows\notepad.exe",),"kwargs": {},"this_args_first": True,},r"C:\Windows\notepad.exe_method_with_more_kwargs": {"function": "method_with_more_kwargs","args": (),"kwargs": {"file": r"C:\Windows\notepad.exe", "folder": "c:\\windows95"},"this_args_first": True,},r"C:\Windows\notepad.exe_method_with_more_kwargs_as_args_first": {"function": "method_with_more_kwargs","args": (r"C:\Windows\notepad.exe", "c:\\windows95"),"kwargs": {},"this_args_first": True,},r"C:\Windows\notepad.exe_method_with_more_kwargs_as_args_last": {"function": "method_with_more_kwargs","args": (r"C:\Windows\notepad.exe", "c:\\windows95"),"kwargs": {},"this_args_first": False,},"this_is_a_list": [55, 3, 3, 1, 4, 43],}
nc.add_methods(dict_all_files)

print(nc.C_Windows_notepad_exe_delete)print(nc.C_Windows_notepad_exe_delete(), end="\n\n")print(nc.C_Windows_notepad_exe_argsfirst)print(nc.C_Windows_notepad_exe_argsfirst(), end="\n\n")print(nc.C_Windows_notepad_exe_copy)print(nc.C_Windows_notepad_exe_copy(), end="\n\n")print(nc.C_Windows_notepad_exe_create)print(nc.C_Windows_notepad_exe_create(), end="\n\n")print(nc.C_Windows_notepad_exe_upper)print(nc.C_Windows_notepad_exe_upper(), end="\n\n")print(nc.C_Windows_notepad_exe_method_with_more_kwargs)print(nc.C_Windows_notepad_exe_method_with_more_kwargs(one_more="f:\\blaaaaaaaaaaaaaaaaaaaaaaaa").C_Windows_notepad_exe_method_with_more_kwargs(one_more="f:\\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ").C_Windows_notepad_exe_method_with_more_kwargs(one_more="f:\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),end="\n\n",)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_first)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_first("f:\\blaaaaaaaaaaaaaaaaaaaaaaaa"),end="\n\n",)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_first("f:\\blaaaaaaaaaaaaaaaaaaaaaaaa").C_Windows_notepad_exe_method_with_more_kwargs_as_args_first("f:\\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ").C_Windows_notepad_exe_method_with_more_kwargs_as_args_first("f:\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),end="\n\n",)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_last)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\blaaaaaaaaaaaaaaaaaaaaaaaa").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),end="\n\n",)print(nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\blaaaaaaaaaaaaaaaaaaaaaaaa").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),end="\n\n",)print(nc.this_is_a_list)checkit = (nc.C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\blaaaaaaaaaaaaaaaaaaaaaaaa").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ").C_Windows_notepad_exe_method_with_more_kwargs_as_args_last("f:\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))print(f'nc is checkit? -> {nc is checkit}')

#output:

NewClass.delete_files(self, file='C:\\Windows\\notepad.exe')File will be deleted: C:\Windows\notepad.exeNone

NewClass.delete_files(self, file='C:\\Windows\\notepad.exe')File will be deleted: C:\Windows\notepad.exeNone

NewClass.copy_files(self, file='C:\\Windows\\notepad.exe', dst='C:\\Windows\\notepad555.exe')File will be copied: C:\Windows\notepad.exe Dest: C:\Windows\notepad555.exeNone

NewClass.create_files(self, file='C:\\Windows\\notepad.exe', folder='c:\\windows95')File will be created: C:\Windows\notepad.exe c:\windows95None

NewClass.upper(self, 'C:\\Windows\\notepad.exe')C:\WINDOWS\NOTEPAD.EXE

NewClass.method_with_more_kwargs(self, file='C:\\Windows\\notepad.exe', folder='c:\\windows95')C:\Windows\notepad.exe c:\windows95 f:\blaaaaaaaaaaaaaaaaaaaaaaaaC:\Windows\notepad.exe c:\windows95 f:\ASJVASDFASÇDFJASÇDJFÇASWFJASÇC:\Windows\notepad.exe c:\windows95 f:\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<__main__.NewClass object at 0x0000000005F199A0>

NewClass.method_with_more_kwargs(self, 'C:\\Windows\\notepad.exe', 'c:\\windows95')C:\Windows\notepad.exe c:\windows95 f:\blaaaaaaaaaaaaaaaaaaaaaaaa<__main__.NewClass object at 0x0000000005F199A0>

C:\Windows\notepad.exe c:\windows95 f:\blaaaaaaaaaaaaaaaaaaaaaaaaC:\Windows\notepad.exe c:\windows95 f:\ASJVASDFASÇDFJASÇDJFÇASWFJASÇC:\Windows\notepad.exe c:\windows95 f:\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX<__main__.NewClass object at 0x0000000005F199A0>

NewClass.method_with_more_kwargs(self, 'C:\\Windows\\notepad.exe', 'c:\\windows95')f:\blaaaaaaaaaaaaaaaaaaaaaaaa C:\Windows\notepad.exe c:\windows95f:\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ C:\Windows\notepad.exe c:\windows95f:\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX C:\Windows\notepad.exe c:\windows95<__main__.NewClass object at 0x0000000005F199A0>

f:\blaaaaaaaaaaaaaaaaaaaaaaaa C:\Windows\notepad.exe c:\windows95f:\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ C:\Windows\notepad.exe c:\windows95f:\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX C:\Windows\notepad.exe c:\windows95<__main__.NewClass object at 0x0000000005F199A0>

[55, 3, 3, 1, 4, 43]

f:\blaaaaaaaaaaaaaaaaaaaaaaaa C:\Windows\notepad.exe c:\windows95f:\ASJVASDFASÇDFJASÇDJFÇASWFJASÇ C:\Windows\notepad.exe c:\windows95f:\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX C:\Windows\notepad.exe c:\windows95

nc is checkit? -> True