编写异常类,我遇到了这个错误:
TypeError: object.__new__(A) is not safe, use Exception.__new__()
这里发布了类似的问题:
TypeError: object.__new__(int) is not safe, use int.__new__()。因此,__new__
已被弃用,原因如下:
[Python-Dev] __new__
deprecation
Guido van Rossum
"该消息意味着它所说的内容。 :-)没有必要打电话
object.__new__()
包含多个类参数,以及任何代码 这样做只是将那些args倾倒在一个黑洞中。"
但我得到的3.3中的警告"并不安全"很可怕我试着理解使用object.__new__
的含义,让我们考虑这个例子:
>>> class A(Exception):
... def __new__(cls, *args):
... return object.__new__(A)
...
>>> A()
TypeError: object.__new__(A) is not safe, use Exception.__new__()
悲惨地失败。另一个例子:
>>> class A(object):
... def __new__(cls, *args):
... return object.__new__(A)
...
>>>
>>> A()
<__main__.A object at 0x0000000002F2E278>
工作正常。虽然object
是一个内置类,就其角色而言就像Exception
一样,但它们共享内置类的特性。现在使用Exception
,第一个示例会引发TypeError
,但是object
会引发object.__new__
。
(a)在第一个示例中使用TypeError:...is not safe...
使Python引发错误(__new__
)有什么缺点?
(b)在调用#include "font.h"
void console_putc(char ch){
volatile unsigned* serialport = (unsigned*) 0x16000000;
volatile unsigned* serialflags = (unsigned*) 0x16000018;
while( *serialflags & 32 )
;
*serialport = ch;
}
struct PL110MMIO {
unsigned haxis; //offset 0: horizontal axis
unsigned vaxis; //offset 4: vertical axis
unsigned polarity; //offset 8: clock+polarity
unsigned lineend; //offset 12: line end
unsigned baseaddr1; //offset 16: upper panel base address
unsigned baseaddr2; //offset 20: lower panel base address
unsigned intmask; //offset 24: interrupt mask
unsigned params; //offset 28: panel parameters
};
#define WIDTH 800
#define HEIGHT 600
#define framebuffer ((volatile unsigned short*) (((0x07ffffff - WIDTH*HEIGHT*2))&~0xf)) //0x200000;
#define pl110 ( (volatile struct PL110MMIO*)0xc0000000 )
void console_init(){
//To get screen width w: 0x3f1f3f00 | (w/4-4)
//ex: 640 = 0x3f1f3f9c
pl110->haxis = 0x3f1f3f00 | (WIDTH/ 4-4);
//To get screen height v: 0x80b600 | (v-1)
//Ex: 480 = 0x80b61df
pl110->vaxis = 0x80b6000 | (HEIGHT-1) ;
pl110->polarity = 0x067f3800;
pl110->baseaddr1 = (unsigned) framebuffer;
//value bpp
//0x1821 1
//0x1823 2
//0x1825 4
//0x1827 8
//0x1829 16
//0x182b 24
pl110->params = 0x1829;
}
void set_pixel(int x, int y, unsigned short color){
framebuffer[ y*WIDTH+x ] = color;
}
//input: r,g,b in range 0...255
//output: 16 bit color with 565 weighting
#define COLOR16(r,g,b) ( ((b&0xf8)<<8) | ((g & 0xfc)<<3) | ((r&0xf8)>>3) )
void console_box( int x, int y, int w, int h ){
int i;
unsigned short color = COLOR16( 0,128,255 );
for(i=0;i<w;++i){
set_pixel(x+i,y,color);
set_pixel(x+i,y+h,color);
}
for(i=0;i<h;++i){
set_pixel(x,y+i,color);
set_pixel(x+w,y+i,color);
}
}
void console_set_pixel(int x, int y, unsigned short color){
framebuffer[ y*WIDTH+x ] = color;
}
void console_draw_character(int x, int y, unsigned short color, char c){
int i,j;
for(i=0;i<CHAR_HEIGHT;++i){
for(j=0;j<CHAR_WIDTH;++j){
if( font_data[(int)c][i] & (MASK_VALUE >> j) )
framebuffer[ (y+i)*WIDTH + (x+j) ] = color;
}
}
}
之前,Python执行了哪些检查?或者:在第一个示例中,Python引发错误的条件是什么?
答案 0 :(得分:4)
调用object.__new__
没有问题,但是在调用Exception.__new__
时出现问题。
Exception
类的设计方式是必须调用它的__new__
,所以如果没有这样做就会抱怨。
有一个问题,为什么只有内置类才会发生这种情况。事实上,Python对每个被编程的类都做到了。
以下是自定义类中相同机制的简化穷人实现:
class A(object):
def __new__(cls):
rtn = object.__new__(cls)
rtn.new_called = True
return rtn
def __init__(self):
assert getattr(self,'new_called',False), \
"object.__new__ is unsafe, use A.__new__"
class B(A):
def __new__(cls):
return object.__new__(cls)
现在:
>>> A()
<__main__.A object at 0x00000000025CFF98>
>>> B()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __init__
AssertionError: object.__new__ is unsafe, use A.__new__
作为旁注,这个问题的例子实际上有两个错误:
>>> class A(Exception):
... def __new__(cls, *args):
... return object.__new__(A)
首先是在__new__
上调用object
,因此忽略了Exception.__new__
。
另一方面,同样严重的是A
传递给__new__
而不是cls
,这阻碍了从A
继承的所有类。
见这个例子:
class A(object):
def __new__(cls):
return object.__new__(A) # The same erroneous line, without Exception
class B(A):
pass
现在B()
没有创建B
的实例:
>>> B()
<__main__.A object at 0x00000000025D30B8>
答案 1 :(得分:0)
调用object.__new__(A)
会返回A
的实例,但如果已定义,则不会调用Exception.__new__()
。