Методы расширения python
ОК, в С# у нас есть что-то вроде:
public static string Destroy(this string s) {
return "";
}
Итак, в основном, когда у вас есть строка, которую вы можете сделать:
str = "This is my string to be destroyed";
newstr = str.Destroy()
# instead of
newstr = Destroy(str)
Теперь это круто, потому что, на мой взгляд, это более читаемо. У python есть что-то подобное? Я имею в виду вместо того, чтобы писать вот так:
x = SomeClass()
div = x.getMyDiv()
span = x.FirstChild(x.FirstChild(div)) # so instead of this I'd like to write:
span = div.FirstChild().FirstChild() # which is more readable to me
Любое предложение?
Ответы
Ответ 1
Через неделю у меня есть решение, которое ближе всего к тому, что я искал. Решение состоит из использования getattr
и __getattr__
. Вот пример для тех, кто заинтересован.
class myClass:
def __init__(self): pass
def __getattr__(self, attr):
try:
methodToCall = getattr(myClass, attr)
return methodToCall(myClass(), self)
except:
pass
def firstChild(self, node):
# bla bla bla
def lastChild(self, node):
# bla bla bla
x = myClass()
div = x.getMYDiv()
y = div.firstChild.lastChild
Я не тестировал этот пример, я просто дал ему понять, кто может быть заинтересован. Надеюсь, что это поможет.
Ответ 2
Вы можете просто изменить класс напрямую, иногда называемый патчем обезьян.
def MyMethod(self):
return self + self
MyClass.MyMethod = MyMethod
del(MyMethod)#clean up namespace
Я не уверен на 100%, что вы можете сделать это на специальном классе, таком как str, но это отлично подходит для ваших пользовательских классов.
Обновление
В комментарии вы подтверждаете мое подозрение, что это невозможно для встроенной строки str. В этом случае я считаю, что аналогов методов расширения С# для таких классов нет.
Наконец, удобство этих методов, как в С#, так и в Python, сопряжено с риском. Использование этих методов может сделать код более сложным для понимания и поддержки.
Ответ 3
Вы можете изменить встроенные классы с помощью патчей обезьян с помощью запрещенных фруктов
Но для установки запрещенного плода требуется компилятор C и неограниченная среда, поэтому он, вероятно, не будет работать или потребует больших усилий для работы в Google App Engine, Heroku и т.д.
Я изменил поведение класса unicode
в Python 2.7 для турецкой i,I
прописной/строчной задачи этой библиотеки.
# -*- coding: utf8 -*-
# Redesigned by @guneysus
import __builtin__
from forbiddenfruit import curse
lcase_table = tuple(u'abcçdefgğhıijklmnoöprsştuüvyz')
ucase_table = tuple(u'ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ')
def upper(data):
data = data.replace('i',u'İ')
data = data.replace(u'ı',u'I')
result = ''
for char in data:
try:
char_index = lcase_table.index(char)
ucase_char = ucase_table[char_index]
except:
ucase_char = char
result += ucase_char
return result
curse(__builtin__.unicode, 'upper', upper)
class unicode_tr(unicode):
"""For Backward compatibility"""
def __init__(self, arg):
super(unicode_tr, self).__init__(*args, **kwargs)
if __name__ == '__main__':
print u'istanbul'.upper()
Ответ 4
Вы можете сделать то, что вы просили, например:
def extension_method(self):
#do stuff
class.extension_method = extension_method
Ответ 5
С# реализованы методы расширения, поскольку в нем отсутствуют функции первого класса, у Python есть их, и это предпочтительный метод для "обертывания" общей функциональности в разных классах на Python.
Есть веские основания полагать, что у Python никогда не будет методов расширения, просто посмотрите доступные встроенные модули:
len(o) calls o.__len__
iter(o) calls o.__iter__
next(o) calls o.next
format(o, s) calls o.__format__(s)
В принципе, Python любит функции.