Rug*_*rra 47 python string int inheritance new-operator
为什么我在创建一个继承自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)
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用int
而不是str
,它会发生同样的情况,但它适用于自定义类.我需要用__new__
而不是__init__
?为什么?
Joh*_*ooy 71
>>> 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'>)
Run Code Online (Sandbox Code Playgroud)
因为__init__
在构造对象之后调用,所以修改不可变类型的值为时已晚.注意,这__new__
是一个classmethod,所以我调用了第一个参数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'
Run Code Online (Sandbox Code Playgroud)
Mik*_*ham 13
继承内置类型很少值得.你必须处理好几个问题而且你并没有获得太多的好处.
使用构图几乎总是更好.str
您可以将str
对象保留为属性,而不是继承.
class EnhancedString(object):
def __init__(self, *args, **kwargs):
self.s = str(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
您可以str
self.s
手动或自动使用推迟您想要在底层工作的任何方法__getattr__
.
话虽这么说,需要你自己的字符串类型应该让你停下来.有许多类应该将字符串存储为其主要数据,但是您通常希望使用str
或unicode
(后者,如果您表示文本)用于字符串的一般表示.(一个常见的例外是如果您需要使用UI工具包的字符串类型.)如果您想为字符串添加功能,请尝试使用对字符串而不是新对象进行操作的函数作为字符串进行操作您的代码更简单,与其他人的程序更兼容.
实例化一个类时,传入的参数将传递给类的__new__
(构造函数),然后传递给类的__init__
(初始化程序)方法.因此,如果从一个对实例化期间可能提供的参数数量有限制的类继承,则必须保证它既不会__new__
,也__init__
不会获得比预期更多的参数.这就是你遇到的问题.用实例化你的类C("a", "B")
.解释器寻找__new__
方法C
.C
没有它,所以python窥视它的基类str
.因为它有一个,所以使用并提供两个参数.但是str.__new__
期望只获得一个参数(除了它的类对象作为第一个参数).所以TypeError
提出来了.这就是为什么你必须在你的子类中扩展它,就像你使用它一样__init__
.但请记住,它必须返回类实例,并且它是一个静态方法(无论是否使用@staticmethod
装饰器定义),如果使用super
函数,则会计算.
__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
Run Code Online (Sandbox Code Playgroud)
打印返回hello
.
Python字符串是不可变类型.__new__
调用该函数以创建对象的新实例C
.该蟒蛇__new__
功能基本存在允许继承自不变类型.
小智 5
仔细阅读this后,这是对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'
Run Code Online (Sandbox Code Playgroud)
这使您可以正确地进行切片和下标。这是用来干嘛的?用于在管理索引页面中重命名 Django 应用程序。