Python print不使用__repr __,__ unicode__或__str__作为unicode子类?

Raf*_*afe 10 python unicode class subclass derived-class

Python打印没有使用__repr__,__unicode____str__打印时我的unicode子类.关于我做错了什么的线索?

这是我的代码:

使用Python 2.5.2(r252:60911,2009年10月13日,14:11:59)

>>> class MyUni(unicode):
...     def __repr__(self):
...         return "__repr__"
...     def __unicode__(self):
...         return unicode("__unicode__")
...     def __str__(self):
...         return str("__str__")
...      
>>> s = MyUni("HI")
>>> s
'__repr__'
>>> print s
'HI'
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是上述的准确近似值,只是为了比较:

>>> class MyUni(object):
...     def __new__(cls, s):
...         return super(MyUni, cls).__new__(cls)
...     def __repr__(self):
...         return "__repr__"
...     def __unicode__(self):
...         return unicode("__unicode__")
...     def __str__(self):
...         return str("__str__")
...
>>> s = MyUni("HI")
>>> s
'__repr__'
>>> print s
'__str__'
Run Code Online (Sandbox Code Playgroud)

[编辑...]这听起来像获取字符串对象isinstance(instance,basestring)并提供对unicode返回值的控制的最佳方式,并且使用unicode repr是...

>>> class UserUnicode(str):
...     def __repr__(self):
...         return "u'%s'" % super(UserUnicode, self).__str__()
...     def __str__(self):
...         return super(UserUnicode, self).__str__()
...     def __unicode__(self):
...         return unicode(super(UserUnicode, self).__str__())
...
>>> s = UserUnicode("HI")
>>> s
u'HI'
>>> print s
'HI'
>>> len(s)
2
Run Code Online (Sandbox Code Playgroud)

上面的_ str __ repr _没有为这个例子添加任何东西,但是想法是明确地显示一个模式,根据需要进行扩展.

只是为了证明这种模式可以控制:

>>> class UserUnicode(str):
...     def __repr__(self):
...         return "u'%s'" % "__repr__"
...     def __str__(self):
...         return "__str__"
...     def __unicode__(self):
...         return unicode("__unicode__")
... 
>>> s = UserUnicode("HI")
>>> s
u'__repr__'
>>> print s
'__str__'
Run Code Online (Sandbox Code Playgroud)

思考?

nne*_*neo 10

问题是,print不尊重__str__unicode子类.

来自PyFile_WriteObject,使用者print:

int
PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
{
...
        if ((flags & Py_PRINT_RAW) &&
    PyUnicode_Check(v) && enc != Py_None) {
    char *cenc = PyString_AS_STRING(enc);
    char *errors = fobj->f_errors == Py_None ? 
      "strict" : PyString_AS_STRING(fobj->f_errors);
    value = PyUnicode_AsEncodedString(v, cenc, errors);
    if (value == NULL)
        return -1;
Run Code Online (Sandbox Code Playgroud)

PyUnicode_Check(v)如果v类型是unicode 或子类,则返回true .因此,此代码直接编写unicode对象,无需咨询__str__.

请注意,子类化str和重写__str__按预期工作:

>>> class mystr(str):
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
... 
>>> print mystr()
str
Run Code Online (Sandbox Code Playgroud)

如调用strunicode明确地:

>>> class myuni(unicode):
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
...     def __unicode__(self): return "unicode"
... 
>>> print myuni()

>>> str(myuni())
'str'
>>> unicode(myuni())
u'unicode'
Run Code Online (Sandbox Code Playgroud)

我相信这可能被解释为目前实施的Python中的一个错误.


Mar*_*ers 6

你是子类unicode.

它永远不会打电话,__unicode__因为它已经是 unicode.这里发生的是对象被编码stdout编码:

>>> s.encode('utf8')
'HI'
Run Code Online (Sandbox Code Playgroud)

除了它将使用直接C调用而不是.encode()方法.这是printunicode对象的默认行为.

print声明称PyFile_WriteObject,这反过来又要求PyUnicode_AsEncodedString处理时,一个unicode物体.后者然后遵循当前编码编码函数,并且这些函数使用Unicode C宏直接访问数据结构.你无法从Python中拦截这个.

__encode__我猜你正在寻找的是一个钩子.由于这已经是一个unicode子类,print只需要编码,不需要unicode 再次转换它,也不能将它转换为字符串而不用显式编码.您必须与Python核心开发人员合作,看看是否__encode__有意义.