Extending builtin classes in python

前端 未结 3 585
情歌与酒
情歌与酒 2020-12-13 14:02

How can I extend a builtin class in python? I would like to add a method to the str class.
I\'ve done some searching but all I\'m finding is older posts, I\'m hoping s

相关标签:
3条回答
  • 2020-12-13 14:36

    Assuming that you can not change builtin classes. To simulate a "class reopening" like Ruby in Python3 where __dict__ is an mappingproxy object and not dict object :

    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
    

    I could also write a decorator function 'open' as well:

    def open(cls):
      def update(extension):
        namespace = dict(cls.__dict__)
        namespace.update(dict(extension.__dict__))
        return type(cls.__name__,cls.__bases__,namespace)
      return update
    
    0 讨论(0)
  • 2020-12-13 14:40

    One way could be to use the "class reopening" concept (natively existing in Ruby) that can be implemented in Python using a class decorator. An exemple is given in this page: http://www.ianbicking.org/blog/2007/08/opening-python-classes.html

    I quote:

    I think with class decorators you could do this:

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

    Implemented like this:

    def extend(class_to_extend):
        def decorator(extending_class):
            class_to_extend.__dict__.update(extending_class.__dict__)
            return class_to_extend
        return decorator
    
    0 讨论(0)
  • 2020-12-13 14:46

    Just subclass the type

    >>> class X(str):
    ...     def my_method(self):
    ...         return int(self)
    ...
    >>> s = X("Hi Mom")
    >>> s.lower()
    'hi mom'
    >>> s.my_method()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in my_method
    ValueError: invalid literal for int() with base 10: 'Hi Mom'
    
    >>> z = X("271828")
    >>> z.lower()
    '271828'
    >>> z.my_method()
    271828
    
    0 讨论(0)
提交回复
热议问题