python-从str或in继承

为什么我在创建从str(或从int)继承的类时遇到问题

class C(str):
   def __init__(self, a, b):
     str.__init__(self,a)
     self.b = b

C("a", "B")

TypeError: str() takes at most 1 argument (2 given)

如果我尝试使用int而不是str,也会发生相同的情况,但是它适用于自定义类。 我需要使用__new__而不是__init__吗? 为什么?

5个解决方案
69 votes
>>> class C(str):
...     def __new__(cls, *args, **kw):
...         return str.__new__(cls, *args, **kw)
... 
>>> c = C("hello world")
>>> type(c)
<class '__main__.C'>

>>> c.__class__.__mro__
(<class '__main__.C'>, <type 'str'>, <type 'basestring'>, <type 'object'>)

由于在构造对象之后调用__init__,因此为不可变类型修改值为时已晚。 请注意__new__是一个类方法,因此我将第一个参数称为cls

浏览此处获取更多信息

>>> class C(str):
...     def __new__(cls, value, meta):
...         obj = str.__new__(cls, value)
...         obj.meta = meta
...         return obj
... 
>>> c = C("hello world", "meta")
>>> c
'hello world'
>>> c.meta
'meta'
John La Rooy answered 2020-06-27T08:26:36Z
13 votes

很少会继承内置类型。 您必须处理几个问题,但实际上并没有获得太多收益。

使用合成几乎总是更好。 您可以保留unicode对象作为属性,而不是继承str

class EnhancedString(object):
     def __init__(self, *args, **kwargs):
         self.s = str(*args, **kwargs)

您可以手动或自动使用__getattr__来推迟要在底层str 294119215740066341上使用的任何方法。

话虽这么说,需要您自己的字符串类型可以让您稍事休息。 有许多类应将字符串存储为其主要数据,但是您通常希望使用strunicode(如果您表示文本,则使用后者)来表示字符串。 (一个常见的例外是,如果您需要使用UI工具箱的字符串类型。)如果要向字符串添加功能,请尝试是否可以使用对字符串进行操作的函数,而不是将新对象用作字符串,这样可以保持 您的代码更简单,并且与其他所有人的程序兼容。

Mike Graham answered 2020-06-27T08:27:13Z
8 votes

当您实例化一个类时,您传入的参数将传递给该类的__new__(构造函数),然后传递给该__init__(初始化程序)方法。因此,如果您从对实例化期间可能提供的参数数量有所限制的类继承,则必须保证其__new____init__所获得的参数都不会超过预期。这就是您所面临的问题。您使用2941192737305105134084实例化了您的类。解释器在C中寻找__new__方法。2941192737305134034087没有该方法,因此python窥视了它的基类str。因为它有一个,所以使用了一个,并提供了两个参数。但是str.__new__期望仅获得一个参数(除了其类对象作为第一个参数之外)。因此TypeError被提出。这就是为什么您必须像在__init__中所做的那样在子类中扩展它。但是请记住,它必须返回类实例并且它是静态方法(无论是否用@staticmethod装饰器定义),计数是否使用super函数。

user2683246 answered 2020-06-27T08:27:35Z
5 votes

对于不可变类型,请使用__new__

class C(str):
    def __new__(cls, content, b):
        return str.__new__(cls, content)

    def __str__(self):
        return str.__str__(self)

a=C("hello", "world")
print a

打印返回__new__

Python字符串是不可变的类型。 调用函数__new__来创建对象C的新实例。python __new__函数基本上存在,可以从不可变类型进行继承。

zoli2k answered 2020-06-27T08:28:04Z
4 votes

仔细阅读本文之后,这是对str进行子类化的另一种尝试。 与其他答案不同的是,使用super(TitleText, cls).__new__在正确的类中创建了实例。 每当使用该函数时,它的行为似乎都像str一样,但是允许我重写一个方法:

class TitleText(str):
    title_text=""
    def __new__(cls,content,title_text):
        o=super(TitleText, cls).__new__(cls,content)
        o.title_text = title_text
        return o

    def title(self):
        return self.title_text

>>> a=TitleText('name','A nice name')
>>> a
'name'
>>> a[0]
'n'
>>> a[0:2]
'na'
>>> a.title()
'A nice name'

这使您可以正确进行切片和下标。 这是用来干嘛的? 用于在admin索引页面中重命名Django应用程序。

Missing Semicolon answered 2020-06-27T08:28:29Z
translate from https://stackoverflow.com:/questions/2673651/inheritance-from-str-or-int