Re: [问题] class str继承问题

楼主: ya790206 (残云夺月)   2013-12-29 16:46:36
这问题简单的回答是 str.__new__ 这个方法只接受一个参数,而你给他三个。
实验:
这两行 str.__new__(str) 和 str.__new__(str, '1') 程式码不会出错
然而 str.__new__(str, '1', '2') 会出现
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: str() takes at most 1 argument (2 given)
细节:
当 class 要产生 instance 时,他会呼叫 class 的 metaclss 的 __call__ 方法
而 metaclass 的 __call__ 方法大概长这样
def __call__(cls, *args, **kwargs):
obj = cls.__new__(cls, *args, **kwargs)
obj.__init__(*args, **kwargs)
return obj
所以你的程式
s = S(1,2,3)
直译器会先做
obj = str.__new__(str, *args, **kwargs)
其中 *args 是 (1, 2, 3)
可是因为 str.__new__ 只接受一个参数,因此发生错误
观察:
class ClsA(object):
def __init__(self, *args, **kwargs):
print 'init: ', args, kwargs
def __new__(cls, *args, **kwargs):
print 'new: ', args, kwargs
return super(ClsA, cls).__new__(cls, *args, **kwargs)
a = ClsA('a', 'b', 2)
上面程式码,当要建立 ClsA 的程式码,他会先执行 __new__,
而喂给 __new__ 的参数则是 ClsA 后面的参数。
之后再把 ClsA 后面的参数喂给 __init__
问题解决方法:
由于问题出现在喂给 str.__new__ 太多参数,因此我们不要让他有太多参数
解法1.
不要使用默认的 metaclass(type),自订一个 meta class
class CustomMetaCls(type):
def __call__(cls, *args, **kwargs):
if len(args):
content = args[0]
else:
content = ''
obj = cls.__new__(cls, content)
obj.__init__(*args, **kwargs)
return obj
class MyStr(str):
__metaclass__ = CustomMetaCls
def __init__(self, a='', b=''):
super(MyStr, self).__init__(a)
self.a = a
self.b = b
b = MyStr('a', 'b')
解法2.
override __new__
class MyStr1(str):
def __init__(self, a='', b=''):
super(MyStr1, self).__init__()
self.a = a
self.b = b
def __new__(cls, *args, **kwargs):
print args, kwargs
if len(args):
content = args[0]
else:
content = ''
return str.__new__(cls, content)
参考资料:
http://www.slideshare.net/hychen/python-type-and-object
或是 tainan.py 12月份的录影
有错敬请指教

Links booklink

Contact Us: admin [ a t ] ucptt.com