2012-01-16 4 views
5

Tôi đã đoạn mã sau trong C++:Namespaces lẫn lộn khi trở về enum scoped từ phương pháp lớp

class Person 
{ 
    public: 
     enum Gender {Male, Female}; 

     Gender GetGender() const; 
} 

tôi bọc nó trong boost :: python theo cách này:

BOOST_PYTHON_MODULE(TestPython) 
{ 
    scope the_scope = class_<Person>("Person") 
     .def("GetGender", &Person::GetGender); 

    enum_<Person::Gender>("Gender") 
     .value(Male, Person::Male) 
     .value(Female, Person::Female) 
     .export_values(); 
} 

Khi tôi cố gắng để gọi person.GetGender() từ Python tôi nhận được ngoại lệ sau đây:

 
Can't pickle : attribute lookup **PyBF.TestPython.Gender**. 
It guesses the namespace of the Gender (which is actually **PyBF.TestPython.Person.Gender**) enum return type incorrectly. 

Làm thế nào tôi có thể nói với GetGender funct ion loại nào để trả về một cách rõ ràng?

+2

Có một số điểm kỳ lạ với việc chọn lọc enums. xem tại đây: http://stackoverflow.com/questions/3214969/ –

Trả lời

1

Vì chúng ta không có mã mà tạo ra lỗi, tôi giả sử nó xảy ra khi bạn cố gắng để dưa một đối tượng Person.

Sự cố của bạn không liên quan cụ thể đến việc sử dụng tăng. Nó nằm trong mô-đun cPickle. Nó có đối tượng pickling vấn đề với các lớp lồng nhau. Xem phần này answer để được giải thích. Dưới đây là một mã đơn giản ví dụ mà tạo ra lỗi:

import cPickle 

class MyOuterClass(object): 
    class MyInnerClass(object): 
     pass 

    def __init__(self): 
     self.my_inner_class = self.MyInnerClass() 


def pickle_error(): 
    print "Pickling ..." 
    my_outer_class = MyOuterClass() 
    print cPickle.dumps(my_outer_class) 

if __name__ == "__main__": 
    pickle_error() 

Chạy nó tạo ra sản lượng này:

Pickling ... 
Traceback (most recent call last): 
    File "pickle.py", line 18, in <module> 
    pickle_error() 
    File "pickle.py", line 15, in pickle_error 
    print cPickle.dumps(my_outer_class) 
cPickle.PicklingError: Can't pickle <class '__main__.MyInnerClass'>: 
attribute lookup __main__.MyInnerClass failed 

Như đã đề cập trong câu trả lời liên quan, khi cPickle hỏi lớp bên trong cho tên của nó nó trả '__main__.MyInnerClass'. Tuy nhiên, tên này không thể được tìm thấy trong không gian tên của mô-đun, do đó bạn nhận được ngoại lệ.


Bây giờ bạn trải nghiệm điều này bởi vì vì không có thứ gì đó tương tự như kiểu enum trong python, hãy tăng đối tượng để đại diện cho nó. Cấu trúc enum_ khai báo một lớp trong phạm vi hiện tại. Bằng cách nắm bắt phạm vi lớp, bạn sẽ tạo một lớp lồng nhau trong Person và bạn nhận được lỗi pickle được đề cập ở trên.

Có một số giải pháp cho vấn đề của bạn.

Cách đơn giản nhất là khai báo enum bên ngoài phạm vi của Người. Bạn có thể không muốn để lộ một enum liên quan của một người bên cạnh nó cho tổ chức mã. Sau đó bạn có thể khai báo lớp Person trong một module con để enum của bạn được khai báo gần với lớp của bạn mà không quá công khai.

Bạn cũng có thể xem boost's pickle support. Tuy nhiên tôi đã không thử nó.

Một giải pháp thứ ba có thể là sử dụng thứ gì đó khác hơn là dưa để lưu trữ đối tượng của bạn.

1

Có thể bạn có một Nam khác, Nữ được xác định ở đâu đó không? bằng không tôi không thấy cách biên dịch này. thử thêm phạm vi lớp:

enum_<Person::Gender>("Gender") 
    .EXPORT_ENUM_VALUE(Person::Male) 
    .EXPORT_ENUM_VALUE(Person::Female) 
    .export_values(); 
+0

Xin lỗi tôi đã cập nhật bài đăng, tôi đã không hoàn toàn sao chép mã của mình, hy vọng nó có ý nghĩa hơn bây giờ – Grim