from fastcore.meta import method
09_method_funcs_kwargs
fastcore.meta.method
Reading Docs
#|export
def method(f):
"Mark `f` as a method"
# `1` is a dummy instance since Py3 doesn't allow `None` any more
return MethodType(f, 1)
The method function is used to change a function’s type to a method. In the below example we change the type of a from a function to a method:
def a(x=2): return x + 1
assert type(a).__name__ == 'function'
= method(a)
a assert type(a).__name__ == 'method'
Running codes
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
= method(a)
a assert type(a).__name__ == 'method'
Document
from fastdebug.utils import *
from fastdebug.core import *
from fastcore.meta import *
= Fastdb(method)
fdb = """
fdb.eg def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = method(a)
assert type(a).__name__ == 'method'
"""
print() fdb.
========================================================== Investigating method ==========================================================
============================================================== on line None ==============================================================
with example
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = method(a)
assert type(a).__name__ == 'method'
def method(f):============================================================================(0)
"Mark `f` as a method"================================================================(1)
# `1` is a dummy instance since Py3 doesn't allow `None` any more=====================(2)
return MethodType(f, 1)===============================================================(3)
(4)
2, "How to use fastcore.meta.method; method(function, instance); f needs to be a function; \
fdb.docsrc(1 is a dummy instance to which the newly created method belongs; no need to worry about instance here")
========================================================== Investigating method ==========================================================
=============================================================== on line 2 ================================================================
with example
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = method(a)
assert type(a).__name__ == 'method'
print selected srcline with expands below--------
def method(f): (0)
"Mark `f` as a method" (1)
# `1` is a dummy instance since Py3 doesn't allow `None` any more===================================================================================(2)
How to use fastcore.meta.method; method(function, instance); f needs to be a function; 1 is a dummy instance to which the newly created method belongs; no need to worry about instance here
return MethodType(f, 1) (3)
(4)
fdb.debug()
method's dbsrc code: ==============
import snoop
@snoop
def method(f):
"Mark `f` as a method"
# `1` is a dummy instance since Py3 doesn't allow `None` any more
return MethodType(f, 1)
method's example processed with dbsrc: ===============
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = method(a)
assert type(a).__name__ == 'method'
snoop
fdb.snoop()
22:28:59.92 >>> Call to method in File "/tmp/method.py", line 3
22:28:59.92 ...... f = <function a>
22:28:59.92 3 | def method(f):
22:28:59.92 6 | return MethodType(f, 1)
22:28:59.92 <<< Return value from method: <bound method int.a of 1>
========================================================== Investigating method ==========================================================
============================================================== on line None ==============================================================
with example
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = method(a)
assert type(a).__name__ == 'method'
fdb.debug()
method's dbsrc code: ==============
import snoop
@snoop
def method(f):
"Mark `f` as a method"
# `1` is a dummy instance since Py3 doesn't allow `None` any more
return MethodType(f, 1)
method's example processed with dbsrc: ===============
def a(x=2): return x + 1
assert type(a).__name__ == 'function' # how to test on the type of function or method
a = self.dbsrc(a)
assert type(a).__name__ == 'method'
funcs_kwargs
Official docs
The func_kwargs decorator allows you to add a list of functions or methods to an existing class. You must set this list as a class attribute named _methods when defining your class. Additionally, you must incldue the **kwargs
argument in the ___init__ method of your class.
After defining your class this way, you can add functions to your class upon instantation as illusrated below.
For example, we define class T to allow adding the function b to class T as follows (note that this function is stored as an attribute of T and doesn’t have access to cls or self):
@funcs_kwargs
class T:
=['b'] # allows you to add method b upon instantiation
_methodsdef __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
= T()
t 1)
test_eq(t.a(), 2)
test_eq(t.b(),
'(f=1, *, b=None)')
test_sig(T,
inspect.signature(T)
def _new_func(): return 5
= T(b = _new_func)
t 5)
test_eq(t.b(),
= T(a = lambda:3)
t 1) # the attempt to add a is ignored and uses the original method instead. test_eq(t.a(),
snoop: from _funcs_kwargs to funcs_kwargs
how to snoop on two functions one wrap around another: funcs_kwargs
is a wrapper around _funcs_kwargs
, so I can first snoop on _funcs_kwargs
and assign its snoop dbsrc to
fm._funcs_kwargs
so that when I snoop on funcs_kwargs
, it can use the snoop dbsrc of _funcs_kwargs
and no example codes need to change.
from fastcore.meta import _funcs_kwargs
= Fastdb(_funcs_kwargs)
fdb_ = """
fdb_.eg @funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
"""
# no snoop result, it is expected, because the example is not calling _funcs_kwargs, but funcs_kwargs
=True) # how to snoop decorator: _funcs_kwargs is a decorator, so set deco=True to see running codes in inner f fdb_.snoop(deco
====================================================== Investigating _funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
import fastcore.meta as fm
= fdb_.dbsrc # how to snoop on two functions one wrap around another fm._funcs_kwargs
= Fastdb(funcs_kwargs)
fdb = """
fdb.eg @funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
"""
print() fdb.
======================================================= Investigating funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
def funcs_kwargs(as_method=False):========================================================(0)
"Replace methods in `cls._methods` with those from `kwargs`"==========================(1)
if callable(as_method): return _funcs_kwargs(as_method, False)========================(2)
return partial(_funcs_kwargs, as_method=as_method)====================================(3)
(4)
print() fdb_.
====================================================== Investigating _funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _funcs_kwargs(cls, as_method):========================================================(0)
old_init = cls.__init__===============================================================(1)
def _init(self, *args, **kwargs):=====================================================(2)
for k in cls._methods:============================================================(3)
arg = kwargs.pop(k,None)======================================================(4)
if arg is not None:===========================================================(5)
if as_method: arg = method(arg)===========================================(6)
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)=======(7)
setattr(self, k, arg)=====================================================(8)
old_init(self, *args, **kwargs)===================================================(9)
functools.update_wrapper(_init, old_init)=============================================(10)
cls.__init__ = use_kwargs(cls._methods)(_init)========================================(11)
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__)) (12)
return cls============================================================================(13)
(14)
1, "how funcs_kwargs works; it is a wrapper around _funcs_kwargs; it offers two ways of running _funcs_kwargs; \
fdb.docsrc(the first, default way, is to add a func to a class without using self; second way is to add func to class enabling self use;")
2, "how to check whether an object is callable; how to return a result of running a func; ")
fdb.docsrc(3, "how to custom the params of `_funcs_kwargs` for a particular use with partial") fdb.docsrc(
======================================================= Investigating funcs_kwargs =======================================================
=============================================================== on line 1 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
print selected srcline with expands below--------
def funcs_kwargs(as_method=False): (0)
"Replace methods in `cls._methods` with those from `kwargs`"========================================================================================(1)
how funcs_kwargs works; it is a wrapper around _funcs_kwargs; it offers two ways of running _funcs_kwargs; the first, default way, is to add a func to a class without using self; second way is to add func to class enabling self use;
if callable(as_method): return _funcs_kwargs(as_method, False) (2)
return partial(_funcs_kwargs, as_method=as_method) (3)
======================================================= Investigating funcs_kwargs =======================================================
=============================================================== on line 2 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
print selected srcline with expands below--------
def funcs_kwargs(as_method=False): (0)
"Replace methods in `cls._methods` with those from `kwargs`" (1)
if callable(as_method): return _funcs_kwargs(as_method, False)======================================================================================(2)
how to check whether an object is callable; how to return a result of running a func;
return partial(_funcs_kwargs, as_method=as_method) (3)
(4)
======================================================= Investigating funcs_kwargs =======================================================
=============================================================== on line 3 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
print selected srcline with expands below--------
"Replace methods in `cls._methods` with those from `kwargs`" (1)
if callable(as_method): return _funcs_kwargs(as_method, False) (2)
return partial(_funcs_kwargs, as_method=as_method)==================================================================================================(3)
how to custom the params of `_funcs_kwargs` for a particular use with partial
(4)
print() fdb_.
====================================================== Investigating _funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _funcs_kwargs(cls, as_method):========================================================(0)
old_init = cls.__init__===============================================================(1)
def _init(self, *args, **kwargs):=====================================================(2)
for k in cls._methods:============================================================(3)
arg = kwargs.pop(k,None)======================================================(4)
if arg is not None:===========================================================(5)
if as_method: arg = method(arg)===========================================(6)
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)=======(7)
setattr(self, k, arg)=====================================================(8)
old_init(self, *args, **kwargs)===================================================(9)
functools.update_wrapper(_init, old_init)=============================================(10)
cls.__init__ = use_kwargs(cls._methods)(_init)========================================(11)
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__)) (12)
return cls============================================================================(13)
(14)
0, "how does _funcs_kwargs work: _funcs_kwargs is a decorator; it helps class e.g., T to add more methods; \
fdb_.docsrc(I need to give the method a name, \
and put the name e.g., 'b' inside a list called _methods=['b'] inside class T; \
then after writing a func e.g., _new_func, I can add it by T(b = _new_func); if I want the func added to class to use self, \
I shall write @funcs_kwargs(as_method=True)")
2, "how to define a method which can use self and accept any parameters")
fdb_.docsrc(3, "how to pop out the value of an item in a dict (with None as default), and if the item name is not found, pop out None instead; ")
fdb_.docsrc(6, "how to turn a func into a method")
fdb_.docsrc(7, "how to give a method a different instance, like self")
fdb_.docsrc(8, "how to add a method to a class as an attribute")
fdb_.docsrc(10, "how to wrap `_init` around `old_init`, so that `_init` can use `old_init` inside itself")
fdb_.docsrc(11, "how to add a list of names with None as default value to function `_init` to repalce its kwargs param")
fdb_.docsrc(12, "how to make a class.`__init__` signature to be the signature of the class using `__signature__` and `_rm_self`") fdb_.docsrc(
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 0 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
def _funcs_kwargs(cls, as_method):======================================================================================================================(0)
how does _funcs_kwargs work: _funcs_kwargs is a decorator; it helps class e.g., T to add more methods; I need to give the method a name, and put the name e.g., 'b' inside a list called _methods=['b'] inside class T; then after writing a func e.g., _new_func, I can add it by T(b = _new_func); if I want the func added to class to use self, I shall write @funcs_kwargs(as_method=True)
old_init = cls.__init__ (1)
def _init(self, *args, **kwargs): (2)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 2 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
def _funcs_kwargs(cls, as_method): (0)
old_init = cls.__init__ (1)
def _init(self, *args, **kwargs):===================================================================================================================(2)
how to define a method which can use self and accept any parameters
for k in cls._methods: (3)
arg = kwargs.pop(k,None) (4)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 3 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
old_init = cls.__init__ (1)
def _init(self, *args, **kwargs): (2)
for k in cls._methods:==========================================================================================================================(3)
how to pop out the value of an item in a dict (with None as default), and if the item name is not found, pop out None instead;
arg = kwargs.pop(k,None) (4)
if arg is not None: (5)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 6 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
arg = kwargs.pop(k,None) (4)
if arg is not None: (5)
if as_method: arg = method(arg)=========================================================================================================(6)
how to turn a func into a method
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self) (7)
setattr(self, k, arg) (8)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 7 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
if arg is not None: (5)
if as_method: arg = method(arg) (6)
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)=====================================================================(7)
how to give a method a different instance, like self
setattr(self, k, arg) (8)
old_init(self, *args, **kwargs) (9)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 8 ================================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
if as_method: arg = method(arg) (6)
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self) (7)
setattr(self, k, arg)===================================================================================================================(8)
how to add a method to a class as an attribute
old_init(self, *args, **kwargs) (9)
functools.update_wrapper(_init, old_init) (10)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 10 ===============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
setattr(self, k, arg) (8)
old_init(self, *args, **kwargs) (9)
functools.update_wrapper(_init, old_init)===========================================================================================================(10)
how to wrap `_init` around `old_init`, so that `_init` can use `old_init` inside itself
cls.__init__ = use_kwargs(cls._methods)(_init) (11)
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__)) (12)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 11 ===============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
old_init(self, *args, **kwargs) (9)
functools.update_wrapper(_init, old_init) (10)
cls.__init__ = use_kwargs(cls._methods)(_init)======================================================================================================(11)
how to add a list of names with None as default value to function `_init` to repalce its kwargs param
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__)) (12)
return cls (13)
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 12 ===============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print selected srcline with expands below--------
functools.update_wrapper(_init, old_init) (10)
cls.__init__ = use_kwargs(cls._methods)(_init) (11)
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__))=====================================================(12)
how to make a class.`__init__` signature to be the signature of the class using `__signature__` and `_rm_self`
return cls (13)
(14)
# how to snoop together with docsrc: snoop first and docsrc above it fdb.snoop()
22:28:59.99 >>> Call to funcs_kwargs in File "/tmp/funcs_kwargs.py", line 3
22:28:59.99 ...... as_method = <class 'fastcore.meta.T'>
22:28:59.99 3 | def funcs_kwargs(as_method=False):
22:28:59.99 5 | if callable(as_method): return _funcs_kwargs(as_method, False)
22:28:59.99 >>> Call to _funcs_kwargs in File "/tmp/_funcs_kwargs.py", line 3
22:28:59.99 ...... cls = <class 'fastcore.meta.T'>
22:28:59.99 ...... as_method = False
22:28:59.99 3 | def _funcs_kwargs(cls, as_method):
22:28:59.99 4 | old_init = cls.__init__
22:28:59.99 .......... old_init = <function T.__init__>
22:28:59.99 5 | import snoop
22:28:59.99 .......... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
22:28:59.99 6 | @snoop
22:28:59.99 7 | def _init(self, *args, **kwargs):
22:28:59.99 .......... _init = <function _funcs_kwargs.<locals>._init>
22:28:59.99 15 | functools.update_wrapper(_init, old_init)
22:28:59.99 .......... _init = <function T.__init__>
22:28:59.99 16 | cls.__init__ = use_kwargs(cls._methods)(_init)
22:28:59.99 17 | if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__))
22:28:59.99 18 | return cls
22:28:59.99 <<< Return value from _funcs_kwargs: <class 'fastcore.meta.T'>
22:28:59.99 5 | if callable(as_method): return _funcs_kwargs(as_method, False)
22:28:59.99 <<< Return value from funcs_kwargs: <class 'fastcore.meta.T'>
22:28:59.99 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:28:59.99 .......... self = <fastcore.meta.T object>
22:28:59.99 .......... args = ()
22:28:59.99 .......... kwargs = {}
22:28:59.99 .......... as_method = False
22:28:59.99 .......... cls = <class 'fastcore.meta.T'>
22:28:59.99 .......... old_init = <function T.__init__>
22:28:59.99 7 | def _init(self, *args, **kwargs):
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 .............. k = 'b'
22:29:00.00 9 | arg = kwargs.pop(k,None)
22:29:00.00 .................. arg = None
22:29:00.00 10 | if arg is not None:
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 14 | old_init(self, *args, **kwargs)
22:29:00.00 <<< Return value from _funcs_kwargs.<locals>._init: None
22:29:00.00 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:29:00.00 .......... self = <fastcore.meta.T object>
22:29:00.00 .......... args = ()
22:29:00.00 .......... kwargs = {'b': <function _new_func>}
22:29:00.00 .......... len(kwargs) = 1
22:29:00.00 .......... as_method = False
22:29:00.00 .......... cls = <class 'fastcore.meta.T'>
22:29:00.00 .......... old_init = <function T.__init__>
22:29:00.00 7 | def _init(self, *args, **kwargs):
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 .............. k = 'b'
22:29:00.00 9 | arg = kwargs.pop(k,None)
22:29:00.00 .................. kwargs = {}
22:29:00.00 .................. arg = <function _new_func>
22:29:00.00 10 | if arg is not None:
22:29:00.00 11 | if as_method: arg = method(arg)
22:29:00.00 12 | if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)
22:29:00.00 13 | setattr(self, k, arg)
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 14 | old_init(self, *args, **kwargs)
22:29:00.00 <<< Return value from _funcs_kwargs.<locals>._init: None
22:29:00.00 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:29:00.00 .......... self = <fastcore.meta.T object>
22:29:00.00 .......... args = ()
22:29:00.00 .......... kwargs = {'a': <function <lambda>>}
22:29:00.00 .......... len(kwargs) = 1
22:29:00.00 .......... as_method = False
22:29:00.00 .......... cls = <class 'fastcore.meta.T'>
22:29:00.00 .......... old_init = <function T.__init__>
22:29:00.00 7 | def _init(self, *args, **kwargs):
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 .............. k = 'b'
22:29:00.00 9 | arg = kwargs.pop(k,None)
22:29:00.00 .................. arg = None
22:29:00.00 10 | if arg is not None:
22:29:00.00 8 | for k in cls._methods:
22:29:00.00 14 | old_init(self, *args, **kwargs)
22:29:00.00 <<< Return value from _funcs_kwargs.<locals>._init: None
22:29:00.00 >>> Call to funcs_kwargs in File "/tmp/funcs_kwargs.py", line 3
22:29:00.00 ...... as_method = True
22:29:00.00 3 | def funcs_kwargs(as_method=False):
22:29:00.00 5 | if callable(as_method): return _funcs_kwargs(as_method, False)
22:29:00.00 6 | return partial(_funcs_kwargs, as_method=as_method)
22:29:00.00 <<< Return value from funcs_kwargs: functools.partial(<function _funcs_kwargs>, as_method=True)
22:29:00.00 >>> Call to _funcs_kwargs in File "/tmp/_funcs_kwargs.py", line 3
22:29:00.00 ...... cls = <class 'fastcore.meta.T'>
22:29:00.00 ...... as_method = True
22:29:00.00 3 | def _funcs_kwargs(cls, as_method):
22:29:00.00 4 | old_init = cls.__init__
22:29:00.00 .......... old_init = <slot wrapper '__init__' of 'object' objects>
22:29:00.00 5 | import snoop
22:29:00.00 .......... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
22:29:00.00 6 | @snoop
22:29:00.00 7 | def _init(self, *args, **kwargs):
22:29:00.00 .......... _init = <function _funcs_kwargs.<locals>._init>
22:29:00.00 15 | functools.update_wrapper(_init, old_init)
22:29:00.00 .......... _init = <function object.__init__>
22:29:00.00 16 | cls.__init__ = use_kwargs(cls._methods)(_init)
22:29:00.01 17 | if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__))
22:29:00.01 18 | return cls
22:29:00.01 <<< Return value from _funcs_kwargs: <class 'fastcore.meta.T'>
22:29:00.01 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:29:00.01 .......... self = <fastcore.meta.T object>
22:29:00.01 .......... args = ()
22:29:00.01 .......... kwargs = {'b': <function _f>}
22:29:00.01 .......... len(kwargs) = 1
22:29:00.01 .......... as_method = True
22:29:00.01 .......... cls = <class 'fastcore.meta.T'>
22:29:00.01 .......... old_init = <slot wrapper '__init__' of 'object' objects>
22:29:00.01 7 | def _init(self, *args, **kwargs):
22:29:00.01 8 | for k in cls._methods:
22:29:00.01 .............. k = 'b'
22:29:00.01 9 | arg = kwargs.pop(k,None)
22:29:00.01 .................. kwargs = {}
22:29:00.01 .................. arg = <function _f>
22:29:00.01 10 | if arg is not None:
22:29:00.01 11 | if as_method: arg = method(arg)
22:29:00.01 ...... arg = <bound method int._f of 1>
22:29:00.01 12 | if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)
22:29:00.01 ...... arg = <bound method T._f of <fastcore.meta.T object>>
22:29:00.01 13 | setattr(self, k, arg)
22:29:00.01 8 | for k in cls._methods:
22:29:00.01 14 | old_init(self, *args, **kwargs)
22:29:00.01 <<< Return value from _funcs_kwargs.<locals>._init: None
22:29:00.01 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:29:00.01 .......... self = <fastcore.meta.T2 object>
22:29:00.01 .......... args = ()
22:29:00.01 .......... kwargs = {'b': <function _f>}
22:29:00.01 .......... len(kwargs) = 1
22:29:00.01 .......... as_method = True
22:29:00.01 .......... cls = <class 'fastcore.meta.T'>
22:29:00.01 .......... old_init = <slot wrapper '__init__' of 'object' objects>
22:29:00.01 7 | def _init(self, *args, **kwargs):
22:29:00.01 8 | for k in cls._methods:
22:29:00.01 .............. k = 'b'
22:29:00.01 9 | arg = kwargs.pop(k,None)
22:29:00.01 .................. kwargs = {}
22:29:00.01 .................. arg = <function _f>
22:29:00.01 10 | if arg is not None:
22:29:00.01 11 | if as_method: arg = method(arg)
22:29:00.01 ...... arg = <bound method int._f of 1>
22:29:00.01 12 | if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)
22:29:00.01 ...... arg = <bound method T2._f of <fastcore.meta.T2 object>>
22:29:00.01 13 | setattr(self, k, arg)
22:29:00.01 8 | for k in cls._methods:
22:29:00.01 14 | old_init(self, *args, **kwargs)
22:29:00.01 <<< Return value from _funcs_kwargs.<locals>._init: None
======================================================= Investigating funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
fdb_.debug()
_funcs_kwargs's dbsrc code: ==============
import snoop
@snoop
def _funcs_kwargs(cls, as_method):
old_init = cls.__init__
import snoop
@snoop
def _init(self, *args, **kwargs):
for k in cls._methods:
arg = kwargs.pop(k,None)
if arg is not None:
if as_method: arg = method(arg)
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)
setattr(self, k, arg)
old_init(self, *args, **kwargs)
functools.update_wrapper(_init, old_init)
cls.__init__ = use_kwargs(cls._methods)(_init)
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__))
return cls
_funcs_kwargs's example processed with dbsrc: ===============
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
print() fdb.
======================================================= Investigating funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _f(self,a=1): return self.num + a # access the num attribute from the instance
@funcs_kwargs(as_method=True)
class T:
_methods=['b']
num = 5
t = T(b = _f) # adds method b
test_eq(t.b(5), 10) # self.num + 5 = 10
def _f(self,a=1): return self.num * a #multiply instead of add
class T2(T):
def __init__(self,num):
super().__init__(b = _f) # add method b from the super class
self.num=num
t = T2(num=3)
test_eq(t.b(a=5), 15) # 3 * 5 = 15
test_sig(T2, '(num)')
def funcs_kwargs(as_method=False):========================================================(0)
"Replace methods in `cls._methods` with those from `kwargs`"==========================(1) # how funcs_kwargs works; it is a wrapper around _funcs_kwargs; it offers two ways of running _funcs_kwargs; the first, default way, is to add a func to a class without using self; second way is to add func to class enabling self use;;
if callable(as_method): return _funcs_kwargs(as_method, False)========================(2) # how to check whether an object is callable; how to return a result of running a func; ;
return partial(_funcs_kwargs, as_method=as_method)====================================(3) # how to custom the params of `_funcs_kwargs` for a particular use with partial;
(4)
print() fdb_.
====================================================== Investigating _funcs_kwargs =======================================================
=============================================================== on line 12 ===============================================================
with example
@funcs_kwargs
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = T()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
def _new_func(): return 5
t = T(b = _new_func)
test_eq(t.b(), 5)
t = T(a = lambda:3)
test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
def _funcs_kwargs(cls, as_method):========================================================(0) # how does _funcs_kwargs work: _funcs_kwargs is a decorator; it helps class e.g., T to add more methods; I need to give the method a name, and put the name e.g., 'b' inside a list called _methods=['b'] inside class T; then after writing a func e.g., _new_func, I can add it by T(b = _new_func); if I want the func added to class to use self, I shall write @funcs_kwargs(as_method=True);
old_init = cls.__init__===============================================================(1)
def _init(self, *args, **kwargs):=====================================================(2) # how to define a method which can use self and accept any parameters;
for k in cls._methods:============================================================(3) # how to pop out the value of an item in a dict (with None as default), and if the item name is not found, pop out None instead; ;
arg = kwargs.pop(k,None)======================================================(4)
if arg is not None:===========================================================(5)
if as_method: arg = method(arg)===========================================(6) # how to turn a func into a method;
if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)=======(7) # how to give a method a different instance, like self;
setattr(self, k, arg)=====================================================(8) # how to add a method to a class as an attribute;
old_init(self, *args, **kwargs)===================================================(9)
functools.update_wrapper(_init, old_init)=============================================(10) # how to wrap `_init` around `old_init`, so that `_init` can use `old_init` inside itself;
cls.__init__ = use_kwargs(cls._methods)(_init)========================================(11) # how to add a list of names with None as default value to function `_init` to repalce its kwargs param;
if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__)) # how to make a class.`__init__` signature to be the signature of the class using `__signature__` and `_rm_self`; (12)
return cls============================================================================(13)
(14)
snoop only ’_funcs_kwargs’ by breaking up ‘funcs_kwargs’
I could do it this way, but I have to change more codes which leads to more efforts and potential errors. So not recommended.
= Fastdb(funcs_kwargs)
fdb = Fastdb(_funcs_kwargs) fdb_
= """
fdb_.eg
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
t = _funcs_kwargs(T, False)()
test_eq(t.a(), 1)
test_eq(t.b(), 2)
test_sig(T, '(f=1, *, b=None)')
inspect.signature(T)
"""
= """
fdb_.eg class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
def _new_func(): return 5
t = _funcs_kwargs(T, False)(b = _new_func)
test_eq(t.b(), 5)
"""
# fdb_.eg = """
# class T:
# _methods=['b'] # allows you to add method b upon instantiation
# def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
# def a(self): return 1
# def b(self): return 2
# t = _funcs_kwargs(T, False)(a = lambda:3)
# test_eq(t.a(), 1) # the attempt to add a is ignored and uses the original method instead.
# """
=["cls.__init__"], deco=True) # can't do this expression fdb_.snoop(watch
22:29:00.04 >>> Call to _funcs_kwargs in File "/tmp/_funcs_kwargs.py", line 3
22:29:00.04 ...... cls = <class 'fastcore.meta.T'>
22:29:00.04 ...... as_method = False
22:29:00.04 3 | def _funcs_kwargs(cls, as_method):
22:29:00.04 4 | old_init = cls.__init__
22:29:00.05 .......... old_init = <function T.__init__>
22:29:00.05 5 | import snoop
22:29:00.05 .......... snoop = <class 'snoop.configuration.Config.__init__.<locals>.ConfiguredTracer'>
22:29:00.05 6 | @snoop
22:29:00.05 7 | def _init(self, *args, **kwargs):
22:29:00.05 .......... _init = <function _funcs_kwargs.<locals>._init>
22:29:00.05 15 | functools.update_wrapper(_init, old_init)
22:29:00.05 .......... _init = <function T.__init__>
22:29:00.05 16 | cls.__init__ = use_kwargs(cls._methods)(_init)
22:29:00.05 17 | if hasattr(cls, '__signature__'): cls.__signature__ = _rm_self(inspect.signature(cls.__init__))
22:29:00.05 18 | return cls
22:29:00.05 <<< Return value from _funcs_kwargs: <class 'fastcore.meta.T'>
22:29:00.05 >>> Call to _funcs_kwargs.<locals>._init in File "/tmp/_funcs_kwargs.py", line 7
22:29:00.05 .......... self = <fastcore.meta.T object>
22:29:00.05 .......... args = ()
22:29:00.05 .......... kwargs = {'b': <function _new_func>}
22:29:00.05 .......... len(kwargs) = 1
22:29:00.05 .......... as_method = False
22:29:00.05 .......... cls = <class 'fastcore.meta.T'>
22:29:00.05 .......... old_init = <function T.__init__>
22:29:00.05 7 | def _init(self, *args, **kwargs):
22:29:00.05 8 | for k in cls._methods:
22:29:00.05 .............. k = 'b'
22:29:00.05 9 | arg = kwargs.pop(k,None)
22:29:00.05 .................. kwargs = {}
22:29:00.05 .................. arg = <function _new_func>
22:29:00.05 10 | if arg is not None:
22:29:00.05 11 | if as_method: arg = method(arg)
22:29:00.05 12 | if isinstance(arg,MethodType): arg = MethodType(arg.__func__, self)
22:29:00.05 13 | setattr(self, k, arg)
22:29:00.05 8 | for k in cls._methods:
22:29:00.05 14 | old_init(self, *args, **kwargs)
22:29:00.05 <<< Return value from _funcs_kwargs.<locals>._init: None
====================================================== Investigating _funcs_kwargs =======================================================
============================================================== on line None ==============================================================
with example
class T:
_methods=['b'] # allows you to add method b upon instantiation
def __init__(self, f=1, **kwargs): pass # don't forget to include **kwargs in __init__
def a(self): return 1
def b(self): return 2
def _new_func(): return 5
t = _funcs_kwargs(T, False)(b = _new_func)
test_eq(t.b(), 5)