Въпроси и отговори за Python

  1. Имам въпрос относно самия език, понеже не видях подобна тема, а да не отварям отделна тема за всеки отделен въпрос, отварям тази, където да си пишем питанията :).

    class A:
        def f():
            pass
    
    a = A()
    b = A()
    
    a.f is b.f
    

    Резултат: False id(a.f) == id(b.f) Резултат: True

    Явно a.f и b.f са различни метод-обекти, но защо тогава имат едно и също id ? Също и id(A.f) == id(a.f) A.f is a.f Резултат: False и за двете.Това означава, че a.f и b.f не се оценяват до обекта на функцията A.f.

  2. До колкото аз разбирам нещатa:

    • id-то на обект е консистентно само по време на неговия lifetime
    • id-тата се reuse-ват след като се освободят
    • не ми е ясно точно кога и как, но явно методите се чистят в определен момент и bind-ват наново

    за да не загубиш id-тата:

    m1 = a.f
    m2 = b.f
    m1 is m2 # False
    id(m1) == id(m2) # False
    
  3. @Станиславе, нищо подобно. id-тата не се губят току така.

    След седмица-две ще има по-advanced лекция за мета обектния протокол на езика и тогава ще ви се обясни това.

    Засега накратко: Казахме ви, че is просто сравнява id-тата на два обекта. Истината е, че той не е толкова наивен. Когато се създаде нова инстанция на даден клас, не се копират всичките му методи и атрибути на ново място, поради очевидни причини. Т.е. когато извикаш a.f() се извиква въпросния метод A.f и му се подава инстанцията на a като първи аргумент. Същото се случва и с b.f(). Извиква се едно и също парче код, върху различни обекти.

    Ако погледнем в паметта (както прави id) тези два метода са едно и също нещо. Но реално - не са, тъй като се извикват върху два различни обекта. Дължината на котка и куче няма как да са едно и също нещо (дори по стойност да съвпаднат), предвид факта, че ги изпълняваме върху два различни обекта. И is прави разликата.

    Ето ви обаче малко храна за размисъл. Ако това, което ви казах е вярно, някой може ли да ми обясни защо тези двете са с различен адрес в паметта?

    >>> id(A.f)
    <<< 139964990037744
    
    >>> id(a.f)
    <<< 139964990004616
    
  4. A.f е обект-функция; a.f е обект-метод, който е сдвояване на 2 указателя - един към обекта а и един към обект-функцията A.f

    Ето и от къде се обърквам. Тези обект-методи трябва да са различни, понеже обектите a и b са различни, съответно is трябва да връща False, но ме объркват резултатите от id(). Иначе реално is връща True за A.f и a.f.__func__(това е указателя към обект-функцията A.f, а a.f.__self__ е указателя към обекта a от така нареченото сдвояване, т.е __func__ и __self__ са атрибути на обект-метода a.f).

  5. Очевидно е също толкова забранено :) Ако тръгнеш да си решаваш проблемите с global или nonlocal най-вероятно вършиш нещо грешно.

    Идеята ни тотално да изпускаме такива неща е да научите езика без тях. Т.е. да не са ви в първоначалния набор от знания. Така вече ще знаете как да си решавате проблемите без тях. Така ако попаднате на код, който ги използва, един от първите ви инстинкти би трябвало да е "това очевидно е грешно, трябва да го оправя, преди да продължа".

    И все пак ги има в езика, има и доста добри причини да са там. Няма лошо да си играем с тях, да разучаваме как са имплементирани и какви case-ове покриват ;)

  6. На една от последните лекции говорихме за множествено наследяване и как се търсят атрибутите в базовите класове. Колкото и да е странно, наистина е DFS: http://docs.python.org/3.3/tutorial/classes.html#multiple-inheritance Възможно е и инфото да е старо ,но е част от курса за python3.3. Интересно е, че този код принтира A2, което показва, че е BFS: class Base(): def p(self): print("Base")

    class A1(Base):
        pass
    
    class A2(Base):
        def p(self):
            print("A2")
    
    class Derived(A1, A2):
        pass
    
    d = Derived()
    d.print()
    
  7. Не може да се каже нито че е DFS, нито BFS. Търси ги по тоя алгоритъм http://en.wikipedia.org/wiki/C3_linearization Може да се каже, че на първо ниво е BFS, и ако не намери там нищо, почва DFS от ляво надясно, като в тях пак на първа стъпка си търси BFS (рекурсия) и така. Но резултата е, че ще ти задълбае до 15 предшественика от първия наследен клас, без да е стигнало да провери предшественика на втория наследен. (Но ще провери втория наследен преди да задълбае първия)

Трябва да сте влезли в системата, за да може да отговаряте на теми.