2016-04-19 16 views
5

Tôi đang phân loại một loại được xác định trong mô-đun C để đặt bí danh một số thuộc tính và phương thức sao cho tập lệnh của tôi hoạt động trong các ngữ cảnh khác nhau.Phương thức bị bỏ qua khi phân loại một loại được định nghĩa trong mô-đun C

Làm cách nào để làm việc này, tôi phải tinh chỉnh từ điển của lớp học theo cách thủ công? Nếu tôi không thêm tham chiếu đến DistanceTo trong từ điển, tôi nhận được 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) 

Tôi đã nghĩ rằng một khi __new__ đã trả lại một trường hợp tôi vẫn có thể điền nó bằng các phương pháp và thuộc tính. Bất cứ ai có thể làm sáng tỏ về điều này ?

EDIT: Mô-đun tôi nhập từ là FreeCAD. Loại cơ sở C được xác định there. Sau đó, Vector có nguồn gốc hình thức định nghĩa này here

EDIT2: Tôi cũng thử như sau:

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) 

và sau khi tạo một điểm thứ hai, cả hai Point3D p trả về giá trị của điểm cuối cùng cho p.X, p.Yp.Z không có vấn đề gì các thông số x,y,z được thông qua khi tạo cá thể. p.x, p.y, p.z trả lại giá trị mong đợi. Dường như cho biết từ điển được chia sẻ giữa các phiên bản.

CHỈNH SỬA 3: Sự cố được giải quyết! Bit Py_TPFLAGS_BASETYPE được đặt thành 0 để ngăn phân lớp phụ như được giải thích trong câu trả lời dưới đây.

Trả lời

1

Tôi tìm thấy câu trả lời trong 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. 
*/ 

Điều này là do lớp App::VectorPy không được thực hiện để hỗ trợ một cách an toàn subclassing và do đó các bit Py_TPFLAGS_BASETYPE được thiết lập để không để ngăn chặn nó xảy ra.

Để biết thông tin, tình huống tương tự với loại tích hợp bytes không thể được phân loại. Xem điều này discussion để nghe từ Guido van Rossum lý do tại sao bytes không phải là phân lớp.

+0

Tôi nghĩ đây là câu trả lời hợp lệ nhưng tôi khuyên bạn nên hỏi những câu hỏi tiếp theo trong một câu hỏi mới thay vì ở đây. – MSeifert

+0

Xin lỗi, tôi sẽ mở một câu hỏi mới sau khi thực hiện một số nghiên cứu. –

2

Tôi không hiểu tại sao bạn muốn thêm thuộc tính động. Chỉ cần sử dụng:

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

Tuyệt đối, đó là những gì tôi đã thử trước tiên nhưng tôi nhận được một 'Point3d không có thuộc tính có tên' X''. Tôi không hiểu tại sao tôi phải đi dưới mui xe để làm điều này ... –

+1

@JacquesGaudin: Kiểm tra thụt đầu dòng của bạn và thử lại. Bạn có thể thụt vào các thuộc tính sai. – user2357112

+0

Cảm ơn bạn đã đề xuất điều này. Thụt lề là chính xác, tất cả các khoảng trống trong tệp của tôi nhưng bị ảnh hưởng trong quá trình sao chép-dán. –

Các vấn đề liên quan