在继承自 int 或 float 或 str 的 class 中设置参数的值
Set the value of an argument in a class who inherits from int or float or str
当我尝试设置继承自 str
的 class 的参数值时出现错误。仅当我尝试使用 myClass(arg = 'test')
访问参数时才会发生错误。错误是:
TypeError: 'arg' is an invalid keyword argument for this function
此示例中显示了问题:
class A(str):
def __init__(self, arg):
pass
A("test") # Works well
A(arg = "test") # Fails
只有最后一行引发错误。上一行效果很好。
问题与继承自 int
或 float
的 classes 相同。
更新(解决方案):
我找到了使用这些 link 的解决方案:
- Adding optional parameters to the constructors of multiply-inheriting subclasses of built-in types?
- inheritance from str or int
解决方法是:
class A(str):
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
def __init__(self, arg01):
print(arg01)
A(arg01= "test")
我不知道为什么会这样,我会对此进行调查。如果有人有明确的解释,我很感兴趣,我提前感谢他。
更新(我的解释):
我完全不确定我会说什么,但这就是我的理解。
想象一下没有任何继承的 class 'myClass'
。
当我这样做 myInstance = myClass()
时,会发生以下情况:
方法myClass.__new__
被执行。此方法将创建对象 myInstance
。 __new__
是真正的构造函数(__init__
不是构造函数!)。在伪代码中,__new__
看起来像这样:
def __new__ (cls, *args, **kwargs):
myInstance = # Do some stuff to create myInstance, an object of the type passed as argument (cls).
# Add the method __init__ to myInstance.
# Call __init__ and pass to it the list 'args' and the dictionary 'kwargs' (both come from arguments of __new__). Pass to it also the object itself (self) :
obj.__init__(self, args, kwargs) :
# Do some stuff.
当我们使用不可变类型(str、int、float、tuple)时,情况有点不同。在前面的伪代码中,我写了def __new__(cls, *args, **kwargs)
。对于不可变类型,方法 __new__
的伪代码更像这样 def __new__(cls, anUniqueValue)
。我真的不明白为什么 immutableTypes.__new__
的行为与其他人不同,但事实就是如此。你可以在这个例子中看到它:
class foo():
def __init__(self):
pass
foo.__new__(foo, arg = 1)
# That works because the method __new__ look like this : def __new__(*args, **kargs).
str.__new__(str, arg = 1)
# That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue).
从那里,我们可以理解为什么前面提出的解决方案有效。我们所做的是编辑不可变类型的方法 __new__
,使其像可变类型一样工作。
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
这两行将 def __new__ (cls, anUniqueValue)
转换为 def __new__ (cls, *args, **kwargs)
我希望我的解释几乎清楚,没有那么多错误。如果你说法语,你可以了解更多 link : http://sametmax.com/la-difference-entre-new-et-init-en-python/
你写的基本上是对的,有一些错误。
class A(str):
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
def __init__(self, arg01):
print(arg01)
这并不完全正确:如果您不向 str.__new__
传递任何参数,您的新实例将相当于一个空字符串。
class A(str):
def __new__(cls, arg):
return str.__new__(cls, arg)
def __init__(self, arg):
print(arg)
一般来说,__new__
和__init__
应该有相同的签名。这不是必需的,但在这种情况下,您需要将 arg
传递给 str.__new__
,因此您必须拦截 arg
.
The method myClass.__new__
is executed. This method will create the object myInstance
. __new__
is the real constructor (__init__
isn't a constructor !). In pseudocode, __new__
look something like this :
__new__
不负责调用 __init__
,如以下简单示例所示:
class C:
def __new__(cls):
print('entering __new__')
self = super().__new__(cls)
print('exiting __new__')
return self
def __init__(self):
print('entering __init__')
super().__init__()
print('exiting __init__')
C()
# Output:
# entering __new__
# exiting __new__
# entering __init__
# exiting __init__
如您所见,在我的 __new__
中,我没有明确调用 __init__
,object.__new__
也没有调用 __init__
。
__init__
会在 __new__
returns 一个类型的实例时被 Python 解释器本身自动调用。
The situation is a little different when we are using immutable types (str, int, float, tuple).
这不完全正确。当我们从未使用默认 __new__
实现的类型继承时,情况会有所不同 。
默认的 __new__
实现(即 object.__new__
)非常宽松,会忽略每个位置参数和关键字参数。如果您将其替换为不太宽松的实施方式,则会发生您所观察到的问题。
需要理解的是,问题不是非默认的__new__
本身带来的,而是我们的__init__
不兼容__new__
.
foo.__new__(foo, arg = 1)
# That works because the method __new__ look like this : def __new__(*args, **kargs).
str.__new__(str, arg = 1)
# That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue).
你明白了。只有一位是错误的:str.__new__
的正确签名是:
def __new__(cls[, object[, encoding[, errors]]])
除了cls
之外的所有参数都是位置参数和关键字参数。事实上你可以这样做:
>>> class C(str):
... def __init__(self, object):
... pass
...
>>> C('abc')
'abc'
>>> C(object='abc')
'abc'
看到了吗?我们为 __init__
使用了与 str.__new__
兼容的签名,现在我们可以避免覆盖 __new__
!
当我尝试设置继承自 str
的 class 的参数值时出现错误。仅当我尝试使用 myClass(arg = 'test')
访问参数时才会发生错误。错误是:
TypeError: 'arg' is an invalid keyword argument for this function
此示例中显示了问题:
class A(str):
def __init__(self, arg):
pass
A("test") # Works well
A(arg = "test") # Fails
只有最后一行引发错误。上一行效果很好。
问题与继承自 int
或 float
的 classes 相同。
更新(解决方案):
我找到了使用这些 link 的解决方案:
- Adding optional parameters to the constructors of multiply-inheriting subclasses of built-in types?
- inheritance from str or int
解决方法是:
class A(str):
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
def __init__(self, arg01):
print(arg01)
A(arg01= "test")
我不知道为什么会这样,我会对此进行调查。如果有人有明确的解释,我很感兴趣,我提前感谢他。
更新(我的解释):
我完全不确定我会说什么,但这就是我的理解。
想象一下没有任何继承的 class 'myClass'
。
当我这样做 myInstance = myClass()
时,会发生以下情况:
方法myClass.__new__
被执行。此方法将创建对象 myInstance
。 __new__
是真正的构造函数(__init__
不是构造函数!)。在伪代码中,__new__
看起来像这样:
def __new__ (cls, *args, **kwargs):
myInstance = # Do some stuff to create myInstance, an object of the type passed as argument (cls).
# Add the method __init__ to myInstance.
# Call __init__ and pass to it the list 'args' and the dictionary 'kwargs' (both come from arguments of __new__). Pass to it also the object itself (self) :
obj.__init__(self, args, kwargs) :
# Do some stuff.
当我们使用不可变类型(str、int、float、tuple)时,情况有点不同。在前面的伪代码中,我写了def __new__(cls, *args, **kwargs)
。对于不可变类型,方法 __new__
的伪代码更像这样 def __new__(cls, anUniqueValue)
。我真的不明白为什么 immutableTypes.__new__
的行为与其他人不同,但事实就是如此。你可以在这个例子中看到它:
class foo():
def __init__(self):
pass
foo.__new__(foo, arg = 1)
# That works because the method __new__ look like this : def __new__(*args, **kargs).
str.__new__(str, arg = 1)
# That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue).
从那里,我们可以理解为什么前面提出的解决方案有效。我们所做的是编辑不可变类型的方法 __new__
,使其像可变类型一样工作。
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
这两行将 def __new__ (cls, anUniqueValue)
转换为 def __new__ (cls, *args, **kwargs)
我希望我的解释几乎清楚,没有那么多错误。如果你说法语,你可以了解更多 link : http://sametmax.com/la-difference-entre-new-et-init-en-python/
你写的基本上是对的,有一些错误。
class A(str):
def __new__(cls, *args, **kwargs):
return str.__new__(cls)
def __init__(self, arg01):
print(arg01)
这并不完全正确:如果您不向 str.__new__
传递任何参数,您的新实例将相当于一个空字符串。
class A(str):
def __new__(cls, arg):
return str.__new__(cls, arg)
def __init__(self, arg):
print(arg)
一般来说,__new__
和__init__
应该有相同的签名。这不是必需的,但在这种情况下,您需要将 arg
传递给 str.__new__
,因此您必须拦截 arg
.
The method
myClass.__new__
is executed. This method will create the objectmyInstance
.__new__
is the real constructor (__init__
isn't a constructor !). In pseudocode,__new__
look something like this :
__new__
不负责调用 __init__
,如以下简单示例所示:
class C:
def __new__(cls):
print('entering __new__')
self = super().__new__(cls)
print('exiting __new__')
return self
def __init__(self):
print('entering __init__')
super().__init__()
print('exiting __init__')
C()
# Output:
# entering __new__
# exiting __new__
# entering __init__
# exiting __init__
如您所见,在我的 __new__
中,我没有明确调用 __init__
,object.__new__
也没有调用 __init__
。
__init__
会在 __new__
returns 一个类型的实例时被 Python 解释器本身自动调用。
The situation is a little different when we are using immutable types (str, int, float, tuple).
这不完全正确。当我们从未使用默认 __new__
实现的类型继承时,情况会有所不同 。
默认的 __new__
实现(即 object.__new__
)非常宽松,会忽略每个位置参数和关键字参数。如果您将其替换为不太宽松的实施方式,则会发生您所观察到的问题。
需要理解的是,问题不是非默认的__new__
本身带来的,而是我们的__init__
不兼容__new__
.
foo.__new__(foo, arg = 1) # That works because the method __new__ look like this : def __new__(*args, **kargs). str.__new__(str, arg = 1) # That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue).
你明白了。只有一位是错误的:str.__new__
的正确签名是:
def __new__(cls[, object[, encoding[, errors]]])
除了cls
之外的所有参数都是位置参数和关键字参数。事实上你可以这样做:
>>> class C(str):
... def __init__(self, object):
... pass
...
>>> C('abc')
'abc'
>>> C(object='abc')
'abc'
看到了吗?我们为 __init__
使用了与 str.__new__
兼容的签名,现在我们可以避免覆盖 __new__
!