我正在将遗留代码库从Python2.7移植到Python3.6。在这个代码库中,我有一些例子,比如:
class EntityName(unicode):
@staticmethod
def __new__(cls, s):
clean = cls.strip_junk(s)
return super(EntityName, cls).__new__(cls, clean)
def __init__(self, s):
self._clean = s
self._normalized = normalized_name(self._clean)
self._simplified = simplified_name(self._clean)
self._is_all_caps = None
self._is_all_lower = None
super(EntityName, self).__init__(self._clean)它可以这样叫:
EntityName("Guy DeFalt")当将它移植到Python3时,上面的代码会失败,因为unicode不再是您可以扩展的类(至少,如果有一个类似的类,我就找不到它)。考虑到str现在是unicode,我尝试只交换str,但是父init不接受我试图传递的字符串值:
TypeError: object.__init__() takes no parameters这是有意义的,因为str没有__init__方法--这似乎不是使用该类的惯用方法。因此,我的问题有两个主要分支:
str是适当的,我应该如何修改__init__函数的惯用行为?发布于 2019-03-28 12:51:24
在Python 3中子类字符串或其他不可变类的正确方法与Python 2中相同:
class MyString(str):
def __new__(cls, initial_arguments): # no staticmethod
desired_string_value = get_desired_string_value(initial_arguments)
return super(MyString, cls).__new__(cls, desired_string_value)
# can be shortened to super().__new__(...)
def __init__(self, initial_arguments): # arguments are unused
self.whatever = whatever(self)
# no need to call super().__init__(), but if you must, do not pass arguments 你的样本有几个问题。首先,为什么__new__是@staticmethod?它是@classmethod,尽管您不需要指定它。第二,代码似乎是在这样的假设下运行的:当您调用超类的__new__时,它也以某种方式调用了您的__init__。我是从self._clean应该如何设置的角度得出这个结论的。事实并非如此。当您调用MyString(arguments)时,会发生以下情况:
__new__ )和arguments调用arguments。__new__必须返回类实例。要做到这一点,它可以创建它,就像我们所做的那样,或者做一些其他的事情;例如,它可能返回一个现有的,或者事实上,任何东西。__init__接收到的实例(这个参数通常称为self)和相同的arguments调用arguments。__init__返回不是传递类的子类,__new__就不会调用__new__。)Python使用类层次结构来查看要调用哪个__new__和__init__。在这两个方法中,需要正确地排序参数并使用适当的超类调用。
https://stackoverflow.com/questions/49038559
复制相似问题