{"id":1537,"date":"2026-04-23T16:07:12","date_gmt":"2026-04-23T14:07:12","guid":{"rendered":"https:\/\/trzykody.pl\/?p=1537"},"modified":"2026-04-28T16:11:31","modified_gmt":"2026-04-28T14:11:31","slug":"setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie","status":"publish","type":"post","link":"https:\/\/trzykody.pl\/index.php\/2026\/04\/23\/setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie\/","title":{"rendered":"Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie"},"content":{"rendered":"\n<p>W programowaniu obiektowym cz\u0119sto pojawia si\u0119 potrzeba modyfikowania obiektu bez r\u0119cznego odwo\u0142ywania si\u0119 do ka\u017cdego pola osobno. Dotyczy to konfiguracji klas, mapowania danych z formularzy, importu plik\u00f3w JSON, budowania prostych ORM czy automatycznego uzupe\u0142niania modeli danych. Python pozwala robi\u0107 to bardzo elastycznie, poniewa\u017c obiekty mo\u017cna modyfikowa\u0107 tak\u017ce w czasie dzia\u0142ania programu, a nie tylko na etapie definicji klasy. W praktyce w\u0142a\u015bnie temu s\u0142u\u017cy Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie.<\/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=\"#setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-w-praktyce-dzialania-modelu-obiektowego-pythona\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie w praktyce dzia\u0142ania modelu obiektowego Pythona<\/a><ol><li><a href=\"#co-dzieje-sie-wewnetrznie\">Co dzieje si\u0119 wewn\u0119trznie<\/a><\/li><li><a href=\"#podstawowe-przyklady-dzialania\">Podstawowe przyk\u0142ady dzia\u0142ania<\/a><\/li><\/ol><\/li><li><a href=\"#dlaczego-dynamiczne-ustawianie-atrybutow-jest-potrzebne-przy-pracy-z-formularzami-api-i-konfiguracja-systemu\">Dlaczego dynamiczne ustawianie atrybut\u00f3w jest potrzebne przy pracy z formularzami, API i konfiguracj\u0105 systemu<\/a><\/li><li><a href=\"#setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-podczas-konfiguracji-klas-instancji-i-danych-wejsciowych\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie podczas konfiguracji klas, instancji i danych wej\u015bciowych<\/a><ol><li><a href=\"#roznica-miedzy-klasa-a-instancja\">R\u00f3\u017cnica mi\u0119dzy klas\u0105 a instancj\u0105<\/a><\/li><li><a href=\"#wspolpraca-z-getattr-i-hasattr\">Wsp\u00f3\u0142praca z getattr() i hasattr()<\/a><\/li><\/ol><\/li><li><a href=\"#kontrola-nad-przypisaniem-przez-metode-setattr-i-jej-realne-znaczenie-w-wiekszych-projektach\">Kontrola nad przypisaniem przez metod\u0119 __setattr__() i jej realne znaczenie w wi\u0119kszych projektach<\/a><\/li><li><a href=\"#setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-i-wymaga-kontroli-bezpieczenstwa-oraz-przewidywalnosci\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie i wymaga kontroli bezpiecze\u0144stwa oraz przewidywalno\u015bci<\/a><ol><li><a href=\"#literowki-sa-grozniejsze-niz-wygladaja\">Liter\u00f3wki s\u0105 gro\u017aniejsze ni\u017c wygl\u0105daj\u0105<\/a><\/li><\/ol><\/li><li><a href=\"#wzory-myslenia-o-tym-mechanizmie-i-porownanie-z-podejsciem-statycznym\">Wzory my\u015blenia o tym mechanizmie i por\u00f3wnanie z podej\u015bciem statycznym<\/a><\/li><li><a href=\"#krotkie-uwagi-praktyczne-ktore-oszczedzaja-najwiecej-czasu-podczas-pracy\">Kr\u00f3tkie uwagi praktyczne, kt\u00f3re oszcz\u0119dzaj\u0105 najwi\u0119cej czasu podczas pracy<\/a><\/li><li><a href=\"#faq\">FAQ<\/a><ol><li><a href=\"#czy-setattr-tworzy-nowy-atrybut-jesli-wczesniej-go-nie-bylo\">Czy setattr() tworzy nowy atrybut, je\u015bli wcze\u015bniej go nie by\u0142o?<\/a><\/li><li><a href=\"#czy-setattr-jest-szybsze-od-zwyklego-przypisania\">Czy setattr() jest szybsze od zwyk\u0142ego przypisania?<\/a><\/li><li><a href=\"#czy-mozna-uzywac-setattr-na-klasie-zamiast-instancji\">Czy mo\u017cna u\u017cywa\u0107 setattr() na klasie zamiast instancji?<\/a><\/li><li><a href=\"#czy-setattr-omija-walidacje-zdefiniowana-w-klasie\">Czy setattr() omija walidacj\u0119 zdefiniowan\u0105 w klasie?<\/a><\/li><li><a href=\"#czy-warto-uzywac-tego-mechanizmu-w-kodzie-produkcyjnym\">Czy warto u\u017cywa\u0107 tego mechanizmu w kodzie produkcyjnym?<\/a><\/li><\/ol><\/li><\/ol><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-w-praktyce-dzialania-modelu-obiektowego-pythona\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie w praktyce dzia\u0142ania modelu obiektowego Pythona<\/h2>\n\n\n\n<p>Funkcja <code>setattr()<\/code> jest wbudowan\u0105 funkcj\u0105 Pythona s\u0142u\u017c\u0105c\u0105 do ustawiania warto\u015bci atrybutu obiektu na podstawie nazwy przekazanej jako tekst. Zamiast pisa\u0107:<\/p>\n\n\n\n<p><code>obiekt.imie = \"Jan\"<\/code><\/p>\n\n\n\n<p>mo\u017cna wykona\u0107:<\/p>\n\n\n\n<p><code>setattr(obiekt, \"imie\", \"Jan\")<\/code><\/p>\n\n\n\n<p>Efekt ko\u0144cowy jest identyczny, ale druga forma pozwala budowa\u0107 kod dynamiczny, czyli taki, w kt\u00f3rym nazwa pola nie jest znana wcze\u015bniej i pochodzi na przyk\u0142ad z pliku konfiguracyjnego, API albo danych u\u017cytkownika.<\/p>\n\n\n\n<p>Sk\u0142adnia jest bardzo prosta:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Element<\/th><th>Opis<\/th><\/tr><\/thead><tbody><tr><td><code>setattr(obiekt, nazwa, wartosc)<\/code><\/td><td>ustawia atrybut<\/td><\/tr><tr><td><code>obiekt<\/code><\/td><td>instancja klasy lub klasa<\/td><\/tr><tr><td><code>nazwa<\/code><\/td><td>nazwa atrybutu jako <code>str<\/code><\/td><\/tr><tr><td><code>wartosc<\/code><\/td><td>warto\u015b\u0107 przypisywana do pola<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Najwa\u017cniejsze jest to, \u017ce <code>nazwa<\/code> musi by\u0107 tekstem. Python nie oczekuje tutaj referencji do pola, tylko jego nazwy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"co-dzieje-sie-wewnetrznie\">Co dzieje si\u0119 wewn\u0119trznie<\/h3>\n\n\n\n<p>Wi\u0119kszo\u015b\u0107 zwyk\u0142ych obiekt\u00f3w Pythona przechowuje dane w s\u0142owniku <code>__dict__<\/code>. Gdy wykonujemy <code>setattr()<\/code>, interpreter aktualizuje w\u0142a\u015bnie ten mechanizm albo uruchamia w\u0142asn\u0105 logik\u0119 klasy, je\u015bli zdefiniowano <code>__setattr__()<\/code>.<\/p>\n\n\n\n<p>To wa\u017cne, bo oznacza, \u017ce:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mo\u017cna tworzy\u0107 nowe pola \u201ew locie\u201d<\/li>\n\n\n\n<li>mo\u017cna nadpisywa\u0107 istniej\u0105ce warto\u015bci<\/li>\n\n\n\n<li>mo\u017cna przechwyci\u0107 ca\u0142y proces i go kontrolowa\u0107<\/li>\n<\/ul>\n\n\n\n<p>To daje du\u017c\u0105 wygod\u0119, ale te\u017c \u0142atwo wprowadzi\u0107 trudny do wykrycia b\u0142\u0105d.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"podstawowe-przyklady-dzialania\">Podstawowe przyk\u0142ady dzia\u0142ania<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>J\u0119zyk<\/th><th>Przyk\u0142ad<\/th><\/tr><\/thead><tbody><tr><td>Python<\/td><td><code>class User:\\n pass\\n\\nu = User()\\nsetattr(u, \"name\", \"Anna\")\\nprint(u.name)<\/code><\/td><\/tr><tr><td>C++<\/td><td><code>struct User {\\n std::string name;\\n};\\n\\nUser u;\\nu.name = \"Anna\";<\/code><\/td><\/tr><tr><td>C<\/td><td><code>struct User {\\n char name[50];\\n};\\n\\nstruct User u;\\nstrcpy(u.name, \"Anna\");<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>W C i C++ nie ma odpowiednika dzia\u0142aj\u0105cego identycznie, bo pola s\u0105 znane statycznie. Python pozwala na znacznie wi\u0119ksz\u0105 elastyczno\u015b\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"dlaczego-dynamiczne-ustawianie-atrybutow-jest-potrzebne-przy-pracy-z-formularzami-api-i-konfiguracja-systemu\">Dlaczego dynamiczne ustawianie atrybut\u00f3w jest potrzebne przy pracy z formularzami, API i konfiguracj\u0105 systemu<\/h2>\n\n\n\n<p>Najcz\u0119stszy przypadek u\u017cycia to dane wej\u015bciowe, kt\u00f3rych struktura jest zmienna. Przyk\u0142ad: formularz administracyjny zwraca s\u0142ownik:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{<br>    \"email\": \"test@example.com\",<br>    \"is_active\": True,<br>    \"age\": 31<br>}<\/pre>\n\n\n\n<p>Zamiast r\u0119cznie przypisywa\u0107 ka\u017cde pole osobno, mo\u017cna przej\u015b\u0107 po s\u0142owniku p\u0119tl\u0105.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Przyk\u0142ad Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Uzupe\u0142nianie obiektu danymi<\/td><td><code>class Profile:\\n pass\\n\\np = Profile()\\n\\ndata = {\\n \"email\": \"test@example.com\",\\n \"is_active\": True,\\n \"age\": 31\\n}\\n\\nfor key, value in data.items():\\n setattr(p, key, value)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To rozwi\u0105zanie jest kr\u00f3tsze, ale przede wszystkim skaluje si\u0119 dobrze. Przy 3 polach r\u00f3\u017cnica jest ma\u0142a. Przy 50 polach r\u0119czne przypisanie staje si\u0119 strat\u0105 czasu i \u017ar\u00f3d\u0142em pomy\u0142ek.<\/p>\n\n\n\n<p>Podobny mechanizm stosuj\u0105:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>frameworki webowe<\/li>\n\n\n\n<li>serializatory danych<\/li>\n\n\n\n<li>systemy konfiguracji<\/li>\n\n\n\n<li>bibliotki ORM<\/li>\n\n\n\n<li>generatory modeli danych<\/li>\n<\/ul>\n\n\n\n<p>W praktyce programista bardzo cz\u0119sto korzysta z tego po\u015brednio, nawet je\u015bli nie wywo\u0142uje <code>setattr()<\/code> samodzielnie.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-podczas-konfiguracji-klas-instancji-i-danych-wejsciowych\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie podczas konfiguracji klas, instancji i danych wej\u015bciowych<\/h2>\n\n\n\n<p><code>setattr()<\/code> dzia\u0142a nie tylko na instancjach, ale r\u00f3wnie\u017c na klasach.<\/p>\n\n\n\n<p>To oznacza, \u017ce mo\u017cna dynamicznie dodawa\u0107 pola wsp\u00f3lne dla wszystkich obiekt\u00f3w.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Przyk\u0142ad<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Atrybut klasy<\/td><td><code>class Config:\\n pass\\n\\nsetattr(Config, \"version\", \"1.0\")\\n\\nprint(Config.version)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Je\u017celi atrybut zostanie ustawiony na klasie, wszystkie instancje b\u0119d\u0105 mog\u0142y go odczyta\u0107, dop\u00f3ki nie nadpisz\u0105 go lokalnie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"roznica-miedzy-klasa-a-instancja\">R\u00f3\u017cnica mi\u0119dzy klas\u0105 a instancj\u0105<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Operacja<\/th><th>Efekt<\/th><\/tr><\/thead><tbody><tr><td><code>setattr(User, \"role\", \"admin\")<\/code><\/td><td>atrybut klasy<\/td><\/tr><tr><td><code>setattr(user, \"role\", \"admin\")<\/code><\/td><td>atrybut konkretnej instancji<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To rozr\u00f3\u017cnienie ma znaczenie przy debugowaniu. Cz\u0119sto problem wygl\u0105da jak \u201ePython nadpisa\u0142 dane\u201d, a w rzeczywisto\u015bci ustawiono warto\u015b\u0107 na klasie zamiast na obiekcie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wspolpraca-z-getattr-i-hasattr\">Wsp\u00f3\u0142praca z <code>getattr()<\/code> i <code>hasattr()<\/code><\/h3>\n\n\n\n<p>Dynamiczna praca z obiektem zwykle wygl\u0105da tak:<\/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>hasattr()<\/code><\/td><td>sprawdza istnienie pola<\/td><\/tr><tr><td><code>getattr()<\/code><\/td><td>pobiera warto\u015b\u0107<\/td><\/tr><tr><td><code>setattr()<\/code><\/td><td>ustawia warto\u015b\u0107<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Przyk\u0142ad bezpieczniejszego podej\u015bcia:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Kontrola przed zapisem<\/td><td><code>if hasattr(user, \"email\"):\\n setattr(user, \"email\", \"nowy@mail.com\")<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Dzi\u0119ki temu nie tworzymy przypadkiem nowego pola z liter\u00f3wk\u0105, np. <code>emial<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"kontrola-nad-przypisaniem-przez-metode-setattr-i-jej-realne-znaczenie-w-wiekszych-projektach\">Kontrola nad przypisaniem przez metod\u0119 <code>__setattr__()<\/code> i jej realne znaczenie w wi\u0119kszych projektach<\/h2>\n\n\n\n<p>Ka\u017cda klasa mo\u017ce zdefiniowa\u0107 metod\u0119 specjaln\u0105 <code>__setattr__()<\/code>, kt\u00f3ra przechwytuje ka\u017cd\u0105 pr\u00f3b\u0119 ustawienia atrybutu.<\/p>\n\n\n\n<p>To jest miejsce na:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>walidacj\u0119 danych<\/li>\n\n\n\n<li>logowanie zmian<\/li>\n\n\n\n<li>blokowanie nieautoryzowanych p\u00f3l<\/li>\n\n\n\n<li>automatyczne konwersje typ\u00f3w<\/li>\n<\/ul>\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><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Walidacja wieku<\/td><td><code>class Person:\\n def __setattr__(self, name, value):\\n if name == \"age\" and value &lt; 0:\\n raise ValueError(\"Wiek nie mo\u017ce by\u0107 ujemny\")\\n super().__setattr__(name, value)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Tutaj zwyk\u0142e <code>setattr()<\/code> r\u00f3wnie\u017c uruchomi t\u0119 logik\u0119.<\/p>\n\n\n\n<p>To bardzo wa\u017cne: <code>setattr()<\/code> nie omija zasad klasy. Ono korzysta z mechanizmu obiektowego, a nie \u201ew\u0142amuje si\u0119\u201d do \u015brodka obiektu.<\/p>\n\n\n\n<p>W wi\u0119kszych systemach to chroni przed sytuacj\u0105, w kt\u00f3rej dane z zewn\u0119trznego API nadpisuj\u0105 pola w niekontrolowany spos\u00f3b.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setattr-ustawia-wartosc-atrybutu-obiektu-dynamicznie-i-wymaga-kontroli-bezpieczenstwa-oraz-przewidywalnosci\">Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie i wymaga kontroli bezpiecze\u0144stwa oraz przewidywalno\u015bci<\/h2>\n\n\n\n<p>Najcz\u0119stszy b\u0142\u0105d to bezrefleksyjne przepisywanie wszystkiego ze s\u0142ownika wej\u015bciowego.<\/p>\n\n\n\n<p>Przyk\u0142ad ryzykowny:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Niebezpieczne mapowanie<\/td><td><code>for key, value in request_data.items():\\n setattr(user, key, value)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Je\u017celi u\u017cytkownik prze\u015ble pole:<\/p>\n\n\n\n<p><code>\"is_admin\": True<\/code><\/p>\n\n\n\n<p>to system mo\u017ce sam nada\u0107 uprawnienia administracyjne, je\u015bli programista nie wprowadzi ogranicze\u0144.<\/p>\n\n\n\n<p>Dlatego praktyczna zasada jest prosta:<\/p>\n\n\n\n<p>najpierw whitelist, potem <code>setattr()<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Bezpieczniejsze podej\u015bcie<\/td><td><code>allowed = [\"email\", \"phone\"]\\n\\nfor key, value in request_data.items():\\n if key in allowed:\\n setattr(user, key, value)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>To drobiazg, ale oszcz\u0119dza realne problemy: utrat\u0119 danych, b\u0142\u0119dne uprawnienia, kosztowne poprawki po wdro\u017ceniu.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"literowki-sa-grozniejsze-niz-wygladaja\">Liter\u00f3wki s\u0105 gro\u017aniejsze ni\u017c wygl\u0105daj\u0105<\/h3>\n\n\n\n<p>Python pozwala stworzy\u0107 nowe pole automatycznie.<\/p>\n\n\n\n<p>To oznacza, \u017ce:<\/p>\n\n\n\n<p><code>setattr(user, \"emial\", \"x\")<\/code><\/p>\n\n\n\n<p>nie zg\u0142osi b\u0142\u0119du &#8211; po prostu utworzy nowe pole.<\/p>\n\n\n\n<p>Efekt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>system dzia\u0142a \u201eprawie dobrze\u201d<\/li>\n\n\n\n<li>testy czasem przechodz\u0105<\/li>\n\n\n\n<li>bug wychodzi po tygodniach<\/li>\n<\/ul>\n\n\n\n<p>To jeden z najbardziej irytuj\u0105cych b\u0142\u0119d\u00f3w przy dynamicznej pracy z obiektami.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"wzory-myslenia-o-tym-mechanizmie-i-porownanie-z-podejsciem-statycznym\">Wzory my\u015blenia o tym mechanizmie i por\u00f3wnanie z podej\u015bciem statycznym<\/h2>\n\n\n\n<p>W j\u0119zykach statycznych, takich jak C lub klasyczne C++, struktura danych jest znana wcze\u015bniej. Programista deklaruje pola i kompilator pilnuje zgodno\u015bci.<\/p>\n\n\n\n<p>Python dzia\u0142a inaczej.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Podej\u015bcie<\/th><th>Charakterystyka<\/th><\/tr><\/thead><tbody><tr><td>statyczne<\/td><td>wi\u0119ksza kontrola kompilatora<\/td><\/tr><tr><td>dynamiczne<\/td><td>wi\u0119ksza elastyczno\u015b\u0107 wykonania<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Nie oznacza to, \u017ce jedno jest lepsze zawsze. Dynamiczne przypisywanie jest \u015bwietne przy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>parserach danych<\/li>\n\n\n\n<li>narz\u0119dziach administracyjnych<\/li>\n\n\n\n<li>systemach plugin\u00f3w<\/li>\n\n\n\n<li>modelach konfiguracyjnych<\/li>\n<\/ul>\n\n\n\n<p>Ale przy logice krytycznej biznesowo cz\u0119sto lepiej zachowa\u0107 jawno\u015b\u0107 kodu i nie przesadza\u0107 z automatyzacj\u0105.<\/p>\n\n\n\n<p>Program, kt\u00f3rego nie da si\u0119 \u0142atwo przeczyta\u0107, zwykle staje si\u0119 dro\u017cszy w utrzymaniu ni\u017c program troch\u0119 d\u0142u\u017cszy, ale przewidywalny.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"krotkie-uwagi-praktyczne-ktore-oszczedzaja-najwiecej-czasu-podczas-pracy\">Kr\u00f3tkie uwagi praktyczne, kt\u00f3re oszcz\u0119dzaj\u0105 najwi\u0119cej czasu podczas pracy<\/h2>\n\n\n\n<p>Nie warto u\u017cywa\u0107 <code>setattr()<\/code> tylko dlatego, \u017ce \u201eda si\u0119 kr\u00f3cej\u201d.<\/p>\n\n\n\n<p>Je\u017celi kod wygl\u0105da tak:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Niepotrzebna dynamika<\/td><td><code>setattr(user, \"name\", \"Jan\")<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>to zwyk\u0142e:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Python<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Czytelniejsza forma<\/td><td><code>user.name = \"Jan\"<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>jest po prostu lepsze.<\/p>\n\n\n\n<p><code>setattr()<\/code> ma sens wtedy, gdy nazwa pola jest zmienna.<\/p>\n\n\n\n<p>Dobrze te\u017c pami\u0119ta\u0107 o:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>walidacji danych wej\u015bciowych<\/li>\n\n\n\n<li>ograniczeniu do dozwolnych p\u00f3l<\/li>\n\n\n\n<li>testach na liter\u00f3wki<\/li>\n\n\n\n<li>rozr\u00f3\u017cnieniu klasy i instancji<\/li>\n\n\n\n<li>ostro\u017cno\u015bci przy <code>__setattr__()<\/code>, bo \u0142atwo stworzy\u0107 rekurencj\u0119<\/li>\n<\/ul>\n\n\n\n<p>Szczeg\u00f3lnie ostatni punkt bywa bolesny. Je\u015bli w <code>__setattr__()<\/code> u\u017cyje si\u0119 <code>self.name = value<\/code>, metoda wywo\u0142a sam\u0105 siebie bez ko\u0144ca. Poprawnie u\u017cywa si\u0119 <code>super().__setattr__()<\/code>.<\/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-setattr-tworzy-nowy-atrybut-jesli-wczesniej-go-nie-bylo\">Czy <code>setattr()<\/code> tworzy nowy atrybut, je\u015bli wcze\u015bniej go nie by\u0142o?<\/h3>\n\n\n\n<p>Tak, w wi\u0119kszo\u015bci zwyk\u0142ych klas Python utworzy nowe pole automatycznie. Wyj\u0105tkiem s\u0105 klasy z ograniczeniami, np. <code>__slots__<\/code> albo w\u0142asn\u0105 kontrol\u0105 w <code>__setattr__()<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-setattr-jest-szybsze-od-zwyklego-przypisania\">Czy <code>setattr()<\/code> jest szybsze od zwyk\u0142ego przypisania?<\/h3>\n\n\n\n<p>Nie. Zwyk\u0142e <code>obiekt.pole = wartosc<\/code> jest prostsze i czytelniejsze. <code>setattr()<\/code> wybiera si\u0119 dla elastyczno\u015bci, nie dla wydajno\u015bci.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-mozna-uzywac-setattr-na-klasie-zamiast-instancji\">Czy mo\u017cna u\u017cywa\u0107 <code>setattr()<\/code> na klasie zamiast instancji?<\/h3>\n\n\n\n<p>Tak. Wtedy ustawiany jest atrybut klasy, wsp\u00f3lny dla wszystkich instancji, o ile nie zostanie lokalnie nadpisany.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-setattr-omija-walidacje-zdefiniowana-w-klasie\">Czy <code>setattr()<\/code> omija walidacj\u0119 zdefiniowan\u0105 w klasie?<\/h3>\n\n\n\n<p>Nie. Je\u015bli klasa posiada <code>__setattr__()<\/code>, to ta metoda zostanie wykonana r\u00f3wnie\u017c przy u\u017cyciu <code>setattr()<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-warto-uzywac-tego-mechanizmu-w-kodzie-produkcyjnym\">Czy warto u\u017cywa\u0107 tego mechanizmu w kodzie produkcyjnym?<\/h3>\n\n\n\n<p>Tak, ale tylko tam, gdzie rzeczywi\u015bcie potrzebna jest dynamika. Przy prostych modelach jawne przypisanie jest zwykle bezpieczniejsze i \u0142atwiejsze do utrzymania.<\/p>\n\n\n\n<p><em>\u0179r\u00f3d\u0142o Foto: Freepik<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>W programowaniu obiektowym cz\u0119sto pojawia si\u0119 potrzeba modyfikowania obiektu bez r\u0119cznego odwo\u0142ywania si\u0119 do ka\u017cdego pola osobno. Dotyczy to konfiguracji klas, mapowania danych z formularzy, importu plik\u00f3w JSON, budowania prostych ORM czy automatycznego uzupe\u0142niania modeli danych. Python pozwala robi\u0107 to bardzo elastycznie, poniewa\u017c obiekty mo\u017cna modyfikowa\u0107 tak\u017ce w czasie dzia\u0142ania programu, a nie tylko na etapie definicji klasy. W praktyce w\u0142a\u015bnie temu s\u0142u\u017cy Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie. Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie w praktyce dzia\u0142ania modelu obiektowego Pythona Funkcja setattr() jest wbudowan\u0105 funkcj\u0105 Pythona s\u0142u\u017c\u0105c\u0105 do ustawiania warto\u015bci atrybutu obiektu na podstawie nazwy przekazanej jako tekst. Zamiast pisa\u0107: obiekt.imie = &#8222;Jan&#8221; mo\u017cna wykona\u0107: setattr(obiekt, &#8222;imie&#8221;, &#8222;Jan&#8221;) Efekt ko\u0144cowy jest identyczny, ale druga forma pozwala budowa\u0107 kod dynamiczny, czyli taki, w kt\u00f3rym nazwa pola nie jest znana wcze\u015bniej i pochodzi na przyk\u0142ad z pliku konfiguracyjnego, API albo danych u\u017cytkownika. Sk\u0142adnia jest bardzo prosta: Element Opis setattr(obiekt, nazwa, wartosc) ustawia atrybut obiekt instancja klasy lub klasa nazwa nazwa atrybutu jako str wartosc warto\u015b\u0107 przypisywana do pola Najwa\u017cniejsze jest to, \u017ce nazwa musi by\u0107 tekstem. Python nie oczekuje tutaj referencji do pola, tylko jego nazwy. Co dzieje si\u0119 wewn\u0119trznie Wi\u0119kszo\u015b\u0107 zwyk\u0142ych obiekt\u00f3w Pythona przechowuje dane w s\u0142owniku __dict__. Gdy wykonujemy setattr(), interpreter aktualizuje w\u0142a\u015bnie ten mechanizm albo uruchamia w\u0142asn\u0105 logik\u0119 klasy, je\u015bli zdefiniowano __setattr__(). To wa\u017cne, bo oznacza, \u017ce: To daje du\u017c\u0105 wygod\u0119, ale te\u017c \u0142atwo wprowadzi\u0107 trudny do wykrycia b\u0142\u0105d. Podstawowe przyk\u0142ady dzia\u0142ania J\u0119zyk Przyk\u0142ad Python class User:\\n pass\\n\\nu = User()\\nsetattr(u, &#8222;name&#8221;, &#8222;Anna&#8221;)\\nprint(u.name) C++ struct User {\\n std::string name;\\n};\\n\\nUser u;\\nu.name = &#8222;Anna&#8221;; C struct User {\\n char name[50];\\n};\\n\\nstruct User u;\\nstrcpy(u.name, &#8222;Anna&#8221;); W C i C++ nie ma odpowiednika dzia\u0142aj\u0105cego identycznie, bo pola s\u0105 znane statycznie. Python pozwala na znacznie wi\u0119ksz\u0105 elastyczno\u015b\u0107. Dlaczego dynamiczne ustawianie atrybut\u00f3w jest potrzebne przy pracy z formularzami, API i konfiguracj\u0105 systemu Najcz\u0119stszy przypadek u\u017cycia to dane wej\u015bciowe, kt\u00f3rych struktura jest zmienna. Przyk\u0142ad: formularz administracyjny zwraca s\u0142ownik: { &#8222;email&#8221;: &#8222;test@example.com&#8221;, &#8222;is_active&#8221;: True, &#8222;age&#8221;: 31} Zamiast r\u0119cznie przypisywa\u0107 ka\u017cde pole osobno, mo\u017cna przej\u015b\u0107 po s\u0142owniku p\u0119tl\u0105. Przyk\u0142ad Python Kod Uzupe\u0142nianie obiektu danymi class Profile:\\n pass\\n\\np = Profile()\\n\\ndata = {\\n &#8222;email&#8221;: &#8222;test@example.com&#8221;,\\n &#8222;is_active&#8221;: True,\\n &#8222;age&#8221;: 31\\n}\\n\\nfor key, value in data.items():\\n setattr(p, key, value) To rozwi\u0105zanie jest kr\u00f3tsze, ale przede wszystkim skaluje si\u0119 dobrze. Przy 3 polach r\u00f3\u017cnica jest ma\u0142a. Przy 50 polach r\u0119czne przypisanie staje si\u0119 strat\u0105 czasu i \u017ar\u00f3d\u0142em pomy\u0142ek. Podobny mechanizm stosuj\u0105: W praktyce programista bardzo cz\u0119sto korzysta z tego po\u015brednio, nawet je\u015bli nie wywo\u0142uje setattr() samodzielnie. Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie podczas konfiguracji klas, instancji i danych wej\u015bciowych setattr() dzia\u0142a nie tylko na instancjach, ale r\u00f3wnie\u017c na klasach. To oznacza, \u017ce mo\u017cna dynamicznie dodawa\u0107 pola wsp\u00f3lne dla wszystkich obiekt\u00f3w. Przyk\u0142ad Kod Atrybut klasy class Config:\\n pass\\n\\nsetattr(Config, &#8222;version&#8221;, &#8222;1.0&#8221;)\\n\\nprint(Config.version) Je\u017celi atrybut zostanie ustawiony na klasie, wszystkie instancje b\u0119d\u0105 mog\u0142y go odczyta\u0107, dop\u00f3ki nie nadpisz\u0105 go lokalnie. R\u00f3\u017cnica mi\u0119dzy klas\u0105 a instancj\u0105 Operacja Efekt setattr(User, &#8222;role&#8221;, &#8222;admin&#8221;) atrybut klasy setattr(user, &#8222;role&#8221;, &#8222;admin&#8221;) atrybut konkretnej instancji To rozr\u00f3\u017cnienie ma znaczenie przy debugowaniu. Cz\u0119sto problem wygl\u0105da jak \u201ePython nadpisa\u0142 dane\u201d, a w rzeczywisto\u015bci ustawiono warto\u015b\u0107 na klasie zamiast na obiekcie. Wsp\u00f3\u0142praca z getattr() i hasattr() Dynamiczna praca z obiektem zwykle wygl\u0105da tak: Funkcja Zastosowanie hasattr() sprawdza istnienie pola getattr() pobiera warto\u015b\u0107 setattr() ustawia warto\u015b\u0107 Przyk\u0142ad bezpieczniejszego podej\u015bcia: Python Kod Kontrola przed zapisem if hasattr(user, &#8222;email&#8221;):\\n setattr(user, &#8222;email&#8221;, &#8222;nowy@mail.com&#8221;) Dzi\u0119ki temu nie tworzymy przypadkiem nowego pola z liter\u00f3wk\u0105, np. emial. Kontrola nad przypisaniem przez metod\u0119 __setattr__() i jej realne znaczenie w wi\u0119kszych projektach Ka\u017cda klasa mo\u017ce zdefiniowa\u0107 metod\u0119 specjaln\u0105 __setattr__(), kt\u00f3ra przechwytuje ka\u017cd\u0105 pr\u00f3b\u0119 ustawienia atrybutu. To jest miejsce na: Przyk\u0142ad: Python Kod Walidacja wieku class Person:\\n def __setattr__(self, name, value):\\n if name == &#8222;age&#8221; and value &lt; 0:\\n raise ValueError(&#8222;Wiek nie mo\u017ce by\u0107 ujemny&#8221;)\\n super().__setattr__(name, value) Tutaj zwyk\u0142e setattr() r\u00f3wnie\u017c uruchomi t\u0119 logik\u0119. To bardzo wa\u017cne: setattr() nie omija zasad klasy. Ono korzysta z mechanizmu obiektowego, a nie \u201ew\u0142amuje si\u0119\u201d do \u015brodka obiektu. W wi\u0119kszych systemach to chroni przed sytuacj\u0105, w kt\u00f3rej dane z zewn\u0119trznego API nadpisuj\u0105 pola w niekontrolowany spos\u00f3b. Setattr \u2013 ustawia warto\u015b\u0107 atrybutu obiektu dynamicznie i wymaga kontroli bezpiecze\u0144stwa oraz przewidywalno\u015bci Najcz\u0119stszy b\u0142\u0105d to bezrefleksyjne przepisywanie wszystkiego ze s\u0142ownika wej\u015bciowego. Przyk\u0142ad ryzykowny: Python Kod Niebezpieczne mapowanie for key, value in request_data.items():\\n setattr(user, key, value) Je\u017celi u\u017cytkownik prze\u015ble pole: &#8222;is_admin&#8221;: True to system mo\u017ce sam nada\u0107 uprawnienia administracyjne, je\u015bli programista nie wprowadzi ogranicze\u0144. Dlatego praktyczna zasada jest prosta: najpierw whitelist, potem setattr(). Python Kod Bezpieczniejsze podej\u015bcie allowed = [&#8222;email&#8221;, &#8222;phone&#8221;]\\n\\nfor key, value in request_data.items():\\n if key in allowed:\\n setattr(user, key, value) To drobiazg, ale oszcz\u0119dza realne problemy: utrat\u0119 danych, b\u0142\u0119dne uprawnienia, kosztowne poprawki po wdro\u017ceniu. Liter\u00f3wki s\u0105 gro\u017aniejsze ni\u017c wygl\u0105daj\u0105 Python pozwala stworzy\u0107 nowe pole automatycznie. To oznacza, \u017ce: setattr(user, &#8222;emial&#8221;, &#8222;x&#8221;) nie zg\u0142osi b\u0142\u0119du &#8211; po prostu utworzy nowe pole. Efekt: To jeden z najbardziej irytuj\u0105cych b\u0142\u0119d\u00f3w przy dynamicznej pracy z obiektami. Wzory my\u015blenia o tym mechanizmie i por\u00f3wnanie z podej\u015bciem statycznym W j\u0119zykach statycznych, takich jak C lub klasyczne C++, struktura danych jest znana wcze\u015bniej. Programista deklaruje pola i kompilator pilnuje zgodno\u015bci. Python dzia\u0142a inaczej. Podej\u015bcie Charakterystyka statyczne wi\u0119ksza kontrola kompilatora dynamiczne wi\u0119ksza elastyczno\u015b\u0107 wykonania Nie oznacza to, \u017ce jedno jest lepsze zawsze. Dynamiczne przypisywanie jest \u015bwietne przy: Ale przy logice krytycznej biznesowo cz\u0119sto lepiej zachowa\u0107 jawno\u015b\u0107 kodu i nie przesadza\u0107 z automatyzacj\u0105. Program, kt\u00f3rego nie da si\u0119 \u0142atwo przeczyta\u0107, zwykle staje si\u0119 dro\u017cszy w utrzymaniu ni\u017c program troch\u0119 d\u0142u\u017cszy, ale przewidywalny. Kr\u00f3tkie uwagi praktyczne, kt\u00f3re oszcz\u0119dzaj\u0105 najwi\u0119cej czasu podczas pracy Nie warto u\u017cywa\u0107 setattr() tylko dlatego, \u017ce \u201eda si\u0119 kr\u00f3cej\u201d. Je\u017celi kod wygl\u0105da tak: Python Kod Niepotrzebna dynamika setattr(user, &#8222;name&#8221;, &#8222;Jan&#8221;) to zwyk\u0142e: Python Kod Czytelniejsza forma user.name = &#8222;Jan&#8221; jest po prostu lepsze. setattr() ma sens wtedy, gdy nazwa pola jest zmienna. Dobrze te\u017c pami\u0119ta\u0107 o: Szczeg\u00f3lnie ostatni punkt bywa bolesny. Je\u015bli w __setattr__() u\u017cyje si\u0119 self.name = value, metoda wywo\u0142a sam\u0105 siebie bez ko\u0144ca. Poprawnie u\u017cywa si\u0119 super().__setattr__(). FAQ Czy setattr() tworzy nowy atrybut, je\u015bli wcze\u015bniej go nie by\u0142o? Tak, w wi\u0119kszo\u015bci zwyk\u0142ych klas Python utworzy nowe pole automatycznie. Wyj\u0105tkiem s\u0105 klasy z ograniczeniami, np. __slots__ albo w\u0142asn\u0105 kontrol\u0105 w __setattr__(). Czy setattr() jest szybsze od zwyk\u0142ego przypisania? Nie. Zwyk\u0142e obiekt.pole = wartosc jest prostsze i czytelniejsze. setattr() wybiera si\u0119 dla elastyczno\u015bci, nie dla wydajno\u015bci. Czy mo\u017cna u\u017cywa\u0107 setattr() na klasie zamiast instancji? Tak. Wtedy ustawiany jest atrybut klasy, wsp\u00f3lny dla wszystkich instancji, o ile nie zostanie lokalnie nadpisany. Czy setattr() omija walidacj\u0119 zdefiniowan\u0105 w klasie? Nie. Je\u015bli klasa posiada __setattr__(), to ta metoda zostanie wykonana r\u00f3wnie\u017c przy u\u017cyciu setattr(). Czy warto u\u017cywa\u0107 tego mechanizmu w kodzie produkcyjnym? Tak, ale tylko tam, gdzie rzeczywi\u015bcie potrzebna jest dynamika. Przy prostych modelach jawne przypisanie jest zwykle bezpieczniejsze i \u0142atwiejsze do utrzymania. \u0179r\u00f3d\u0142o Foto: Freepik<\/p>\n","protected":false},"author":1,"featured_media":1538,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[],"class_list":["post-1537","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\/1537","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=1537"}],"version-history":[{"count":1,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1537\/revisions"}],"predecessor-version":[{"id":1539,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1537\/revisions\/1539"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media\/1538"}],"wp:attachment":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}