{"id":3049,"date":"2025-09-21T05:57:15","date_gmt":"2025-09-21T03:57:15","guid":{"rendered":"https:\/\/davidka.net\/en\/?p=3049"},"modified":"2025-09-22T04:21:12","modified_gmt":"2025-09-22T02:21:12","slug":"python-classes-context-managers","status":"publish","type":"post","link":"https:\/\/it.davidka.net\/it\/python-classes-oop-context-managers\/","title":{"rendered":"Classi in Python, OOP e context manager: guida completa"},"content":{"rendered":"\n<p class=\"has-neve-link-color-color has-text-color has-link-color has-medium-font-size wp-elements-06111590ac3e6b2218bc246647b4630b wp-block-paragraph\">Questa guida copre la <strong>programmazione orientata agli oggetti (OOP)<\/strong> in Python e i <strong>context manager<\/strong>, con esempi pratici per <strong>catturare stdout\/stderr<\/strong> e usare il pattern <strong>Tee<\/strong> per visualizzare e salvare l\u2019output contemporaneamente.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div id=\"rtoc-mokuji-wrapper\" class=\"rtoc-mokuji-content frame2 preset1 animation-fade rtoc_open default\" data-id=\"3049\" data-theme=\"Neve - Davidka\">\n\t\t\t<div id=\"rtoc-mokuji-title\" class=\"rtoc_btn_none rtoc_left\">\n\t\t\t\n\t\t\t<span>In Questo Articolo<\/span>\n\t\t\t<\/div><ol class=\"rtoc-mokuji decimal_ol level-1\"><li class=\"rtoc-item\"><a href=\"#rtoc-1\">1. Classi in Python<\/a><ul class=\"rtoc-mokuji mokuji_ul level-2\"><li class=\"rtoc-item\"><a href=\"#rtoc-2\">Struttura di una classe<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-3\">Creazione di oggetti<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-4\">Tipi di metodi<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-5\">Ereditariet\u00e0<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-6\">Polimorfismo<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-7\">Incapsulamento<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-8\">Metodi speciali e distruttore<\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-9\">Diagramma ASCII: ereditariet\u00e0 e polimorfismo<\/a><\/li><\/ul><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-10\">2. Context manager in Python<\/a><ul class=\"rtoc-mokuji mokuji_ul level-2\"><li class=\"rtoc-item\"><a href=\"#rtoc-11\">Uso di <code class=\"\" data-line=\"\">@contextmanager<\/code><\/a><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-12\">Cattura stdout\/stderr e pattern Tee<\/a><\/li><\/ul><\/li><li class=\"rtoc-item\"><a href=\"#rtoc-13\">3. Esempio completo: <code class=\"\" data-line=\"\">oop_and_context.py<\/code><\/a><\/li><\/ol><\/div><h2 id=\"rtoc-1\"  class=\"wp-block-heading\">1. Classi in Python<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Le classi sono il cuore della <strong>OOP<\/strong>. Una classe \u00e8 un <strong>modello<\/strong> per creare oggetti con <strong>attributi<\/strong> (dati) e <strong>metodi<\/strong> (funzioni). Gli oggetti creati da una classe sono chiamati <strong>istanze<\/strong>. Le classi aiutano a strutturare il codice, aumentano il riuso e semplificano la manutenzione.<\/p>\n\n\n\n<h3 id=\"rtoc-2\"  class=\"wp-block-heading\">Struttura di una classe<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class ClassName:\n    def __init__(self, param1, param2):\n        self.param1 = param1\n        self.param2 = param2\n\n    def method(self):\n        return f&#039;{self.param1} e {self.param2}&#039;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Punti chiave:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code class=\"\" data-line=\"\">__init__<\/code>: costruttore per inizializzare gli attributi dell\u2019oggetto.<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">self<\/code>: riferimento all\u2019istanza corrente.<\/li>\n\n\n\n<li>Attributi: definiti tramite <code class=\"\" data-line=\"\">self<\/code> e accessibili in tutti i metodi.<\/li>\n\n\n\n<li>Metodi: operano sui dati dell\u2019oggetto.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-3\"  class=\"wp-block-heading\">Creazione di oggetti<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class Car:\n    def __init__(self, make, model, year):\n        self.make = make\n        self.model = model\n        self.year = year\n\n    def description(self):\n        return f&#039;{self.year} {self.make} {self.model}&#039;\n\nmy_car = Car(&#039;Toyota&#039;, &#039;Corolla&#039;, 2020)\nprint(my_car.description())  # Output: 2020 Toyota Corolla\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-4\"  class=\"wp-block-heading\">Tipi di metodi<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Metodi di istanza<\/strong> \u2014 operano sull\u2019oggetto (<code class=\"\" data-line=\"\">self<\/code>).<\/li>\n\n\n\n<li><strong>Metodi di classe<\/strong> \u2014 operano sulla classe (<code class=\"\" data-line=\"\">cls<\/code>) usando <code class=\"\" data-line=\"\">@classmethod<\/code>.<\/li>\n\n\n\n<li><strong>Metodi statici<\/strong> \u2014 non dipendono n\u00e9 dall\u2019istanza n\u00e9 dalla classe (<code class=\"\" data-line=\"\">@staticmethod<\/code>).<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-5\"  class=\"wp-block-heading\">Ereditariet\u00e0<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class Animal:\n    def speak(self):\n        return &#039;Voce animale&#039;\n\nclass Dog(Animal):\n    def speak(self):\n        return &#039;Bau&#039;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-6\"  class=\"wp-block-heading\">Polimorfismo<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class Cat(Animal):\n    def speak(self):\n        return &#039;Miao&#039;\n\ncat = Cat()\nprint(cat.speak())  # Output: Miao\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Lo stesso metodo pu\u00f2 avere comportamenti diversi a seconda del tipo di oggetto.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-7\"  class=\"wp-block-heading\">Incapsulamento<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class Car:\n    def __init__(self, make, model):\n        self._make = make  # attributo protetto\n        self._model = model\n\n    def get_make(self):\n        return self._make\n\n    def set_make(self, make):\n        self._make = make\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-8\"  class=\"wp-block-heading\">Metodi speciali e distruttore<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">class Point:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    def __repr__(self):\n        return f&#039;Point({self.x}, {self.y})&#039;\n\np = Point(3, 4)\nprint(p)  # Output: Point(3, 4)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-9\"  class=\"wp-block-heading\">Diagramma ASCII: ereditariet\u00e0 e polimorfismo<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n       \u2502 Animal  \u2502\n       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n       \u2502 speak() \u2502\n       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n            \u25b2\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n    \u2502                \u2502\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510      \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Dog    \u2502      \u2502  Cat    \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518      \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\u2502 speak() \u2502      \u2502 speak() \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518      \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 id=\"rtoc-10\"  class=\"wp-block-heading\">2. Context manager in Python<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I context manager permettono di <strong>allocare e rilasciare automaticamente risorse<\/strong>, anche in caso di errori.<\/p>\n\n\n\n<h3 id=\"rtoc-11\"  class=\"wp-block-heading\">Uso di <code class=\"\" data-line=\"\">@contextmanager<\/code><\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">from contextlib import contextmanager\n\n@contextmanager\ndef my_context():\n    print(&quot;Entrata nel contesto&quot;)\n    try:\n        yield &quot;Risorsa&quot;\n    finally:\n        print(&quot;Uscita dal contesto&quot;)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Esempio:<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">with my_context() as res:\n    print(&quot;Nel contesto:&quot;, res)\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 id=\"rtoc-12\"  class=\"wp-block-heading\">Cattura stdout\/stderr e pattern Tee<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Python permette di catturare stdout, stderr o entrambi, e <strong>visualizzare e catturare contemporaneamente<\/strong> con il pattern Tee.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 id=\"rtoc-13\"  class=\"wp-block-heading\">3. Esempio completo: <code class=\"\" data-line=\"\">oop_and_context.py<\/code><\/h2>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\">&quot;&quot;&quot;\noop_and_context.py\n\nEsempi di classi, principi OOP e context manager in Python.\nInclude:\n- Definizioni di classi, ereditariet\u00e0, polimorfismo, incapsulamento\n- Metodi di istanza, classe e statici\n- Metodi speciali e distruttore\n- Context manager con @contextmanager\n- Cattura stdout, stderr e entrambi\n- Pattern Tee: visualizzazione e cattura\n- Context manager basato su classe\n&quot;&quot;&quot;\n\nimport sys\nimport io\nfrom contextlib import contextmanager\n\n# ==========================\n# Parte 1: Classi e OOP\n# ==========================\n\nclass Animal:\n    &quot;&quot;&quot;Classe base per animali.&quot;&quot;&quot;\n    def speak(self):\n        return &#039;Voce animale&#039;\n\nclass Dog(Animal):\n    def speak(self):\n        return &#039;Bau&#039;\n\nclass Cat(Animal):\n    def speak(self):\n        return &#039;Miao&#039;\n\nclass Car:\n    &quot;&quot;&quot;Esempio di incapsulamento.&quot;&quot;&quot;\n    def __init__(self, make, model, year=None):\n        self._make = make\n        self._model = model\n        self.year = year\n\n    def get_make(self):\n        return self._make\n\n    def set_make(self, make):\n        self._make = make\n\n    def description(self):\n        if self.year:\n            return f&#039;{self.year} {self._make} {self._model}&#039;\n        return f&#039;{self._make} {self._model}&#039;\n\nclass Point:\n    &quot;&quot;&quot;Classe con metodi speciali.&quot;&quot;&quot;\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    def __repr__(self):\n        return f&#039;Point({self.x}, {self.y})&#039;\n\n# ==========================\n# Parte 2: Context manager\n# ==========================\n\n@contextmanager\ndef my_context():\n    print(&quot;Entrata nel contesto&quot;)\n    try:\n        yield &quot;Risorsa&quot;\n    finally:\n        print(&quot;Uscita dal contesto&quot;)\n\n@contextmanager\ndef capture_stdout():\n    old_stdout = sys.stdout\n    sys.stdout = buffer = io.StringIO()\n    try:\n        yield buffer\n    finally:\n        sys.stdout = old_stdout\n\n@contextmanager\ndef capture_stderr():\n    old_stderr = sys.stderr\n    sys.stderr = buffer = io.StringIO()\n    try:\n        yield buffer\n    finally:\n        sys.stderr = old_stderr\n\n@contextmanager\ndef capture_output():\n    old_stdout = sys.stdout\n    old_stderr = sys.stderr\n    sys.stdout = sys.stderr = buffer = io.StringIO()\n    try:\n        yield buffer\n    finally:\n        sys.stdout = old_stdout\n        sys.stderr = old_stderr\n\nclass Tee(io.StringIO):\n    &quot;&quot;&quot;Visualizzazione e cattura contemporanea.&quot;&quot;&quot;\n    def __init__(self, original):\n        super().__init__()\n        self.original = original\n\n    def write(self, text):\n        self.original.write(text)\n        super().write(text)\n\n    def flush(self):\n        self.original.flush()\n\n@contextmanager\ndef capture_stdout_tee():\n    old_stdout = sys.stdout\n    sys.stdout = tee = Tee(old_stdout)\n    try:\n        yield tee\n    finally:\n        sys.stdout = old_stdout\n\n# ==========================\n# Parte 3: Context manager basato su classe\n# ==========================\n\nclass OutputCapture:\n    &quot;&quot;&quot;Context manager per catturare stdout.&quot;&quot;&quot;\n    def __init__(self):\n        self._buffer = io.StringIO()\n        self._old_stdout = None\n\n    def __enter__(self):\n        self._old_stdout = sys.stdout\n        sys.stdout = self._buffer\n        return self._buffer\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        sys.stdout = self._old_stdout\n        return False  # propagare l&#039;eccezione\n\n# ==========================\n# Parte 4: Dimostrazioni\n# ==========================\n\ndef demo_classes():\n    print(&quot;\\n--- Dimostrazione classi ---&quot;)\n    dog = Dog()\n    cat = Cat()\n    print(&quot;Il cane dice:&quot;, dog.speak())\n    print(&quot;Il gatto dice:&quot;, cat.speak())\n\n    my_car = Car(&#039;Toyota&#039;, &#039;Corolla&#039;, 2020)\n    print(&quot;Descrizione auto:&quot;, my_car.description())\n    my_car.set_make(&#039;Honda&#039;)\n    print(&quot;Marca aggiornata:&quot;, my_car.get_make())\n\n    point = Point(3, 4)\n    print(&quot;Punto:&quot;, point)\n\ndef demo_context_managers():\n    print(&quot;\\n--- Dimostrazione context manager ---&quot;)\n\n    with my_context() as res:\n        print(&quot;Nel contesto:&quot;, res)\n\n    with capture_stdout() as out:\n        print(&quot;stdout catturato&quot;)\n    print(&quot;Buffer:&quot;, out.getvalue().strip())\n\n    with capture_stderr() as err:\n        print(&quot;Va a stdout&quot;)\n        sys.stderr.write(&quot;Messaggio di errore\\n&quot;)\n    print(&quot;Errore:&quot;, err.getvalue().strip())\n\n    with capture_output() as out_all:\n        print(&quot;stdout in cattura combinata&quot;)\n        sys.stderr.write(&quot;stderr in cattura combinata\\n&quot;)\n    print(&quot;Output combinato:&quot;, out_all.getvalue().strip())\n\n    with capture_stdout_tee() as tee_out:\n        print(&quot;Output visibile e catturato (Tee)&quot;)\n    print(&quot;Buffer Tee:&quot;, tee_out.getvalue().strip())\n\n    with OutputCapture() as class_capture:\n        print(&quot;Cattura tramite context manager di classe&quot;)\n    print(&quot;Buffer context manager di classe:&quot;, class_capture.getvalue().strip())\n\n# ==========================\n# Esecuzione principale\n# ==========================\n\nif __name__ == &quot;__main__&quot;:\n    demo_classes()\n    demo_context_managers()\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Questa guida copre la programmazione orientata agli oggetti (OOP) in Python e i context manager, con esempi pratici per catturare stdout\/stderr e usare il pattern Tee per visualizzare e salvare l\u2019output contemporaneamente.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[610,1],"tags":[],"class_list":["post-3049","post","type-post","status-publish","format-standard","hentry","category-python-basics","category-uncategorized"],"acf":[],"_links":{"self":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts\/3049","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/comments?post=3049"}],"version-history":[{"count":0,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/posts\/3049\/revisions"}],"wp:attachment":[{"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/media?parent=3049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/categories?post=3049"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/it.davidka.net\/it\/wp-json\/wp\/v2\/tags?post=3049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}