Servis

Jednoduchost programovacího jazyka

Diskuze k článku: Jednoduchost programovacího jazyka
(počet příspěvků: 16 , poslední: 24. 7. 2008 10:19)

*Redakce si vyhrazuje právo moderovat příspěvky s vulgárním obsahem, urážlivé nebo jiným způsobem nevhodné.

  • jablka a hrusky | od: iky

    S temi deskriptory si autor clanku plete jablka s hruskama.

    PHP metody __get, __set, __delete a __call muzou delat maximalne to, co delaji v pythonu metody __getattr__, __setattr__ a __delattr__. Tyto magicke metody jsou ale, co do funkcnosti a moznosti, jenom uzkou podmnozinou cele implementace pythonich deskriptoru.

    Neplest PHPkovsky __get s pythonim __get__ apod. (a uz vubec neplest PHPkovsky __call s Pythonim __call__!:)

    Metody se sice jmenuji stejne, ale v kazdem z techto jazyku delaji neco jineho.

    A co se tyce autorovo porovnani? Vzdyt Python je z jineho sveta, nez je PHP. Netvari se jako objektovy jazyk, ale jazykem objektovym je.
    Moznosti vyuziti techto jazyku se prekryvaji maximalne v oblasti webovych aplikaci. Jinde neni pro PHP misto.

    (IP: 213.197.167.xxx)

    odpovědět | 10. 7. | 23:56
    • Jakub Vrána

      Z čeho usuzujete, že pletu __get a __get__? Deskriptory se v Pythonu dají použít k tomu, aby se při přístupu k vlastnosti zavolala metoda. K vyřešení stejného problému se v PHP dá použít přetěžování. Funguje to jinak, ale dá se to využít k témuž.

      (IP: 193.85.202.xxx)

      odpovědět | 11. 7. | 12:07
      • al3x

        Zavadejici je prirovnavat k deskriptory k moznostem __get() / __getattr__().

        __get() a __getattr__() plni v php resp. pythonu opravdu tu samou ulohu.

        Naproti tomu magie ukryta v deskriptorech jde uplne opacnym smerem a z toho plyne pouziti v naprosto jinych situacich. A presne pro ty schazi v PHP elagatni reseni zkratka proto, ze PHP ekvivalent pythonich deskriptoru neimplementuje,

        (IP: 217.11.255.xxx)

        odpovědět | 11. 7. | 13:21
        • Jakub Vrána

          Obdoba deskriptorů v PHP pomocí __get():

          <?php
          class Desc {
              function get($obj) {
                  return $obj->x + 10;
              }
          }

          class A {
              var $x;
              private $descriptors = array();
              function __construct($x) {
                  $this->x = $x;
                  $this->descriptors["plus_ten"] = new Desc;
              }
              function __get($name) {
                  if (isset($this->descriptors[$name])) {
                      return $this->descriptors[$name]->get($this);
                  }
              }
          }

          $a = new A(5);
          echo "$a->x\n";
          echo "$a->plus_ten\n";
          ?>

          (IP: 194.228.68.xxx)

          odpovědět | 21. 7. | 23:26
          • al3x

            Mno a tady narazime na zasadni problem: V tvem PHP priklade trida "A" (tedy rodic) MUSI vedet, ze existuji nejake "pseudo-deskriptory" a dokonce ktere to jsou. Mno a v momente, kdy nutim rodicovskou tridu, aby znala a explicitne volala moje rozhrani, ztracim temer veskerou krasu a uzitecnost pythonich deskriptoru.

            Je totiz treba si uvedomit rozdil mezi __get__ a __getattr__. Pokud se budu drzet tveho prikladu kde A() ma vlastnosti typu Desc(), pak:
            - A.__getattr__ pouziju v pripade, kdyz chci ovlivnovat chovani tridy A() pro volani z vnejsku.
            - Desc.__get__ (tedy dekriptor) ovlivnuje chovani Desc() z pohledu tridy A().

            To je dost vyznamny rozdil, pripady, ktere se daji efektivne i elegantne resit obema cestama je opravdu minimalne, proto se mi zda trochu matouci, kdyz zamenujes jedno za druhe.

            (IP: 89.24.5.xxx)

            odpovědět | 22. 7. | 23:45
            • Jakub Vrána (jakub@vrana.cz)

              Promiň, ale teď mícháš jablka a hrušky pro změnu ty. Jednak nevím, proč třídě A říkáš rodič. Ale hlavně tvrdíš, že v Pythonu nemusí třída A znát deskriptor. To přeci není pravda - třída A rozhodně musí vědět o existenci deskriptoru a ve správný okamžik ho použít:

              class A(object):
              plus_ten = Desc()

              Pravdu máš jen s existencí implicitního zavolání deskriptoru v Pythonu (v předdefinované metodě __getattribute__). To by se v PHP dalo vyřešit zděděním třídy z rodiče, který by definoval vlastnost $descriptors a základní formu metody __get.

              Uznávám, že v PHP musíš pro využití myšlenky deskriptorů napsat o pět řádek víc (kvůli chybějícímu implicitnímu zavolání deskriptorů), princip popsaného řešení je ale totožný jako v Pythonu, jen méně přímočarý.

              (IP: 193.85.202.xxx)

              odpovědět | 23. 7. | 15:56
              • al3x

                Ano. S nespravnym pouziti terminu "rodic" mas pravdu. To je moje chyba.

                Za zbytkem si celkem stojim. Trida A() nemusi o descriptorech a jejich specialnich vlastnostich nic vedet. Napada me jak pythoni property(), tak mozna models.ForeignKey() z djanga. Oboje jsou velmi ruznymi ale velmi hezkymi priklady pouziti deskriptoru, o kterych nadrazena trida nemusi vedet nic a veskerou "magii" si obstaraji samy. Nedaji se rozumne nahradit __getattr__()/__get().

                Jak rikas, A() muze dedit z neceho, co castecne nahradi funkcnost __getattribute__(). Problem nastava v tom, kdy A je nejaka hotova trida, kterou chci vyuzit, nastavit ji objekt jako vlastnost/deskriptor a pak mit pristup k udalostem set/get - pak jsem v PHP nahranej. Jak udelat v PHP ekvivalent pythoni property()?? Jak se nastavit jako vlastnost nejake cizi tridy a ovlivnit chovani podle dane instance nadrazene tridy?? To jsou vazne veci, ktere v PHP trivialne nevyresis, ani pres __get a __set. To je prave to michani jablek s hruzkama o kterych mluvil Iky a ktere prisuzujes mne - prosim nezamenovat __getattr__ s __get__, oboje je ovoce, ale jedno jsou jablka a jedno hrusky, chutnaji uplne jinak.

                (IP: 89.24.4.xxx)

                odpovědět | 24. 7. | 7:55
                • Jakub Vrána

                  Možná bude nejlepší, když sem vložíš ukázku kódu v Pythonu, jehož obdobu ty osobně neumíš naprogramovat v PHP. Ale nezaměňuj to prosím nadále s tím, že to v PHP nejde (nebo že někdo míchá hrušky a jablka), protože už jsem dvakrát ukázal, že jak deskriptory, tak property v PHP udělat poměrně přímočaře lze.

                  (IP: 193.85.202.xxx)

                  odpovědět | 24. 7. | 10:19
                • Jakub Vrána

                  Jak udělat v PHP ekvivalent Pythoní property():

                  <?php
                  class Property {
                      protected $fget;
                      function __construct($fget) {
                          $this->fget = $fget;
                      }
                      function get($obj) {
                          $fget = $this->fget;
                          return $obj->$fget();
                      }
                  }

                  class NewStyle {
                      protected $descriptors = array();
                      function __get($name) {
                          if (isset($this->descriptors[$name])) {
                              return $this->descriptors[$name]->get($this);
                          }
                      }
                  }

                  class A extends NewStyle {
                      private $_x;
                      function __construct() {
                          $this->descriptors["x"] = new Property('getx');
                      }
                      function getx() {
                          return $this->_x;
                      }
                  }

                  $a = new A;
                  echo "$a->x\n";
                  ?>

                  Jediný rozdíl mezi Pythonem a PHP je v tom, že v PHP nejsou třídy Property a NewStyle předdefinované.

                  A argumentovat tím, že v PHP musí třída využívající deskriptory z něčeho dědit? V Pythonu přeci také - konkrétně z třídy object.

                  (IP: 217.195.170.xxx)

                  odpovědět | 24. 7. | 8:53