Расширение встроенных классов в Python

Как я могу расширить встроенный класс в Python? Я хочу добавить метод в класс str.
Я немного искал, но все, что я нашел, это старые сообщения, я надеюсь, что кто-то знает что-то новое.

См. Также <stackoverflow.com/questions/192649/…>

sanxiyn 09.12.2008 15:21
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
34
2
20 862
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Просто подклассифицируйте тип

>>> 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 09.12.2008 15:20

@Unkwntech: не могу представить лучшего способа, чем создание подклассов. Серьезно. Все, что вы имели в виду (патчинг обезьян?), Похоже, никогда не сработает так же хорошо, как четкий, точный, очевидный подкласс.

S.Lott 09.12.2008 15:24

@ S.Lott - На ум приходят открытые классы Ruby и методы расширения C#.

orip 09.12.2008 15:40

@orip: Зная об этом. Считайте, что обезьяны во всех формах являются кошмаром для руководства - они эффективно предотвращают повторное использование, внедряя функции неясными способами.

S.Lott 09.12.2008 15:45

В этом примере типом (z.lower ()) является str, а не X. Как сохранить его как X?

dagfr 25.07.2020 01:54

@dagfr, переопределив метод .lower () в классе X и вернув новый объект X

GalacticRaph 15.01.2021 00:38

Одним из способов может быть использование концепции «повторного открытия класса» (изначально существующей в 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.

caram 21.01.2021 10:37

Предполагая, что вы не можете изменять встроенные классы. Чтобы смоделировать «повторное открытие класса», например 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. Работает как шарм. Я предпочитаю второе определение.

caram 21.01.2021 10:38

Другие вопросы по теме