Как я могу расширить встроенный класс в Python?
Я хочу добавить метод в класс str.
Я немного искал, но все, что я нашел, это старые сообщения, я надеюсь, что кто-то знает что-то новое.
См. Также <stackoverflow.com/questions/192649/…>






Просто подклассифицируйте тип
>>> 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
Я надеялся, что мне не придется создавать подклассы, но после некоторых дополнительных исследований я пришел к выводу, что это невозможно по-другому, поэтому я приму этот ответ.
@Unkwntech: не могу представить лучшего способа, чем создание подклассов. Серьезно. Все, что вы имели в виду (патчинг обезьян?), Похоже, никогда не сработает так же хорошо, как четкий, точный, очевидный подкласс.
@ S.Lott - На ум приходят открытые классы Ruby и методы расширения C#.
@orip: Зная об этом. Считайте, что обезьяны во всех формах являются кошмаром для руководства - они эффективно предотвращают повторное использование, внедряя функции неясными способами.
В этом примере типом (z.lower ()) является str, а не X. Как сохранить его как X?
@dagfr, переопределив метод .lower () в классе X и вернув новый объект X
Одним из способов может быть использование концепции «повторного открытия класса» (изначально существующей в Ruby), которая может быть реализована в Python с помощью декоратора классов. Пример приведен на этой странице: http://www.ianbicking.org/blog/2007/08/opening-python-classes.html
Я цитирую:
Я думаю, что с декораторами классов вы могли бы сделать это:
@extend(SomeClassThatAlreadyExists)
class SomeClassThatAlreadyExists:
def some_method(self, blahblahblah):
stuff
Реализовано так:
def extend(class_to_extend):
def decorator(extending_class):
class_to_extend.__dict__.update(extending_class.__dict__)
return class_to_extend
return decorator
Python 3.9, __dict__ больше не dict, а mappingproxy, вместо этого вам нужно использовать решение @ MVP.
Предполагая, что вы не можете изменять встроенные классы.
Чтобы смоделировать «повторное открытие класса», например Ruby в Python3, где __dict__ является объектом сопоставления прокси, а не объектом 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
В Python2 я мог бы также написать функцию-декоратор open:
def open(cls):
def update(extension):
namespace = dict(cls.__dict__)
namespace.update(dict(extension.__dict__))
return type(cls.__name__,cls.__bases__,namespace)
return update
Наконец-то я могу делать это как в Ruby. Работает как шарм. Я предпочитаю второе определение.
возможный дубликат Можете ли вы обезопасить методы исправления основных типов в Python?