从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作为他们的主要数据,但是你通常想要使用str
或unicode
(后者如果你是表示文本)用于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的。