{"id":1465,"date":"2026-04-25T13:00:44","date_gmt":"2026-04-25T11:00:44","guid":{"rendered":"https:\/\/trzykody.pl\/?p=1465"},"modified":"2026-04-25T13:00:47","modified_gmt":"2026-04-25T11:00:47","slug":"getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa","status":"publish","type":"post","link":"https:\/\/trzykody.pl\/index.php\/2026\/04\/25\/getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa\/","title":{"rendered":"Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa"},"content":{"rendered":"\n<p>W programowaniu obiektowym bardzo cz\u0119sto pojawia si\u0119 potrzeba dynamicznego odczytu danych z obiektu bez sztywnego odwo\u0142ywania si\u0119 do konkretnej nazwy pola w kodzie. Problem staje si\u0119 widoczny szczeg\u00f3lnie wtedy, gdy nazwa atrybutu pochodzi z konfiguracji, danych wej\u015bciowych u\u017cytkownika, pliku JSON albo zewn\u0119trznego API. Zamiast pisa\u0107 wiele instrukcji warunkowych lub r\u0119cznie mapowa\u0107 nazw\u0119 pola na konkretn\u0105 w\u0142a\u015bciwo\u015b\u0107, wygodniej u\u017cy\u0107 mechanizmu introspekcji obiektu. W praktyce w\u0142a\u015bnie temu s\u0142u\u017cy Getattr, kt\u00f3ry pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Spis Tre\u015bci<\/h2><nav><ol><li><a href=\"#getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-i-pozwala-na-dynamiczny-dostep-do-danych-bez-twardego-kodowania-nazw-pol\">Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i pozwala na dynamiczny dost\u0119p do danych bez twardego kodowania nazw p\u00f3l<\/a><\/li><li><a href=\"#roznica-miedzy-bezposrednim-dostepem-a-getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-wtedy-gdy-nazwa-nie-jest-znana-wczesniej\">R\u00f3\u017cnica mi\u0119dzy bezpo\u015brednim dost\u0119pem a Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa wtedy, gdy nazwa nie jest znana wcze\u015bniej<\/a><\/li><li><a href=\"#getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-i-bywa-podstawa-prostych-systemow-konfiguracji-dispatcherow-oraz-automatyzacji-logiki\">Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i bywa podstaw\u0105 prostych system\u00f3w konfiguracji, dispatcher\u00f3w oraz automatyzacji logiki<\/a><\/li><li><a href=\"#pulapki-bledy-i-miejsca-w-ktorych-dynamiczny-dostep-zaczyna-utrudniac-utrzymanie-kodu\">Pu\u0142apki, b\u0142\u0119dy i miejsca, w kt\u00f3rych dynamiczny dost\u0119p zaczyna utrudnia\u0107 utrzymanie kodu<\/a><\/li><li><a href=\"#zaleznosc-miedzy-introspekcja-refleksja-i-praca-na-metadanych-obiektu\">Zale\u017cno\u015b\u0107 mi\u0119dzy introspekcj\u0105, refleksj\u0105 i prac\u0105 na metadanych obiektu<\/a><\/li><li><a href=\"#faq\">FAQ<\/a><ol><li><a href=\"#czy-getattr-dziala-tylko-w-pythonie\">Czy getattr() dzia\u0142a tylko w Pythonie?<\/a><\/li><li><a href=\"#czy-warto-zawsze-uzywac-trzeciego-argumentu-z-wartoscia-domyslna\">Czy warto zawsze u\u017cywa\u0107 trzeciego argumentu z warto\u015bci\u0105 domy\u015bln\u0105?<\/a><\/li><li><a href=\"#czy-mozna-pobierac-metody-zamiast-zwyklych-pol\">Czy mo\u017cna pobiera\u0107 metody zamiast zwyk\u0142ych p\u00f3l?<\/a><\/li><li><a href=\"#czy-getattr-jest-wolne\">Czy getattr() jest wolne?<\/a><\/li><li><a href=\"#czy-dynamiczne-wywolywanie-metod-jest-bezpieczne\">Czy dynamiczne wywo\u0142ywanie metod jest bezpieczne?<\/a><\/li><li><a href=\"#czy-hasattr-jest-lepsze-od-getattr\">Czy hasattr() jest lepsze od getattr()?<\/a><\/li><\/ol><\/li><\/ol><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-i-pozwala-na-dynamiczny-dostep-do-danych-bez-twardego-kodowania-nazw-pol\">Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i pozwala na dynamiczny dost\u0119p do danych bez twardego kodowania nazw p\u00f3l<\/h2>\n\n\n\n<p>W Pythonie funkcja <code>getattr()<\/code> jest wbudowanym mechanizmem s\u0142u\u017c\u0105cym do pobierania warto\u015bci atrybutu obiektu poprzez przekazanie jego nazwy jako tekstu. To rozwi\u0105zanie jest prostsze ni\u017c bezpo\u015bredni zapis <code>obiekt.atrybut<\/code>, gdy nazwa atrybutu nie jest znana w momencie pisania programu.<\/p>\n\n\n\n<p>Podstawowa sk\u0142adnia wygl\u0105da tak:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Element<\/th><th>Zapis<\/th><\/tr><\/thead><tbody><tr><td>Podstawowa forma<\/td><td><code>getattr(obiekt, \"nazwa\")<\/code><\/td><\/tr><tr><td>Forma bezpieczna<\/td><td><code>getattr(obiekt, \"nazwa\", wartosc_domyslna)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Pierwszy argument to obiekt, drugi to nazwa atrybutu jako string. Trzeci argument jest opcjonalny i ma bardzo du\u017ce znaczenie praktyczne &#8211; pozwala unikn\u0105\u0107 wyj\u0105tku <code>AttributeError<\/code>, je\u015bli atrybut nie istnieje.<\/p>\n\n\n\n<p>Bez trzeciego argumentu:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class User:<\/td><\/tr><tr><td>def <strong>init<\/strong>(self):<\/td><\/tr><tr><td>self.name = &#8222;Anna&#8221;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>u = User()<\/td><\/tr><tr><td>print(getattr(u, &#8222;name&#8221;))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Wynik:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Rezultat<\/th><\/tr><\/thead><tbody><tr><td><code>Anna<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Je\u017celi spr\u00f3bujemy pobra\u0107 nieistniej\u0105cy atrybut:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>print(getattr(u, &#8222;age&#8221;))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>otrzymamy wyj\u0105tek:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>B\u0142\u0105d<\/th><\/tr><\/thead><tbody><tr><td><code>AttributeError<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Dlatego w kodzie produkcyjnym bardzo cz\u0119sto u\u017cywa si\u0119 wersji z warto\u015bci\u0105 domy\u015bln\u0105:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>print(getattr(u, &#8222;age&#8221;, 0))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Wynik:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Rezultat<\/th><\/tr><\/thead><tbody><tr><td><code>0<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To podej\u015bcie oszcz\u0119dza czas i eliminuje konieczno\u015b\u0107 dodatkowych blok\u00f3w <code>try\/except<\/code>.<\/p>\n\n\n\n<p>Warto rozumie\u0107, \u017ce <code>getattr()<\/code> nie dzia\u0142a wy\u0142\u0105cznie na polach danych. Mo\u017cna pobiera\u0107 r\u00f3wnie\u017c metody, poniewa\u017c w Pythonie metody te\u017c s\u0105 atrybutami obiektu.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class User:<\/td><\/tr><tr><td>def hello(self):<\/td><\/tr><tr><td>return &#8222;Witaj&#8221;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>u = User()<\/td><\/tr><tr><td>metoda = getattr(u, &#8222;hello&#8221;)<\/td><\/tr><tr><td>print(metoda())<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Tutaj funkcja zwraca referencj\u0119 do metody, kt\u00f3r\u0105 mo\u017cna p\u00f3\u017aniej wywo\u0142a\u0107.<\/p>\n\n\n\n<p>To jest szczeg\u00f3lnie przydatne w systemach plugin\u00f3w, routerach komend i prostych interpreterach polece\u0144.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"roznica-miedzy-bezposrednim-dostepem-a-getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-wtedy-gdy-nazwa-nie-jest-znana-wczesniej\">R\u00f3\u017cnica mi\u0119dzy bezpo\u015brednim dost\u0119pem a Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa wtedy, gdy nazwa nie jest znana wcze\u015bniej<\/h2>\n\n\n\n<p>Bezpo\u015bredni zapis:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">user.name<\/pre>\n\n\n\n<p>jest szybszy do czytania i zwykle minimalnie szybszy wykonawczo, ale wymaga znajomo\u015bci nazwy atrybutu ju\u017c na etapie pisania programu.<\/p>\n\n\n\n<p>Z kolei:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">getattr(user, nazwa)<\/pre>\n\n\n\n<p>pozwala pracowa\u0107 dynamicznie.<\/p>\n\n\n\n<p>Najprostszy przyk\u0142ad z \u017cycia: import danych CSV.<\/p>\n\n\n\n<p>Za\u0142\u00f3\u017cmy, \u017ce kolumny pliku s\u0105 mapowane na pola obiektu:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>CSV<\/th><\/tr><\/thead><tbody><tr><td><code>name,email,city<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Nazwy kolumn s\u0105 stringami, wi\u0119c program mo\u017ce iterowa\u0107 po nich automatycznie.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class Client:<\/td><\/tr><tr><td>def <strong>init<\/strong>(self):<\/td><\/tr><tr><td>self.name = &#8222;Jan&#8221;<\/td><\/tr><tr><td>self.email = &#8222;<a>jan@example.com<\/a>&#8222;<\/td><\/tr><tr><td>self.city = &#8222;Wroc\u0142aw&#8221;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>c = Client()<\/td><\/tr><tr><td>pola = [&#8222;name&#8221;, &#8222;email&#8221;, &#8222;city&#8221;]<\/td><\/tr><tr><td><\/td><\/tr><tr><td>for pole in pola:<\/td><\/tr><tr><td>print(getattr(c, pole))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To eliminuje konieczno\u015b\u0107 pisania:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">print(c.name)<br>print(c.email)<br>print(c.city)<\/pre>\n\n\n\n<p>dla ka\u017cdego przypadku osobno.<\/p>\n\n\n\n<p>W j\u0119zykach takich jak C lub C++ taki mechanizm nie istnieje wprost jako standardowa funkcja refleksji dla zwyk\u0142ych struktur. Tam dost\u0119p do p\u00f3l dynamicznych zwykle wymaga r\u0119cznego mapowania.<\/p>\n\n\n\n<p>Przyk\u0142ad w C:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>C<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`c<\/td><\/tr><tr><td>#include &lt;stdio.h&gt;<\/td><\/tr><tr><td>#include &lt;string.h&gt;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>struct User {<\/td><\/tr><tr><td>char name[50];<\/td><\/tr><tr><td>int age;<\/td><\/tr><tr><td>};<\/td><\/tr><tr><td><\/td><\/tr><tr><td>int main() {<\/td><\/tr><tr><td>struct User u = {&#8222;Adam&#8221;, 30};<\/td><\/tr><tr><td><\/td><\/tr><tr><td>char field[] = &#8222;age&#8221;;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>if (strcmp(field, &#8222;age&#8221;) == 0)<\/td><\/tr><tr><td>printf(&#8222;%d\\n&#8221;, u.age);<\/td><\/tr><tr><td><\/td><\/tr><tr><td>return 0;<\/td><\/tr><tr><td>}<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Tutaj trzeba r\u0119cznie sprawdza\u0107 nazwy.<\/p>\n\n\n\n<p>W C++ mo\u017cna u\u017cywa\u0107 map lub w\u0142asnych mechanizm\u00f3w refleksji:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>C++<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`cpp<\/td><\/tr><tr><td>#include &lt;iostream&gt;<\/td><\/tr><tr><td>#include &lt;map&gt;<\/td><\/tr><tr><td>using namespace std;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>int main() {<\/td><\/tr><tr><td>map&lt;string, string&gt; user;<\/td><\/tr><tr><td>user[&#8222;name&#8221;] = &#8222;Ewa&#8221;;<\/td><\/tr><tr><td>user[&#8222;city&#8221;] = &#8222;Opole&#8221;;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>cout &lt;&lt; user[&#8222;city&#8221;] &lt;&lt; endl;<\/td><\/tr><tr><td>return 0;<\/td><\/tr><tr><td>}<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Python robi to natywnie i znacznie wygodniej.<\/p>\n\n\n\n<p>Warto te\u017c pami\u0119ta\u0107 o r\u00f3\u017cnicy mi\u0119dzy <code>getattr()<\/code> a <code>hasattr()<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Funkcja<\/th><th>Cel<\/th><\/tr><\/thead><tbody><tr><td><code>getattr()<\/code><\/td><td>pobranie warto\u015bci<\/td><\/tr><tr><td><code>hasattr()<\/code><\/td><td>sprawdzenie istnienia<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Przyk\u0142ad:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>if hasattr(u, &#8222;name&#8221;):<\/td><\/tr><tr><td>print(getattr(u, &#8222;name&#8221;))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>W praktyce cz\u0119\u015bciej lepsze jest u\u017cycie trzeciego argumentu <code>getattr()<\/code>, bo wykonuje oba zadania naraz.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"getattr-pobiera-wartosc-atrybutu-obiektu-na-podstawie-jego-nazwy-w-formie-stringa-i-bywa-podstawa-prostych-systemow-konfiguracji-dispatcherow-oraz-automatyzacji-logiki\">Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i bywa podstaw\u0105 prostych system\u00f3w konfiguracji, dispatcher\u00f3w oraz automatyzacji logiki<\/h2>\n\n\n\n<p>Jedno z najcz\u0119stszych zastosowa\u0144 to dispatcher metod, czyli uruchamianie r\u00f3\u017cnych funkcji na podstawie tekstowej komendy.<\/p>\n\n\n\n<p>Przyk\u0142ad: prosty system polece\u0144.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class Commands:<\/td><\/tr><tr><td>def start(self):<\/td><\/tr><tr><td>print(&#8222;Start programu&#8221;)<\/td><\/tr><tr><td><\/td><\/tr><tr><td>def stop(self):<\/td><\/tr><tr><td>print(&#8222;Stop programu&#8221;)<\/td><\/tr><tr><td><\/td><\/tr><tr><td>c = Commands()<\/td><\/tr><tr><td>polecenie = &#8222;start&#8221;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>metoda = getattr(c, polecenie, None)<\/td><\/tr><tr><td><\/td><\/tr><tr><td>if metoda:<\/td><\/tr><tr><td>metoda()<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Bez tego trzeba by\u0142oby pisa\u0107 wiele <code>if\/elif<\/code>.<\/p>\n\n\n\n<p>W systemach administracyjnych i panelach backendowych ten wzorzec pojawia si\u0119 bardzo cz\u0119sto.<\/p>\n\n\n\n<p>Drugie praktyczne zastosowanie to konfiguracja.<\/p>\n\n\n\n<p>Za\u0142\u00f3\u017cmy, \u017ce parametry systemu s\u0105 zapisane jako nazwy p\u00f3l:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class Config:<\/td><\/tr><tr><td>timeout = 30<\/td><\/tr><tr><td>retries = 5<\/td><\/tr><tr><td><\/td><\/tr><tr><td>cfg = Config()<\/td><\/tr><tr><td>klucz = &#8222;timeout&#8221;<\/td><\/tr><tr><td><\/td><\/tr><tr><td>print(getattr(cfg, klucz, 10))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Dzi\u0119ki temu mo\u017cna budowa\u0107 elastyczne mechanizmy bez przebudowy ca\u0142ej logiki.<\/p>\n\n\n\n<p>Trzecie zastosowanie to serializacja i logowanie.<\/p>\n\n\n\n<p>Je\u017celi trzeba wypisa\u0107 stan obiektu:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>fields = [&#8222;name&#8221;, &#8222;email&#8221;, &#8222;status&#8221;]<\/td><\/tr><tr><td><\/td><\/tr><tr><td>for field in fields:<\/td><\/tr><tr><td>print(field, getattr(user, field, &#8222;brak&#8221;))<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Taki kod jest prosty, czytelny i \u0142atwy do rozszerzenia.<\/p>\n\n\n\n<p>Trzeba jednak uwa\u017ca\u0107 na bezpiecze\u0144stwo. Dynamiczne wywo\u0142ywanie metod na podstawie danych u\u017cytkownika mo\u017ce by\u0107 niebezpieczne.<\/p>\n\n\n\n<p>Z\u0142y przyk\u0142ad:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>komenda = input()<\/td><\/tr><tr><td>getattr(system, komenda)()<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Je\u017celi u\u017cytkownik poda nazw\u0119 metody administracyjnej albo wewn\u0119trznej funkcji, mo\u017ce uruchomi\u0107 co\u015b, czego nie powinien.<\/p>\n\n\n\n<p>Dlatego stosuje si\u0119 whitelist\u0119:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>dozwolone = [&#8222;start&#8221;, &#8222;stop&#8221;]<\/td><\/tr><tr><td><\/td><\/tr><tr><td>if komenda in dozwolone:<\/td><\/tr><tr><td>getattr(system, komenda)()<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To bardzo wa\u017cne w praktyce.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pulapki-bledy-i-miejsca-w-ktorych-dynamiczny-dostep-zaczyna-utrudniac-utrzymanie-kodu\">Pu\u0142apki, b\u0142\u0119dy i miejsca, w kt\u00f3rych dynamiczny dost\u0119p zaczyna utrudnia\u0107 utrzymanie kodu<\/h2>\n\n\n\n<p>Najcz\u0119stszy b\u0142\u0105d to nadu\u017cywanie dynamicznego dost\u0119pu tam, gdzie zwyk\u0142e <code>obiekt.atrybut<\/code> by\u0142oby lepsze.<\/p>\n\n\n\n<p>Je\u017celi nazwa pola jest sta\u0142a, nie ma sensu u\u017cywa\u0107 <code>getattr()<\/code>. Kod staje si\u0119 mniej czytelny:<\/p>\n\n\n\n<p>zamiast:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">user.email<\/pre>\n\n\n\n<p>powstaje:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">getattr(user, \"email\")<\/pre>\n\n\n\n<p>To nie daje \u017cadnej korzy\u015bci.<\/p>\n\n\n\n<p>Drugi problem to ukrywanie b\u0142\u0119d\u00f3w przez z\u0142\u0105 warto\u015b\u0107 domy\u015bln\u0105.<\/p>\n\n\n\n<p>Przyk\u0142ad:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>salary = getattr(employee, &#8222;salary&#8221;, 0)<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Je\u017celi pole powinno istnie\u0107 zawsze, warto\u015b\u0107 <code>0<\/code> mo\u017ce ukry\u0107 realny problem w danych. Program b\u0119dzie dzia\u0142a\u0142, ale b\u0142\u0119dnie.<\/p>\n\n\n\n<p>Trzeci problem to wydajno\u015b\u0107 przy bardzo du\u017cej liczbie operacji.<\/p>\n\n\n\n<p>Jedno wywo\u0142anie nie ma znaczenia, ale przy milionach iteracji w systemach analitycznych r\u00f3\u017cnica mo\u017ce by\u0107 zauwa\u017calna. Bezpo\u015bredni dost\u0119p do atrybutu jest zwykle szybszy.<\/p>\n\n\n\n<p>Czwarty problem dotyczy debugowania.<\/p>\n\n\n\n<p>B\u0142\u0119dy typu:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">getattr(obj, dynamic_name)<\/pre>\n\n\n\n<p>s\u0105 trudniejsze do znaleziencia ni\u017c klasyczne:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">obj.name<\/pre>\n\n\n\n<p>bo problem wynika z danych wej\u015bciowych, a nie z samego kodu.<\/p>\n\n\n\n<p>Dlatego dobra praktyka jest prosta:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>u\u017cywa\u0107 dynamicznego dost\u0119pu tylko tam, gdzie naprawd\u0119 jest potrzebny,<\/li>\n\n\n\n<li>stosowa\u0107 warto\u015b\u0107 domy\u015bln\u0105 \u015bwiadomie,<\/li>\n\n\n\n<li>nie uruchamia\u0107 metod bez walidacji nazwy,<\/li>\n\n\n\n<li>nie ukrywa\u0107 b\u0142\u0119d\u00f3w architektury pod warstw\u0105 refleksji.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"zaleznosc-miedzy-introspekcja-refleksja-i-praca-na-metadanych-obiektu\">Zale\u017cno\u015b\u0107 mi\u0119dzy introspekcj\u0105, refleksj\u0105 i prac\u0105 na metadanych obiektu<\/h2>\n\n\n\n<p><code>getattr()<\/code> jest prostym elementem wi\u0119kszego mechanizmu introspekcji.<\/p>\n\n\n\n<p>Introspekcja oznacza mo\u017cliwo\u015b\u0107 badania struktury obiektu w czasie dzia\u0142ania programu. Python mocno wspiera takie podej\u015bcie.<\/p>\n\n\n\n<p>Najcz\u0119\u015bciej u\u017cywane funkcje:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Funkcja<\/th><th>Zastosowanie<\/th><\/tr><\/thead><tbody><tr><td><code>getattr()<\/code><\/td><td>pobranie warto\u015bci<\/td><\/tr><tr><td><code>setattr()<\/code><\/td><td>ustawienie warto\u015bci<\/td><\/tr><tr><td><code>hasattr()<\/code><\/td><td>sprawdzenie istnienia<\/td><\/tr><tr><td><code>delattr()<\/code><\/td><td>usuni\u0119cie atrybutu<\/td><\/tr><tr><td><code>dir()<\/code><\/td><td>lista dost\u0119pnych atrybut\u00f3w<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Przyk\u0142ad zestawienia:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><\/tr><\/thead><tbody><tr><td>&#8222;`python<\/td><\/tr><tr><td>class Product:<\/td><\/tr><tr><td>pass<\/td><\/tr><tr><td><\/td><\/tr><tr><td>p = Product()<\/td><\/tr><tr><td><\/td><\/tr><tr><td>setattr(p, &#8222;price&#8221;, 199)<\/td><\/tr><tr><td>print(getattr(p, &#8222;price&#8221;))<\/td><\/tr><tr><td>print(hasattr(p, &#8222;price&#8221;))<\/td><\/tr><tr><td>delattr(p, &#8222;price&#8221;)<\/td><\/tr><tr><td>&#8222;`<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To pokazuje pe\u0142ny cykl pracy na atrybutach dynamicznych.<\/p>\n\n\n\n<p>W praktyce te funkcje s\u0105 fundamentem wielu bibliotek ORM, framework\u00f3w webowych i narz\u0119dzi automatyzuj\u0105cych mapowanie danych.<\/p>\n\n\n\n<p>Dla pocz\u0105tkuj\u0105cych programist\u00f3w wygl\u0105da to czasem jak \u201emagia frameworka\u201d, ale zwykle pod spodem dzia\u0142a w\u0142a\u015bnie taki prosty mechanizm.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faq\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-getattr-dziala-tylko-w-pythonie\">Czy <code>getattr()<\/code> dzia\u0142a tylko w Pythonie?<\/h3>\n\n\n\n<p>Nie. Sama funkcja o tej nazwie jest charakterystyczna dla Pythona, ale idea dynamicznego dost\u0119pu do p\u00f3l istnieje tak\u017ce w innych j\u0119zykach. Java u\u017cywa refleksji, PHP ma mechanizmy dynamicznych w\u0142a\u015bciwo\u015bci, a C# korzysta z reflection API.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-warto-zawsze-uzywac-trzeciego-argumentu-z-wartoscia-domyslna\">Czy warto zawsze u\u017cywa\u0107 trzeciego argumentu z warto\u015bci\u0105 domy\u015bln\u0105?<\/h3>\n\n\n\n<p>Nie zawsze. Je\u015bli brak atrybutu oznacza b\u0142\u0105d logiczny programu, lepiej dopu\u015bci\u0107 wyj\u0105tek i szybciej wykry\u0107 problem. Warto\u015b\u0107 domy\u015blna jest dobra wtedy, gdy brak pola jest akceptowalnym scenariuszem.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-mozna-pobierac-metody-zamiast-zwyklych-pol\">Czy mo\u017cna pobiera\u0107 metody zamiast zwyk\u0142ych p\u00f3l?<\/h3>\n\n\n\n<p>Tak. Metody s\u0105 r\u00f3wnie\u017c atrybutami obiektu. <code>getattr()<\/code> mo\u017ce zwr\u00f3ci\u0107 funkcj\u0119, kt\u00f3r\u0105 p\u00f3\u017aniej mo\u017cna wywo\u0142a\u0107.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-getattr-jest-wolne\">Czy <code>getattr()<\/code> jest wolne?<\/h3>\n\n\n\n<p>W normalnym kodzie r\u00f3\u017cnica jest pomijalna. Problem pojawia si\u0119 dopiero przy ogromnej liczbie operacji, np. w przetwarzaniu milion\u00f3w rekord\u00f3w.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-dynamiczne-wywolywanie-metod-jest-bezpieczne\">Czy dynamiczne wywo\u0142ywanie metod jest bezpieczne?<\/h3>\n\n\n\n<p>Tylko wtedy, gdy nazwy s\u0105 kontrolowane. Dane pochodz\u0105ce od u\u017cytkownika powinny by\u0107 filtrowane przez whitelist\u0119 dozwolonych komend.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-hasattr-jest-lepsze-od-getattr\">Czy <code>hasattr()<\/code> jest lepsze od <code>getattr()<\/code>?<\/h3>\n\n\n\n<p>Nie zawsze. Je\u015bli i tak potrzebna jest warto\u015b\u0107, cz\u0119sto lepiej u\u017cy\u0107 <code>getattr()<\/code> z warto\u015bci\u0105 domy\u015bln\u0105, bo wykonuje oba zadania jednocze\u015bnie.<\/p>\n\n\n\n<p><em>\u0179r\u00f3d\u0142o Foto: Freepik<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>W programowaniu obiektowym bardzo cz\u0119sto pojawia si\u0119 potrzeba dynamicznego odczytu danych z obiektu bez sztywnego odwo\u0142ywania si\u0119 do konkretnej nazwy pola w kodzie. Problem staje si\u0119 widoczny szczeg\u00f3lnie wtedy, gdy nazwa atrybutu pochodzi z konfiguracji, danych wej\u015bciowych u\u017cytkownika, pliku JSON albo zewn\u0119trznego API. Zamiast pisa\u0107 wiele instrukcji warunkowych lub r\u0119cznie mapowa\u0107 nazw\u0119 pola na konkretn\u0105 w\u0142a\u015bciwo\u015b\u0107, wygodniej u\u017cy\u0107 mechanizmu introspekcji obiektu. W praktyce w\u0142a\u015bnie temu s\u0142u\u017cy Getattr, kt\u00f3ry pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa. Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i pozwala na dynamiczny dost\u0119p do danych bez twardego kodowania nazw p\u00f3l W Pythonie funkcja getattr() jest wbudowanym mechanizmem s\u0142u\u017c\u0105cym do pobierania warto\u015bci atrybutu obiektu poprzez przekazanie jego nazwy jako tekstu. To rozwi\u0105zanie jest prostsze ni\u017c bezpo\u015bredni zapis obiekt.atrybut, gdy nazwa atrybutu nie jest znana w momencie pisania programu. Podstawowa sk\u0142adnia wygl\u0105da tak: Element Zapis Podstawowa forma getattr(obiekt, &#8222;nazwa&#8221;) Forma bezpieczna getattr(obiekt, &#8222;nazwa&#8221;, wartosc_domyslna) Pierwszy argument to obiekt, drugi to nazwa atrybutu jako string. Trzeci argument jest opcjonalny i ma bardzo du\u017ce znaczenie praktyczne &#8211; pozwala unikn\u0105\u0107 wyj\u0105tku AttributeError, je\u015bli atrybut nie istnieje. Bez trzeciego argumentu: Python &#8222;`python class User: def init(self): self.name = &#8222;Anna&#8221; u = User() print(getattr(u, &#8222;name&#8221;)) &#8222;` Wynik: Rezultat Anna Je\u017celi spr\u00f3bujemy pobra\u0107 nieistniej\u0105cy atrybut: Python &#8222;`python print(getattr(u, &#8222;age&#8221;)) &#8222;` otrzymamy wyj\u0105tek: B\u0142\u0105d AttributeError Dlatego w kodzie produkcyjnym bardzo cz\u0119sto u\u017cywa si\u0119 wersji z warto\u015bci\u0105 domy\u015bln\u0105: Python &#8222;`python print(getattr(u, &#8222;age&#8221;, 0)) &#8222;` Wynik: Rezultat 0 To podej\u015bcie oszcz\u0119dza czas i eliminuje konieczno\u015b\u0107 dodatkowych blok\u00f3w try\/except. Warto rozumie\u0107, \u017ce getattr() nie dzia\u0142a wy\u0142\u0105cznie na polach danych. Mo\u017cna pobiera\u0107 r\u00f3wnie\u017c metody, poniewa\u017c w Pythonie metody te\u017c s\u0105 atrybutami obiektu. Python &#8222;`python class User: def hello(self): return &#8222;Witaj&#8221; u = User() metoda = getattr(u, &#8222;hello&#8221;) print(metoda()) &#8222;` Tutaj funkcja zwraca referencj\u0119 do metody, kt\u00f3r\u0105 mo\u017cna p\u00f3\u017aniej wywo\u0142a\u0107. To jest szczeg\u00f3lnie przydatne w systemach plugin\u00f3w, routerach komend i prostych interpreterach polece\u0144. R\u00f3\u017cnica mi\u0119dzy bezpo\u015brednim dost\u0119pem a Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa wtedy, gdy nazwa nie jest znana wcze\u015bniej Bezpo\u015bredni zapis: user.name jest szybszy do czytania i zwykle minimalnie szybszy wykonawczo, ale wymaga znajomo\u015bci nazwy atrybutu ju\u017c na etapie pisania programu. Z kolei: getattr(user, nazwa) pozwala pracowa\u0107 dynamicznie. Najprostszy przyk\u0142ad z \u017cycia: import danych CSV. Za\u0142\u00f3\u017cmy, \u017ce kolumny pliku s\u0105 mapowane na pola obiektu: CSV name,email,city Nazwy kolumn s\u0105 stringami, wi\u0119c program mo\u017ce iterowa\u0107 po nich automatycznie. Python &#8222;`python class Client: def init(self): self.name = &#8222;Jan&#8221; self.email = &#8222;jan@example.com&#8222; self.city = &#8222;Wroc\u0142aw&#8221; c = Client() pola = [&#8222;name&#8221;, &#8222;email&#8221;, &#8222;city&#8221;] for pole in pola: print(getattr(c, pole)) &#8222;` To eliminuje konieczno\u015b\u0107 pisania: print(c.name)print(c.email)print(c.city) dla ka\u017cdego przypadku osobno. W j\u0119zykach takich jak C lub C++ taki mechanizm nie istnieje wprost jako standardowa funkcja refleksji dla zwyk\u0142ych struktur. Tam dost\u0119p do p\u00f3l dynamicznych zwykle wymaga r\u0119cznego mapowania. Przyk\u0142ad w C: C &#8222;`c #include &lt;stdio.h&gt; #include &lt;string.h&gt; struct User { char name[50]; int age; }; int main() { struct User u = {&#8222;Adam&#8221;, 30}; char field[] = &#8222;age&#8221;; if (strcmp(field, &#8222;age&#8221;) == 0) printf(&#8222;%d\\n&#8221;, u.age); return 0; } &#8222;` Tutaj trzeba r\u0119cznie sprawdza\u0107 nazwy. W C++ mo\u017cna u\u017cywa\u0107 map lub w\u0142asnych mechanizm\u00f3w refleksji: C++ &#8222;`cpp #include &lt;iostream&gt; #include &lt;map&gt; using namespace std; int main() { map&lt;string, string&gt; user; user[&#8222;name&#8221;] = &#8222;Ewa&#8221;; user[&#8222;city&#8221;] = &#8222;Opole&#8221;; cout &lt;&lt; user[&#8222;city&#8221;] &lt;&lt; endl; return 0; } &#8222;` Python robi to natywnie i znacznie wygodniej. Warto te\u017c pami\u0119ta\u0107 o r\u00f3\u017cnicy mi\u0119dzy getattr() a hasattr(). Funkcja Cel getattr() pobranie warto\u015bci hasattr() sprawdzenie istnienia Przyk\u0142ad: Python &#8222;`python if hasattr(u, &#8222;name&#8221;): print(getattr(u, &#8222;name&#8221;)) &#8222;` W praktyce cz\u0119\u015bciej lepsze jest u\u017cycie trzeciego argumentu getattr(), bo wykonuje oba zadania naraz. Getattr \u2013 pobiera warto\u015b\u0107 atrybutu obiektu na podstawie jego nazwy w formie stringa i bywa podstaw\u0105 prostych system\u00f3w konfiguracji, dispatcher\u00f3w oraz automatyzacji logiki Jedno z najcz\u0119stszych zastosowa\u0144 to dispatcher metod, czyli uruchamianie r\u00f3\u017cnych funkcji na podstawie tekstowej komendy. Przyk\u0142ad: prosty system polece\u0144. Python &#8222;`python class Commands: def start(self): print(&#8222;Start programu&#8221;) def stop(self): print(&#8222;Stop programu&#8221;) c = Commands() polecenie = &#8222;start&#8221; metoda = getattr(c, polecenie, None) if metoda: metoda() &#8222;` Bez tego trzeba by\u0142oby pisa\u0107 wiele if\/elif. W systemach administracyjnych i panelach backendowych ten wzorzec pojawia si\u0119 bardzo cz\u0119sto. Drugie praktyczne zastosowanie to konfiguracja. Za\u0142\u00f3\u017cmy, \u017ce parametry systemu s\u0105 zapisane jako nazwy p\u00f3l: Python &#8222;`python class Config: timeout = 30 retries = 5 cfg = Config() klucz = &#8222;timeout&#8221; print(getattr(cfg, klucz, 10)) &#8222;` Dzi\u0119ki temu mo\u017cna budowa\u0107 elastyczne mechanizmy bez przebudowy ca\u0142ej logiki. Trzecie zastosowanie to serializacja i logowanie. Je\u017celi trzeba wypisa\u0107 stan obiektu: Python &#8222;`python fields = [&#8222;name&#8221;, &#8222;email&#8221;, &#8222;status&#8221;] for field in fields: print(field, getattr(user, field, &#8222;brak&#8221;)) &#8222;` Taki kod jest prosty, czytelny i \u0142atwy do rozszerzenia. Trzeba jednak uwa\u017ca\u0107 na bezpiecze\u0144stwo. Dynamiczne wywo\u0142ywanie metod na podstawie danych u\u017cytkownika mo\u017ce by\u0107 niebezpieczne. Z\u0142y przyk\u0142ad: Python &#8222;`python komenda = input() getattr(system, komenda)() &#8222;` Je\u017celi u\u017cytkownik poda nazw\u0119 metody administracyjnej albo wewn\u0119trznej funkcji, mo\u017ce uruchomi\u0107 co\u015b, czego nie powinien. Dlatego stosuje si\u0119 whitelist\u0119: Python &#8222;`python dozwolone = [&#8222;start&#8221;, &#8222;stop&#8221;] if komenda in dozwolone: getattr(system, komenda)() &#8222;` To bardzo wa\u017cne w praktyce. Pu\u0142apki, b\u0142\u0119dy i miejsca, w kt\u00f3rych dynamiczny dost\u0119p zaczyna utrudnia\u0107 utrzymanie kodu Najcz\u0119stszy b\u0142\u0105d to nadu\u017cywanie dynamicznego dost\u0119pu tam, gdzie zwyk\u0142e obiekt.atrybut by\u0142oby lepsze. Je\u017celi nazwa pola jest sta\u0142a, nie ma sensu u\u017cywa\u0107 getattr(). Kod staje si\u0119 mniej czytelny: zamiast: user.email powstaje: getattr(user, &#8222;email&#8221;) To nie daje \u017cadnej korzy\u015bci. Drugi problem to ukrywanie b\u0142\u0119d\u00f3w przez z\u0142\u0105 warto\u015b\u0107 domy\u015bln\u0105. Przyk\u0142ad: Python &#8222;`python salary = getattr(employee, &#8222;salary&#8221;, 0) &#8222;` Je\u017celi pole powinno istnie\u0107 zawsze, warto\u015b\u0107 0 mo\u017ce ukry\u0107 realny problem w danych. Program b\u0119dzie dzia\u0142a\u0142, ale b\u0142\u0119dnie. Trzeci problem to wydajno\u015b\u0107 przy bardzo du\u017cej liczbie operacji. Jedno wywo\u0142anie nie ma znaczenia, ale przy milionach iteracji w systemach analitycznych r\u00f3\u017cnica mo\u017ce by\u0107 zauwa\u017calna. Bezpo\u015bredni dost\u0119p do atrybutu jest zwykle szybszy. Czwarty problem dotyczy debugowania. B\u0142\u0119dy typu: getattr(obj, dynamic_name) s\u0105 trudniejsze do znaleziencia ni\u017c klasyczne: obj.name bo problem wynika z danych wej\u015bciowych, a nie z samego kodu. Dlatego dobra praktyka jest prosta: Zale\u017cno\u015b\u0107 mi\u0119dzy introspekcj\u0105, refleksj\u0105 i prac\u0105 na metadanych obiektu getattr() jest prostym elementem wi\u0119kszego mechanizmu introspekcji. Introspekcja oznacza mo\u017cliwo\u015b\u0107 badania struktury obiektu w czasie dzia\u0142ania programu. Python mocno wspiera takie podej\u015bcie. Najcz\u0119\u015bciej u\u017cywane funkcje: Funkcja Zastosowanie getattr() pobranie warto\u015bci setattr() ustawienie warto\u015bci hasattr() sprawdzenie istnienia delattr() usuni\u0119cie atrybutu dir() lista dost\u0119pnych atrybut\u00f3w Przyk\u0142ad zestawienia: Python &#8222;`python class Product: pass p = Product() setattr(p, &#8222;price&#8221;, 199) print(getattr(p, &#8222;price&#8221;)) print(hasattr(p, &#8222;price&#8221;)) delattr(p, &#8222;price&#8221;) &#8222;` To pokazuje pe\u0142ny cykl pracy na atrybutach dynamicznych. W praktyce te funkcje s\u0105 fundamentem wielu bibliotek ORM, framework\u00f3w webowych i narz\u0119dzi automatyzuj\u0105cych mapowanie danych. Dla pocz\u0105tkuj\u0105cych programist\u00f3w wygl\u0105da to czasem jak \u201emagia frameworka\u201d, ale zwykle pod spodem dzia\u0142a w\u0142a\u015bnie taki prosty mechanizm. FAQ Czy getattr() dzia\u0142a tylko w Pythonie? Nie. Sama funkcja o tej nazwie jest charakterystyczna dla Pythona, ale idea dynamicznego dost\u0119pu do p\u00f3l istnieje tak\u017ce w innych j\u0119zykach. Java u\u017cywa refleksji, PHP ma mechanizmy dynamicznych w\u0142a\u015bciwo\u015bci, a C# korzysta z reflection API. Czy warto zawsze u\u017cywa\u0107 trzeciego argumentu z warto\u015bci\u0105 domy\u015bln\u0105? Nie zawsze. Je\u015bli brak atrybutu oznacza b\u0142\u0105d logiczny programu, lepiej dopu\u015bci\u0107 wyj\u0105tek i szybciej wykry\u0107 problem. Warto\u015b\u0107 domy\u015blna jest dobra wtedy, gdy brak pola jest akceptowalnym scenariuszem. Czy mo\u017cna pobiera\u0107 metody zamiast zwyk\u0142ych p\u00f3l? Tak. Metody s\u0105 r\u00f3wnie\u017c atrybutami obiektu. getattr() mo\u017ce zwr\u00f3ci\u0107 funkcj\u0119, kt\u00f3r\u0105 p\u00f3\u017aniej mo\u017cna wywo\u0142a\u0107. Czy getattr() jest wolne? W normalnym kodzie r\u00f3\u017cnica jest pomijalna. Problem pojawia si\u0119 dopiero przy ogromnej liczbie operacji, np. w przetwarzaniu milion\u00f3w rekord\u00f3w. Czy dynamiczne wywo\u0142ywanie metod jest bezpieczne? Tylko wtedy, gdy nazwy s\u0105 kontrolowane. Dane pochodz\u0105ce od u\u017cytkownika powinny by\u0107 filtrowane przez whitelist\u0119 dozwolonych komend. Czy hasattr() jest lepsze od getattr()? Nie zawsze. Je\u015bli i tak potrzebna jest warto\u015b\u0107, cz\u0119sto lepiej u\u017cy\u0107 getattr() z warto\u015bci\u0105 domy\u015bln\u0105, bo wykonuje oba zadania jednocze\u015bnie. \u0179r\u00f3d\u0142o Foto: Freepik<\/p>\n","protected":false},"author":1,"featured_media":1466,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[],"class_list":["post-1465","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jezyk-programowania"],"_links":{"self":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1465"}],"version-history":[{"count":1,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1465\/revisions"}],"predecessor-version":[{"id":1467,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1465\/revisions\/1467"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media\/1466"}],"wp:attachment":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}