Пространство имен класса в python [duplicate]

Еще один удар по нему, от работы с обещаниями.

(Отказ от ответственности: JS noob, исходящий из мира Python. Даже там, currying не используется так много, но может прийти в удобном случае, поэтому я закрепил функцию currying - см. ссылки)

Во-первых, я начинаю с вызова ajax. У меня есть определенная обработка для успеха, но при отказе я просто хочу дать пользователю обратную связь, что вызов чего-то привел к некоторой ошибке . В моем фактическом коде я отображаю обратную связь с ошибками на панели начальной загрузки, но я просто использую запись здесь.

Я изменил свой живой URL-адрес, чтобы сделать это неудачным.

function ajax_batch(e){
    var url = $(e.target).data("url");

    //induce error
    url = "x" + url;

    var promise_details = $.ajax(
        url,
        {
            headers: { Accept : "application/json" },
            // accepts : "application/json",
            beforeSend: function (request) {
                if (!this.crossDomain) {
                    request.setRequestHeader("X-CSRFToken", csrf_token);
                }
        },
        dataType : "json",
        type : "POST"}
    );
    promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}

Теперь, чтобы сообщить пользователю, что пакет завершился неудачно, мне нужно написать эту информацию в обработчике ошибок, потому что все, что он получает, является ответом от сервера.

У меня все еще есть информация доступна во время кодирования - в моем случае у меня есть несколько возможных партий, но я не знаю, какая из них была неудачной синтаксический анализ ответа сервера о неудавшемся URL-адресе.

function fail_status_specific_to_batch(d){
    console.log("bad batch run, dude");
    console.log("response.status:" + d.status);
}

Давайте сделаем это. Консольный выход:

console:

bad batch run, dude utility.js (line 109) response.status:404

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

    ... rest is as before...
    var target = $(e.target).text();
    var context = {"user_msg": "bad batch run, dude.  you were calling :" + target};
    var contexted_fail_notification = curry(generic_fail, context); 

    promise_details.then(notify_batch_success, contexted_fail_notification);
}

function generic_fail(context, d){
    console.log(context);
    console.log("response.status:" + d.status);
}

function curry(fn) {
     var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
     return function () {
        var new_args = slice.call(arguments),
              args = stored_args.concat(new_args);
        return fn.apply(null, args);
     };
}

console:

Object { user_msg="bad batch run, dude. you were calling :Run ACL now"} utility.js (line 117) response.status:404 utility.js (line 118)

В более общем плане, учитывая, насколько широкое использование обратного вызова в JS, каррирование кажется довольно полезным инструментом.

https: //javascriptweblog.wordpress .com / 2010/04/05 / curry-cooking-up-tastier-functions / http://www.drdobbs.com/open-source/currying-and-partial-functions-in- javasc / 231001821? PGNO = 2

18
задан Volker 16 December 2012 в 12:47
поделиться

4 ответа

В то время, когда x=10 выполняется в вашем примере, класс не существует, но класс тоже не существует.

Выполнение в Python идет сверху вниз. Если x=10 находится выше метода класса, вы не можете получить доступ к методу класса в этой точке, потому что он еще не определен.

Даже если вы можете запустить классный метод, это не будет потому что класс еще не существует, поэтому метод класса не мог ссылаться на него. Класс не создается до тех пор, пока не будет запущен весь блок класса, поэтому пока вы находитесь внутри блока класса, нет класса.

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

>>> def deco(cls):
...     cls.initStuff()
...     return cls
>>> @deco
... class Foo(object):
...     x = 10
...     
...     @classmethod
...     def initStuff(cls):
...         cls.x = 88
>>> Foo.x
88
>>> Foo.x = 10
>>> Foo.x
10
>>> Foo.initStuff() # reinitialize
>>> Foo.x
88
15
ответ дан BrenBarn 25 August 2018 в 22:56
поделиться

Вы не можете вызывать classmethod в определении class, потому что класс еще не определен полностью, поэтому нет ничего, чтобы передать метод в качестве его первого аргумента cls ... классического цыпленка- и-яйца. Однако вы можете обойти это ограничение, перегрузив метод __new__() в метаклассе и вызывая метод класса оттуда после создания класса, как показано ниже:

class Test(object):
    # nested metaclass definition
    class __metaclass__(type):
        def __new__(mcl, classname, bases, classdict):
            cls = type.__new__(mcl, classname, bases, classdict)  # creates class
            cls.static_init()  # call the classmethod
            return cls

    x = None

    @classmethod
    def static_init(cls):  # called by metaclass when class is defined
        print("Hello")
        cls.x = 10

print Test.x

Выход:

Hello
10
1
ответ дан martineau 25 August 2018 в 22:56
поделиться

Вы вызываете метод класса, добавляя также имя класса:

class.method

. В вашем коде должно быть достаточно:

Test.static_init()

Вы также можете сделать это:

static_init(Test)

Чтобы вызвать его внутри вашего класса, выполните ваш код:

Test.static_init()

Мой рабочий код:

class Test(object):

    @classmethod
    def static_method(cls):
        print("Hello")

    def another_method(self):
        Test.static_method()

и Test().another_method() возвращает Hello

5
ответ дан NlightNFotis 25 August 2018 в 22:56
поделиться

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

def _test_static_init(value):
    return value, value * 2

class Test:
    x, y = _test_static_init(20)

if __name__ == "__main__":
    print Test.x, Test.y

Старый, неправильный ответ:

Вот пример, я надеюсь, что это поможет:

class Test:
    x = None

    @classmethod
    def set_x_class(cls, value):
        Test.x = value

    def set_x_self(self):
        self.__class__.set_x_class(10)

if __name__ == "__main__":
    obj = Test()
    print Test.x
    obj.set_x_self()
    print Test.x
    obj.__class__.set_x_class(15)
    print Test.x

В любом случае, ответ NlightNFotis является лучшим: используйте имя класса при доступе к методам класса. Это делает ваш код менее неясным.

1
ответ дан ZalewaPL 25 August 2018 в 22:56
поделиться
Другие вопросы по тегам:

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