2016-12-08 6 views
0
class A_old: 
    def __getattr__(self, attr): 
     print 'getattr', attr 
     return super(A_old, self).__getattr__(attr) # <-- note: don't do this! 
    def __trunc__(self): 
     return 3 

class A_new(object): 
    def __getattr__(self, attr): 
     print 'getattr', attr 
     return super(A_new, self).__getattr__(attr) 
    def __trunc__(self): 
     return 3 

古いスタイルのクラスは動作しますが、新しいスタイルのクラスは動作しません。古いスタイルのクラスが動作し、新しいスタイルのクラスが壊れています

>>> range(A_old()) 
getattr __int__ 
[0, 1, 2] 
>>> range(A_new()) 
TypeError: range() integer end argument expected, got A_new. 

なぜですか?


:私は上記の2.7を使用しています。これはPython 3には適用されません。range__index__に対応しており、古いスタイルのクラスはノルウェーブルーの道を切りました。

+0

'range()'の中には、 'A_old .__ getattr __()'で 'super()'を使う 'TypeError()'があります。 –

+0

ああ。やあ、おかしい。 – wim

+0

[datamodel](https://docs.python.org/2/reference/datamodel.html)のどこにでも '__trunc__'が記載されていませんか? – wim

答えて

0

旧式のクラスは、__int__が存在しない場合は、__trunc__を使用してサポートされている数値に変換できるかどうかをテストする別の方法を実装しています。

range()(パイソン2)、uses Py_TYPE(arg)->tp_as_number->nb_int()int()を用いて同様に、はなく、かなりの整数に値を変換します。だから、ここで古いスタイルクラスと新しいスタイルクラスの両方のスロットnb_int()を見なければなりません。 __int__をテストするためにhasattr()(というか、C equivalent)を使用しています

instance_int()として

古いスタイルのクラスimplement the nb_int slot、:

if (PyObject_HasAttr((PyObject*)self, int_name)) 
    return generic_unary_op(self, int_name); 

hasattr()ツバメTypeErrorあなたの古いスタイルを含むすべてのの例外、クラススロー:

>>> A_old().__int__ 
getattr __int__ 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in __getattr__ 
TypeError: super() argument 1 must be type, not classobj 

hasattr()ためツバメ例外、hasattr()戻りFalse

>>> hasattr(A_old(), '__int__') 
getattr __int__ 
False 

instance_int()の次の行は、その後__trunc__使用しています:あなたはnb_intを頼むとき

truncated = _instance_trunc(self); 

新スタイルのクラスでも__trunc__を使用することはありません。彼らは__int__またはバストが欲しい。これはスロットを直接サポートするためです。 tp_as_number->nb_int()直接がある場合は、__int__を呼び出します(__getattribute__は迂回します)。

明示的に変換することint()を使用した場合、その後、基礎となるCのコードは(ないtp_as_number->nb_int()スロットが利用できない場合にのみ、それを使用して)明示的に__trunc__属性を探すことに注意してください、しかし、少なくともそれは、このためにhasattr()を使用しません。 Pythonの3では

>>> int(A_new()) 
3 

__trunc__お菓子のすべての使用を、適切special methodとして:これはまだ動作し、新しいスタイルのクラスにint()を使用することを意味します。

+0

ああ、その古い['hasattr'バグ](http://stackoverflow.com/q/35566680/674039)。 – wim

関連する問題