从Python2.7和Python3中的“str”继承

2024-04-25 22:33:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在将一些较旧的代码从python2.7移植到python3,并试图弄清楚如何在这两个版本中使用inhering from str。下面是一些代码。你知道吗

class OtoString(str):
    def __init__(self, p_string):
        str.__init__(self, p_string)


    def is_url(self):
        if self.startswith("http://") or self.startswith("https://"):
            return True
        else:
            return False

print(OtoString("https://stackoverflow.com").is_url())

在Python2.7中运行这段代码工作得很好,但是当我在Python3.7中运行这段代码时,我得到一个TypeError:

TypeError: object.__init__() takes exactly one argument (the instance to initialize)

如果有人能解释从str继承到底是怎么工作的,这行是做什么的

str.__init__(self, p_string)

为什么这在python3中不起作用,以及我如何使它起作用。你知道吗


Tags: 代码httpsself版本urlstringreturninit
3条回答

试试这个:

class OtoString(str):
    def __init__(self,p_string):
        str.__init__(self)
        self.p_string=p_string
    def is_url(self):
        if self.p_string.startswith('https://') or self.p_string.startswith('http://'):
            return True
        return False

它在我的电脑上工作。你知道吗


这条线

str.__init__(self, p_string)

在python3.x中应该是str.__init__(self),并且 实际继承str的initclass OtoString(str)继承str中的所有函数(包括init

__init__在对象构造之后被调用。str是不可变的,因此不能修改构造函数中的值。构造必须发生在__new__,这是类方法,因此第一个参数是cls,而不是self

class OtoString(str):
    def __new__(cls, *args, **kw):
        return str.__new__(cls, *args, **kw)

    def is_url(self):
        if self.startswith("http://") or self.startswith("https://"):
            return True
        else:
            return False

print(OtoString("https://stackoverflow.com").is_url())

印刷品:

True

str是一个不可变类型,与所有不可变类型一样,应该执行构造和初始化in ^{},而不是^{}。替换__init__的正确代码(在Python 2和Python 3上都适用)是:

def __new__(cls, p_string):
    return str.__new__(cls, p_string)

请注意,它接收一个类对象,而不是一个现有实例,并返回调用超类__new__的结果(因为__new__实际上使成为新对象,它不像__init__那样只初始化一只手给它)。你知道吗

在这种情况下,您应该完全省略__init__/__new__的定义(您将自动继承str的版本)。但是如果您需要做额外的工作(例如,在最终构造之前计算一些规范化版本的p_string),那么上面的__new__就是正确的模式。你知道吗

另外,为了避免增加类的内存使用,我建议添加:

__slots__ = ()

作为类主体中的第一行,这将避免为未使用的__dict____weakref__腾出空间,使您的行为和开销更接近于str(在我的64位python3.6上,它将每个实例的内存开销从217字节减少到81字节,高于字符串数据本身的开销)。最终版本将是:

class OtoString(str): 
    __slots__ = () 

    def is_url(self): 
        return self.startswith(("http://", "https://"))

相关问题 更多 >