Как я могу выбрать вложенный класс в Python?

Предположим, вы хотите подсчитать количество нажатий кнопки пользователя на веб-странице. Для этого вы вызываете функцию на onclick событии кнопки, чтобы обновить счетчик переменной

<button onclick="updateClickCount()">click me</button>  

Теперь может быть много таких подходов, как:

1) Вы может использовать глобальную переменную и функцию для увеличения счетчика:

var counter = 0;

function updateClickCount() {
    ++counter;
    // do something with counter
}

Но ошибка заключается в том, что любой скрипт на странице может изменять счетчик, не вызывая updateClickCount().


2) Теперь вы можете подумать об объявлении переменной внутри функции:

function updateClickCount() {
    var counter = 0;
    ++counter;
    // do something with counter
}

Но, Эй! Каждый раз, когда вызывается функция updateClickCount(), счетчик снова устанавливается на 1.


3) Размышление о вложенных функциях?

Вложенные функции имеют доступ к области «выше». В этом примере внутренняя функция updateClickCount() имеет доступ к переменной счетчика в родительской функции countWrapper()

function countWrapper() {
    var counter = 0;
    function updateClickCount() {
    ++counter;
    // do something with counter
    }
    updateClickCount();    
    return counter; 
}

. Это могло бы решить дилемму счетчика, если бы вы могли достичь функции updateClickCount() извне, и вам также нужно найти способ выполнить counter = 0 только один раз не каждый раз.


4) Закрытие для спасения! (функция самозапуска):

 var updateClickCount=(function(){
    var counter=0;

    return function(){
     ++counter;
     // do something with counter
    }
})();

Функция самозапуска только запускается один раз. Он устанавливает counter в ноль (0) и возвращает выражение функции.

Таким образом updateClickCount становится функцией. «Замечательная» часть состоит в том, что она может обращаться к счетчику в родительском пространстве.

Это называется закрытием JavaScript. Это дает возможность для функции иметь переменные [ private .

counter защищен областью анонимной функции и может быть изменен только с помощью добавления функция!

Более яркий пример закрытия:

  <script>
    var updateClickCount=(function(){
    var counter=0;

    return function(){
    ++counter;
     document.getElementById("spnCount").innerHTML=counter;
    }
  })();
</script>

<html>
 <button onclick="updateClickCount()">click me</button>
  <div> you've clicked 
    <span id="spnCount"> 0 </span> times!
 </div>
</html>
37
задан prinzdezibel 22 December 2009 в 17:25
поделиться

4 ответа

Ответ Нади довольно полный - это практически не то, чем вы хотите заниматься; вы уверены, что не можете использовать наследование в WidgetTypes вместо вложенных классов?

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

1
ответ дан 27 November 2019 в 03:35
поделиться

Модуль пикулирования пытается получить от модуля класс TextType. Но так как класс вложен, то это не работает. Предложение Джейсона сработает. Вот строки в pickle.py, отвечающие за сообщение об ошибке:

    try:
        __import__(module)
        mod = sys.modules[module]
        klass = getattr(mod, name)
    except (ImportError, KeyError, AttributeError):
        raise PicklingError(
            "Can't pickle %r: it's not found as %s.%s" %
            (obj, module, name))

klass = getattr(mod, name) конечно же не сработает в случае вложенного класса. Чтобы продемонстрировать, что происходит, попробуйте добавить эти строки перед пикировкой экземпляра:

import sys
setattr(sys.modules[__name__], 'TextType', WidgetType.TextType)

Этот код добавляет TextType в качестве атрибута к модулю. Пикировка должна работать просто отлично. Но я не советую использовать этот хак.

.
29
ответ дан 27 November 2019 в 03:35
поделиться

Pickle работает только с классами, определенными в области видимости модуля (верхний уровень). В данном случае, похоже, что можно определить вложенные классы в области видимости модуля, а затем установить их в качестве свойств на WidgetType, предполагая, что есть причина не просто ссылаться в своем коде на TextType и FloatType. Или импортируйте модуль, в котором они находятся и используйте widget_type.TextType и widget_type.FloatType.

.
2
ответ дан 27 November 2019 в 03:35
поделиться

В Sage (www.sagemath.org) мы имеем много примеров этой проблемы pickling. Мы решили систематически решить ее следующим образом: поместить внешний класс в специальный метакласс, целью которого является реализация и скрытие хака. Обратите внимание, что это автоматически распространяется через вложенные классы, если есть несколько уровней вложенности.

5
ответ дан 27 November 2019 в 03:35
поделиться
Другие вопросы по тегам:

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