2008-12-09 26 views
20

Làm cách nào để mở rộng lớp nội trang trong python? Tôi muốn thêm một phương thức vào lớp str.
Tôi đã thực hiện một số tìm kiếm nhưng tất cả những gì tôi tìm thấy là các bài đăng cũ hơn, tôi hy vọng ai đó biết điều gì đó mới hơn.Mở rộng các lớp nội trang trong python

+0

thể trùng lặp của [Bạn có thể vá khỉ phương pháp trên các loại lõi trong python?] (http://stackoverflow.com/questions/192649/can-you-monkey-patch-methods-on-core-types-in-python) – jfs

+0

Xem cũng sanxiyn

Trả lời

20

Chỉ cần phân lớp kiểu

>>> class X(str): 
...  def myMethod(self): 
...    return int(self) 
... 
>>> s=X("Hi Mom") 
>>> s.lower() 
'hi mom' 
>>> s.myMethod() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in myMethod 
ValueError: invalid literal for int() with base 10: 'Hi Mom' 

>>> z=X("271828") 
>>> z.lower() 
'271828' 
>>> z.myMethod() 
271828 
+1

Tôi đã hy vọng rằng tôi sẽ không phải phân lớp nhưng sau một vài nghiên cứu nữa tôi đã đi đến kết luận rằng không thể nào khác được, vì vậy tôi sẽ chấp nhận câu trả lời này. – UnkwnTech

+1

@Unkwntech: Không thể tưởng tượng một cách tốt hơn so với phân lớp phụ. Nghiêm túc. Bất cứ điều gì bạn có trong tâm trí (monkeypatching?) Không bao giờ dường như làm việc ra cũng như một rõ ràng, chính xác, rõ ràng phân lớp. –

+5

@ S.Lott - Các lớp mở của Ruby và các phương pháp mở rộng của C# được đề cập đến. – orip

8

Một cách có thể sử dụng "class mở lại" khái niệm (natively hiện trong Ruby) có thể được thực hiện bằng Python sử dụng một trang trí lớp học. Một dụ được đưa ra trong trang này: http://www.ianbicking.org/blog/2007/08/opening-python-classes.html

Tôi xin trích dẫn:

Tôi nghĩ với trang trí lớp học mà bạn có thể làm điều này:

@extend(SomeClassThatAlreadyExists) 
class SomeClassThatAlreadyExists: 
    def some_method(self, blahblahblah): 
     stuff 

thực hiện như thế này:

def extend(class_to_extend): 
    def decorator(extending_class): 
     class_to_extend.__dict__.update(extending_class.__dict__) 
     return class_to_extend 
    return decorator 
0

Giả sử rằng bạn không thể thay đổi các lớp nội trang. Để mô phỏng một "class mở lại" như Ruby trong Python3 nơi __dict__ là một đối tượng mappingproxy và đối tượng không dict:

def open(cls): 
    def update(extension): 
    for k,v in extension.__dict__.items(): 
     if k != '__dict__': 
     setattr(cls,k,v) 
    return cls 
    return update 


class A(object): 
    def hello(self): 
    print('Hello!') 

A().hello() #=> Hello! 

#reopen class A 
@open(A) 
class A(object): 
    def hello(self): 
    print('New hello!') 
    def bye(self): 
    print('Bye bye') 


A().hello() #=> New hello! 
A().bye()  #=> Bye bye 

Tôi cũng có thể viết một hàm trang trí 'mở' cũng như:

def open(cls): 
    def update(extension): 
    namespace = dict(cls.__dict__) 
    namespace.update(dict(extension.__dict__)) 
    return type(cls.__name__,cls.__bases__,namespace) 
    return update 
Các vấn đề liên quan