2016-04-19 7 views
5

Cモジュールで定義された型をサブクラス化して、いくつかの属性とメソッドを別名にしてスクリプトが異なるコンテキストで動作するようにします。Cモジュールで定義された型をサブクラス化するときにメソッドが無視される

これを機能させるには、どうすれば私のクラスの辞書を手動で微調整する必要がありますか?私がDistanceToへの参照を辞書に追加しないと、私はPoint3d has no attribute named DistanceToになります。

class Point3d(App.Base.Vector): 
     def __new__(cls, x, y, z): 
      obj = super(Point3d, cls).__new__(cls) 
      obj.x, obj.y, obj.z = x, y, z 
      obj.__dict__.update({ 
       'X':property(lambda self: self.x), 
       'Y':property(lambda self: self.y), 
       'Z':property(lambda self: self.z), 
       'DistanceTo':lambda self, p: self.distanceToPoint(p)}) 
      return obj 
     def DistanceTo(self, p): return self.distanceToPoint(p) 

私は__new__がインスタンスを返した後、私はまだメソッドと属性を移入できると考えていました。誰かがこれについていくつかの光を当てることができますか?

編集:私がインポートするモジュールはFreeCADです。 Cの基本型はthereと定義されています。

class Point3d(App.Base.Vector): 
     def __new__(cls, x, y, z): 
      obj = super(Point3d, cls).__new__(cls) 
      obj.x, obj.y, obj.z = x, y, z 
      obj.__dict__.update({ 
       'X': x, 'Y': y, 'Z': z, 
       'DistanceTo':lambda self, p: self.distanceToPoint(p)}) 
      return obj 
     def DistanceTo(self, p): return self.distanceToPoint(p) 

と第二の点を作成した後、両方のPoint3dとpは、p.Xの最後のポイントの値を返しp.Yp.Z:私はまた、以下を試してみました:次いで、ベクターは、この定義here

EDIT2派生形でありますどのようなx,y,zパラメータがインスタンスの作成時に渡されたかに関係なく、 p.x, p.y, p.zは期待値を返します。辞書がインスタンス間で共有されていることを示しているようです。

編集3:問題が解決しました! Py_TPFLAGS_BASETYPEビットは、以下の答えで説明するように、サブクラス化を防ぐためにゼロに設定されています。

答えて

1

私はPyObjectBase.cppで答えを見つけました:

/** \brief 
* To prevent subclasses of PyTypeObject to be subclassed in Python we should remove 
* the Py_TPFLAGS_BASETYPE flag. For example, the classes App::VectorPy and App::MatrixPy 
* have removed this flag and its Python proxies App.Vector and App.Matrix cannot be subclassed. 
* In case we want to allow to derive from subclasses of PyTypeObject in Python 
* we must either reimplment tp_new, tp_dealloc, tp_getattr, tp_setattr, tp_repr or set them to 
* 0 and define tp_base as 0. 
*/ 

これはApp::VectorPyクラス安全にサブクラス化をサポートするために実装されているので、Py_TPFLAGS_BASETYPEビットは、それを防ぐために、ゼロに設定されていないためです起こってから。

詳細については、bytesの組み込み型と同様の状況で、サブクラス化できません。 Guido van Rossumからbytesがサブクラス化できない理由については、discussionを参照してください。

+0

これは有効な答えだと思いますが、ここではなく新しい質問でフォローアップの質問をすることをお勧めします。 – MSeifert

+0

申し訳ありません私は少しの研究をした後、新しい質問を開きます。 –

2

なぜプロパティを動的に追加するのかわかりません。ただ、使用:

class Point3d(App.Base.Vector): 
    def __init__(self, x, y, z): 
     super().__init__(x, y, z) # or maybe super().__init__([x, y, z]) 

    @property 
    def X(self): 
     return self[0] # guessing that App.Base.Vector works like a list 

    @property.setter 
    def X(self, value): 
     self[0] = value 

    # Y and Z likewise. 
+0

これは私が最初に試したものですが、 'Point3dには 'X'という名前の属性がありません。私はなぜこれを行うためにフードの下に行かなければならないのかわかりません... –

+1

@JacquesGaudin:あなたの押し込みを確認し、もう一度やり直してください。あなたはおそらくプロパティを間違ってインデントしました。 – user2357112

+0

ありがとうございます。字下げは正しいですが、ファイル内のすべてのスペースはコピー貼り付け操作中に苦しんでいます。 –

関連する問題