Запись класса, который принимает обратный вызов в Python?

Существует несколько способов заняться им.

интуитивный подход, который является тем, о чем думает большинство программистов C/C++, состоит в том, что указатели являются адресами памяти. пример litb проявляет этот подход. Если у Вас есть нулевой указатель (который на большинстве машин соответствует адресу 0), и Вы добавляете размер интервала, Вы получаете адрес 4. Это подразумевает, что указатели являются в основном просто необычными целыми числами.

, К сожалению, существует несколько проблем с этим. Для начала это не может работать. Нулевой указатель, как гарантируют, на самом деле не будет использовать адрес 0. (Хотя присвоение постоянного 0 к указателю приводит к нулевому указателю).

Далее, Нельзя увеличить нулевого указателя, или в более общем плане, указатель должен всегда указывать на выделенную память (или один элемент мимо), или специальный нулевой указатель постоянный 0.

, Таким образом, более корректный образ мыслей его - то, что указатели являются просто итераторами, разрешающими Вам выполнить итерации по выделенной памяти. Это - действительно одна из ключевых идей позади итераторов STL. Они смоделированы, чтобы вести себя очень как указатели и обеспечить специализации, которые исправляют необработанные указатели для работы надлежащими итераторами.

А более тщательно продуманное объяснение этого дано здесь , например.

, Но это последнее представление означает, что необходимо действительно объяснить итераторы STL, и затем просто сказать, что указатели являются особым случаем их. Можно увеличить указатель для указания на следующий элемент в буфере, точно так же, как Вы можете std::vector::iterator. Это может указать на один элемент мимо конца массива, точно так же, как конечный итератор в любом другом контейнере. Можно вычесть два указателя , что точка в тот же буфер для получения числа элементов между ними, точно так же, как Вы можете с итераторами, и точно так же, как с итераторами, если указатели указывают в отдельные буферы, Вы можете не , обоснованно сравнивают их. (Для практического примера почему не, рассмотрите то, что происходит в сегментированном пространстве памяти. Каково расстояние между двумя указателями, указывающими для разделения сегментов?)

, Конечно, на практике, существует очень близкая корреляция между адресами ЦП и указателями C/C++. Но они не точно то же самое. Указатели имеют несколько ограничений, которые не могут быть строго необходимыми на Вашем ЦП.

, Конечно, большинство программистов на C++ запутывает на первом понимании, даже при том, что это технически неправильно. Это достаточно обычно близко к тому, как Ваш код заканчивает тем, что вел себя, что люди думают, что получают его и идут дальше.

, Но для кого-то происходящего из Java, и просто узнающий об указателях с нуля, последнее объяснение может быть столь же понятным, и это собирается преподнести меньше сюрпризов на них позже.

8
задан Charles Dietrich 14 October 2009 в 17:25
поделиться

4 ответа

Python предполагает, что любые функции, связанные в рамках класса, являются методами. Если вы хотите рассматривать их как функции, вы должны покопаться в их атрибутах, чтобы получить исходный объект функции:

def __init__(self, *args, **kwargs):
    super(Fruit, self).__init__(*args, **kwargs)

    # The attribute name was changed in Python 3; pick whichever line matches
    # your Python version.
    callback = self.print_callback.im_func  # Python 2
    callback = self.print_callback.__func__ # Python 3

    callback("Message from Fruit: ")
8
ответ дан 5 December 2019 в 12:10
поделиться

There's also a bit dirtyer solution with metaclasses:

def apple_print(f):
    print "Apple " + f

class FruitMeta(type):
    def __new__(cls, name, bases, dct):
        func = dct["print_callback"]
        dct["print_callback"]=lambda x,f,func=func: func(f)
        return type.__new__(cls,name,bases,dct)

class Fruit(object):
    __metaclass__ = FruitMeta
    print_callback = None
    def __init__(self):
        super(Fruit,self).__init__()
        self.print_callback("Msg ")

class Apple(Fruit):
    print_callback = apple_print

mac = Apple()here

It manipulates the class before its creation!

0
ответ дан 5 December 2019 в 12:10
поделиться

Вы можете использовать напрямую:

class Apple(Fruit):
    print_callback = staticmethod(apple_print)

или:

class Apple(Fruit):
    print_callback = classmethod(apple_print)

В первом случае вы получите только один параметр (оригинал). Во втором вы получите два параметра, где первый будет классом, для которого он был вызван.

Надеюсь, это поможет, и он будет короче и менее сложным.

3
ответ дан 5 December 2019 в 12:10
поделиться

Обновлено : добавлено предложение abourget об использовании статического метода :

Попробуйте следующее:

def __init__(self, *args, **kwargs):
    super(Fruit, self).__init__(*args, **kwargs)

    # Wrap function back into a proper static method
    self.print_callback = staticmethod(self.print_callback)

    # And now you can do:
    self.print_callback("Message from Fruit: ")
2
ответ дан 5 December 2019 в 12:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: