使用 __setattr__ 重写库的整个方法 class 问题:缺少 1 个必需的位置参数:'self'
Usage of __setattr__ to rewrite whole method of library class issue: missing 1 required positional argument: 'self'
我有一些结构复杂的导入包
并且需要调用一些基于许多其他方法的方法
具有非默认参数,这些参数本身不像 sklearn 中的管道那样 class 属性。
此模块结构的最小示例:
class Library_class:
def __init__(
self,
defined_class_options,
):
self.defined_class_options = defined_class_options
def method1( self , default_non_class_arg = 12 ):
assert self.defined_class_options==3
return default_non_class_arg
def method2( self, image ):
return image/ self.method1()
默认用法:
class_instance = Library_class( 3 )
class_instance.method2( 36 )
> 3.0
例如我需要将default_non_class_arg设置为6。
我尝试了多种方法:
- 类似于
class_instance.method2( 36 ,
method1__default_non_class_arg=3 )
TypeError: method2() got an unexpected keyword argument 'method1__default_non_class_arg'
它不起作用可能是因为 class 绝对没有 set_params
- 使用 setattr 重新定义函数
class_instance.__setattr__('method1',Library_class.new_method1)
class_instance.method2( 36 )
TypeError: new_method1() missing 1 required positional argument: 'self'
你的片段和问题都非常混乱,几乎无法阅读。
无论如何,如果您想用另一个函数替换 method1
,例如在特定实例中说 new_method1
,就这样做。您对 .__setattr__
的调用可以做到这一点,但根本不需要它(如果需要,因为您没有在编写代码时替换名称的方法,并且需要它作为参数,它是调用 built-in setattr
而不是实例方法更正确:`setattr(class_instance, "method1", new_method1").
通常,如果您知道,在编写代码时必须替换实例中的“method1”,赋值运算符会执行此操作:
class_instance.method1 = new_method1
你的例子中出了什么问题是,如果你将一个方法分配给一个实例,而不是 class,你就绕过了 Python 用来插入 [=18= 的机制] 属性 - 所以你的 new_method1 需要一个不同的签名。 (这正是错误消息“TypeError: new_method1() missing 1 required positional argument: 'self'”的意思):
class MyClass:
...
def method1(self, param1=36):
...
...
def new_method1(param1=6): # <-- written outside of any class body, sans self
...
my_instance = MyClass()
my_instance.method1 = new_method1
这会奏效。
new_method1
也可以写在 class 主体中,并且可以同样替换,但是你必须在没有 self
参数的情况下编写它,然后就不会了像正常方法一样直接工作。
或者,您可以在赋值时自己插入 self
参数 - functools.partial
调用是一种方便的方法:
class 我的班级:
...
def method1(self, param1=36):
...
def new_method1(self, param1=6):
...
...
my_instance = MyClass()
从 functools 导入部分
MyClass.method1 = partial(MyClass.new_method1, my_instance)
现在,这应该可以回答您的问题,但我不诚实地结束回答而不说这不是一个好的设计是不诚实的。最好的办法是从另一个地方提取参数,它可能来自实例属性,而不是完全替换方法只是为了更改它。
因为对于普通属性,如果没有实例属性存在,Python将读取class属性,它会自然发生,你所要做的就是在你的文件中设置新的默认值实例.
class MyClass:
default_param_1 = 36 # Class attribute. Valid for every instance unless overriden
...
def method1(self, param1=None):
if param1 is None:
param1 = self.default_param_1 #Automatically fetched from the class if not set on the instance
...
...
my_instance = MyClass()
my_instance.default_param_1 = 6
...
我有一些结构复杂的导入包 并且需要调用一些基于许多其他方法的方法 具有非默认参数,这些参数本身不像 sklearn 中的管道那样 class 属性。
此模块结构的最小示例:
class Library_class:
def __init__(
self,
defined_class_options,
):
self.defined_class_options = defined_class_options
def method1( self , default_non_class_arg = 12 ):
assert self.defined_class_options==3
return default_non_class_arg
def method2( self, image ):
return image/ self.method1()
默认用法:
class_instance = Library_class( 3 )
class_instance.method2( 36 )
> 3.0
例如我需要将default_non_class_arg设置为6。
我尝试了多种方法:
- 类似于
class_instance.method2( 36 ,
method1__default_non_class_arg=3 )
TypeError: method2() got an unexpected keyword argument 'method1__default_non_class_arg'
它不起作用可能是因为 class 绝对没有 set_params
- 使用 setattr 重新定义函数
class_instance.__setattr__('method1',Library_class.new_method1)
class_instance.method2( 36 )
TypeError: new_method1() missing 1 required positional argument: 'self'
你的片段和问题都非常混乱,几乎无法阅读。
无论如何,如果您想用另一个函数替换 method1
,例如在特定实例中说 new_method1
,就这样做。您对 .__setattr__
的调用可以做到这一点,但根本不需要它(如果需要,因为您没有在编写代码时替换名称的方法,并且需要它作为参数,它是调用 built-in setattr
而不是实例方法更正确:`setattr(class_instance, "method1", new_method1").
通常,如果您知道,在编写代码时必须替换实例中的“method1”,赋值运算符会执行此操作:
class_instance.method1 = new_method1
你的例子中出了什么问题是,如果你将一个方法分配给一个实例,而不是 class,你就绕过了 Python 用来插入 [=18= 的机制] 属性 - 所以你的 new_method1 需要一个不同的签名。 (这正是错误消息“TypeError: new_method1() missing 1 required positional argument: 'self'”的意思):
class MyClass:
...
def method1(self, param1=36):
...
...
def new_method1(param1=6): # <-- written outside of any class body, sans self
...
my_instance = MyClass()
my_instance.method1 = new_method1
这会奏效。
new_method1
也可以写在 class 主体中,并且可以同样替换,但是你必须在没有 self
参数的情况下编写它,然后就不会了像正常方法一样直接工作。
或者,您可以在赋值时自己插入 self
参数 - functools.partial
调用是一种方便的方法:
class 我的班级: ... def method1(self, param1=36): ...
def new_method1(self, param1=6):
...
...
my_instance = MyClass()
从 functools 导入部分 MyClass.method1 = partial(MyClass.new_method1, my_instance)
现在,这应该可以回答您的问题,但我不诚实地结束回答而不说这不是一个好的设计是不诚实的。最好的办法是从另一个地方提取参数,它可能来自实例属性,而不是完全替换方法只是为了更改它。
因为对于普通属性,如果没有实例属性存在,Python将读取class属性,它会自然发生,你所要做的就是在你的文件中设置新的默认值实例.
class MyClass:
default_param_1 = 36 # Class attribute. Valid for every instance unless overriden
...
def method1(self, param1=None):
if param1 is None:
param1 = self.default_param_1 #Automatically fetched from the class if not set on the instance
...
...
my_instance = MyClass()
my_instance.default_param_1 = 6
...