2013-08-02 33 views
7

Có một lớp cơ sở Base và một phân lớp Special.Chuyển đổi đối tượng BaseClass thành đối tượng SubClass theo cách tự động?

class Base(object): 
    def __init__(self, name): 
     self.name = name 
    def greet(self): 
     return 'Hello %s' % self.name 

class Special(Base): 
    def __init__(self, name): 
     super(Special, self).__init__(name) 
    def rhyme(self): 
     return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name 

Làm thế nào tôi có thể biến một thể hiện của Base vào một thể hiện Special? Hiện nay tôi có một classmethod xác định trên Special mà chỉ reassignes __dict__:

class Special(Base): 
    ... 
    @classmethod 
    def from_base(cls, baseobj): 
     special = Special() 
     special.__dict__ = baseobj.__dict__ 
     return special 

Đây có phải là thành ngữ? Nếu không thì sẽ là gì?

P.S. Một kịch bản ví dụ: Lớp cơ sở là một số thực hiện mặc định. Trong tự nhiên, bạn có thể sẽ tìm thấy các đối tượng của lớp cơ sở. Bây giờ trong một số dự án, lớp cơ sở là các lớp con và các phương thức đặc biệt đã được thêm vào lớp con. Bây giờ bạn chủ yếu vẫn làm việc với các đối tượng lớp cơ sở, nhưng đôi khi bạn sẽ muốn "nâng cấp" lên lớp đặc biệt, vì bạn sẽ cần truy cập vào một số phương thức.

+0

Tại sao nó không thể nhanh chóng hoặc sử dụng vũ lực của 'Special'? –

Trả lời

6

Bạn có thể đạt được điều này bằng cách xác định một hàm tạo thay thế và gán lại thuộc tính __class__ của cá thể.

class Base(object): 
    def __init__(self, name): 
     self.name = name 

    def greet(self): 
     return 'Hello %s' % self.name 

    @classmethod 
    def alt_constructor(cls, *args, **kwargs): 
     obj = cls(*args, **kwargs) 
     obj.__class__ = Special 
     return obj 


class Special(Base): 
    def __init__(self, name): 
     super(Special, self).__init__(name) 

    def rhyme(self): 
     return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name 


>>> s = Base.alt_constructor("test") 
>>> print s.rhyme() 
Hi test! How are you? Fine, thanks. What about you? 

EDIT:

Moved các nhà xây dựng Special-Base.

Nếu bạn không thể sửa đổi lớp Base, bạn có thể thêm một lớp học để Special sẽ thay đổi lớp của bất kỳ đối tượng nào được truyền cho nó.

class Base(object): 
    def __init__(self, name): 
     self.name = name 

    def greet(self): 
     return 'Hello %s' % self.name 


class Special(Base): 
    def __init__(self, name): 
     super(Special, self).__init__(name) 

    def rhyme(self): 
     return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name 

    @classmethod 
    def convert_to_special(cls, obj): 
     obj.__class__ = Special 

>>> b = Base("test") 
>>> print type(b) 
<class '__main__.Base'> 

>>> Special.convert_to_special(b) 
>>> print type(b) 
<class '__main__.Special'> 

Một giải pháp đa mục đích khác là tạo một mixin có thể được thêm vào bất kỳ lớp nào.

class ConverterMixin(object): 

    @classmethod 
    def convert_to_class(cls, obj): 
     obj.__class__ = cls 


class Special(ConverterMixin, Base): 
    def __init__(self, name): 
     super(Special, self).__init__(name) 

    def rhyme(self): 
     return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name 

>>> b = Base("test") 
>>> print type(b) 
<class '__main__.Base'> 

>>> Special.convert_to_class(b) 
>>> print type(b) 
<class '__main__.Special'> 
+0

@miku Bạn nói đúng, trong câu trả lời ban đầu của tôi, tôi đã thêm một hàm tạo thay thế cho 'Base', thay đổi cách lớp đó hoạt động. Tôi đã cập nhật câu trả lời của mình với những gì tôi tin rằng bạn đang tìm kiếm. – FastTurtle

+0

Cảm ơn bạn đã cập nhật. Sử dụng '__class__' là thứ tự cường độ nhanh hơn, điều này không đáng ngạc nhiên, vì trong sẽ không tạo ra một đối tượng mới. – miku

1

thực sự bạn có thể, nhưng tôi không nghĩ bạn nên làm như vậy. thay vì python typecast đã gõ vịt để giải quyết loại tình huống này.

dù sao, đây là các mã:

>>> base = Base("I'm a base!") 
>>> hasattr(base, 'rhyme') 
False 
>>> base.__class__ = Special 
>>> hasattr(base, 'rhyme') 
True 
>>> base.rhyme() 
"Hi I'm a base!! How are you? Fine, thanks. What about you?" 
Các vấn đề liên quan