Câu trả lời ngắn gọn là có và không.
Không, không có thành ngữ cú pháp thuận tiện để chèn nhanh thuộc tính lớp trong một cdef class
. Tuy nhiên ....
Toàn bộ điểm của cython
là nó mang lại cho bạn quyền truy cập cấp thấp hơn. Động cơ thông thường cho nỗ lực thêm là hiệu suất, nhưng bạn cũng có thể làm C
giống như những thứ có thêm tự do. Khó khăn là, có rất nhiều cạm bẫy, và trong trường hợp này, bạn sẽ không nhận được thuộc tính lớp tinh khiết python
mà không có nhiều công việc. Tuy nhiên, khá dễ dàng để có được những gì bạn cần cho các trường hợp sử dụng đơn giản.
Ví dụ: giả sử tôi đang tạo một số công cụ tính toán làm lớp và tôi muốn đặt toàn bộ độ chính xác của giá trị trả lại cho tất cả các phiên bản. Tôi muốn một mặc định tại thời gian biên dịch, và theo thời gian tôi có thể muốn điều chỉnh nó thấp hơn để nhanh chóng xử lý một số thử nghiệm, và sau đó điều chỉnh nó cao hơn cho công việc cuối cùng của tôi. Một thuộc tính lớp được thực hiện để đặt hàng, nhưng bạn có thể nhận được các chức năng mà bạn cần trong cython
như sau:
Thứ nhất, xác định ở cấp mô-đun sau:
cdef int _precision[1] # storage for my class 'attribute'
_precision[0]=8 # my default value, set during compilation
Sử dụng một mảng cho phép chúng ta sử dụng cython
thành ngữ precision[0]
tương đương với C *precision
. Tên cdef
precision
hoàn toàn là con trỏ vì mục dữ liệu là một mảng. Điều này cho phép sử dụng cython
thành ngữ cú pháp để chuyển đổi từ cython
vị trí lưu trữ thành tham chiếu python. Nếu tất cả những gì bạn muốn là một hằng số toàn cầu có thể được truy cập bởi cdef
mã trong bất kỳ lớp nào trong mô-đun, bạn đã hoàn tất. Nếu bạn muốn sử dụng nó đúng như một thuộc tính lớp, bạn phải thực thi kỷ luật đó - trình biên dịch không quan tâm.
Bây giờ nếu bạn cũng muốn điều chỉnh giá trị từ python
mã, bạn sẽ cần một cặp cdef
chức năng mà python
mã trong các mô-đun có thể gọi để truy cập 'thuộc tính':
cdef int* get_precision(): return _precision
cdef void* set_precision(int i): _precision[0]=i
Tại thời điểm này , ngữ nghĩa sẽ thay đổi một chút từ tinh khiết python
, trừ khi bạn thực sự muốn đổ mồ hôi. Bạn cần một hàm python
setter và getter, và tôi tìm thấy những giao thức python
mô tả được thực hiện bởi các thuộc tính là dễ nhất:
cdef class SomeCalculator:
...
property precision:
def __get__(self):
"""Get or set calculation precision, default == 8.
This is like a class attribute: setting affects all instances,
however, it also affects all subclasses."""
return get_precision()[0]
def __set__(self,int integer): set_precision(min(30,max(0,integer)))
Đầu tiên nhận được một tài liệu tham khảo python cho 'thuộc tính'. Cái thứ hai đặt 'thuộc tính' với giá trị tích phân python
, được điều chỉnh để nằm trong giới hạn. Giao diện trả về và gọi hàm cython
tự động xử lý các chuyển đổi phức tạp hơn so với giao diện của chúng.
Ví dụ: get_precision
trả về số C-pointer
. Nếu bạn đã thực hiện cuộc hội thảo tại get_precision
, bạn sẽ gặp lỗi khi cố gắng trả lại C-int
trong __get__
như thể nó là python
. Thay vào đó, nếu bạn chỉ bỏ qua yêu cầu [0]
trong __get__
, bạn sẽ gặp lỗi khi cố gắng trả lại C-pointer
như thể đó là python int
. Như được viết, chuyển đổi tự động đối sánh chính xác các loại. cython
là rất khó tính về loại điều này, và âm thầm có thể trả về giá trị không chính xác, chỉ có thể phát hiện khi chạy. Có thể mất một số thử nghiệm để suy ra câu thần chú chính xác.
Chuỗi tài liệu yêu cầu bạn không mong đợi thuộc tính lớp thuần túy python
. Nếu bạn muốn sub-class, và có các lớp con sử dụng một thiết lập toàn cầu khác, bạn sẽ cần phải đổ mồ hôi nhiều hơn một chút. Trong python
, tất cả được thực hiện tự động.
Mặc dù vậy, có những khác biệt khác. Một thuộc tính lớp thực có thể được tham chiếu trên lớp hoặc trên một cá thể. Thuộc tính này chỉ có thể được tham chiếu trên một cá thể. Việc thiết lập thuộc tính lớp thực trên cá thể tạo ra một bản sao cá thể cụ thể, để lại thuộc tính lớp bị ảnh hưởng, nhưng ẩn với cá thể đã thay đổi.
Đối với trường hợp sử dụng đã cho, tính năng này hoạt động. Một thuộc tính lớp thực là không cần thiết. Vì mã cython
thường ít trừu tượng và tính toán chuyên sâu, cách tiếp cận tối thiểu này thường đủ.
Bạn cũng cần đặt công khai để truy cập từ python 'cdef public int bar' –
Cảm ơn bạn đã trả lời. Tôi sẽ không nghĩ rằng trường hợp sử dụng của tôi sẽ được coi là thêm thuộc tính tại thời gian chạy nghĩ. Tôi muốn xác định các thuộc tính lớp có sẵn một lần tại thời gian biên dịch. – Pwnosaurus
xin lỗi có, đã không chú ý. Tôi chưa bao giờ thấy một thuộc tính lớp trong cython. –