从str或intinheritance

为什么我有问题创build一个类inheritancestr(或从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__ ? 为什么?

 >>> 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__ ,所以修改不可变types的值为时已晚。 请注意, __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' 

inheritance内置types很less值得。 你必须处理好几个问题,你并没有得到太多的好处。

使用作文几乎总是比较好的。 而不是inheritancestr ,你会保留一个str对象作为一个属性。

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

您可以使用__getattr__手动或自动推迟您想要在底层str self.s上工作的任何方法。

这就是说,需要你自己的stringtypes是应该让你暂停的东西。 有很多类应该存储一个string作为他们的主要数据,但是你通常想要使用strunicode (后者如果你是表示文本)用于string的一般表示。 (一个常见的例外是如果你需要使用一个UI工具包的stringtypes。)如果你想添加function到你的string,请尝试,如果你能使用函数的string而不是新的对象作为string ,它保持您的代码更简单,更符合其他人的程序。

当你实例化一个类时,你传入的参数被传递给__new__ (构造函数),然后传递给类的__init__ (初始化方法)。 所以,如果你从一个对实例化过程中可能提供的参数个数有限制的类inheritance,你必须保证它的__new__和它的__init__都不会得到比他们期望的更多的参数。 所以这是你的问题。 你用C("a", "B")实例化你的类。 解释器在C查找__new__方法。 C没有它,所以Python窥探到它的基类str 。 就像它有一个,那个被使用并提供了这两个参数。 但是str.__new__只能得到一个参数(除了它的类对象作为第一个参数)。 所以TypeError 。 这就是为什么你必须在你的子类中扩展它,类似于你对__init__所做的。 但是请记住,它必须返回类实例,并且它是一个静态方法(不pipe是否使用@staticmethod装饰器定义),如果使用super函数,这个方法@staticmethod数。

仔细阅读后,这里是另一个子类str的尝试。 其他答案的变化是使用super(TitleText, cls).__new__在正确的类中创build实例。 这个似乎像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' 

这可以让你正确切片和下标。 这是用来干嘛的? 在pipe理索引页面中重命名Django应用程序。

在不可变types的情况下使用__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 

打印返回hello

Pythonstring是不可变的types。 函数__new__被调用来创build对象C的新实例。 python __new__函数基本上是允许inheritance不可变types的。