12 Tajni Trikova u Pythonu Koji će Vas Pretvoriti u Pro Programera

12 Tajni Trikova u Pythonu Koji će Vas Pretvoriti u Pro Programera

Table of Contents

  1. Ključne Tačke
  2. Uvod
  3. 1. Monkeys-Patching Builtins
  4. 2. Funkcijska Overloading bez @overload
  5. 3. Dinamičko Umetanje Koda s exec i AST
  6. 4. weakref - Reference bez Vlasništva
  7. 5. Protokol Deskriptora
  8. 6. Thread-Safe Brojači uz collections.Counter
  9. 7. Import Hooks
  10. 8. Kreiranje Neizmjenjivih Rečnika sa MappingProxyType
  11. 9. Time Travel Debagovanje
  12. 10. Deljena Memorija između Procesa
  13. 11. Prilagođene getattr na Modulima
  14. 12. Speeds Hacks sa slots
  15. Često Postavljana Pitanja (FAQ)

Ključne Tačke

  • Upoznajte se s 12 naprednih tehnika u Pythonu koje mogu unaprijediti kvalitetu i efikasnost vašeg koda.
  • Ove tehnike uključuju razne metode manipulisanja, optimizacije i debagovanja koje koriste čak i iskusni programeri.
  • Ovaj vodič pruža praktične primjere kodova kako bi vam pomogao da brzo implementirate naučeno.

Uvod

Python je jedan od najpopularnijih programskih jezika na svetu, koristeći se u različitim domenima kao što su web razvoj, analitika podataka, veštačka inteligencija i još mnogo toga. Bez obzira na to koliko dugo pišete kod u Pythonu, uvek postoje nove i zanimljive tehnike koje možete naučiti. Čak i iskusni programeri često su iznenađeni moćnim funkcijama koje je Python u stanju da ponudi. U ovom članku bićemo fokusirani na 12 naprednih trikova koji će vam pomoći da kod izgledate profesionalno i optimizovano, čak i ako ste novi u ovom jeziku.

1. Monkeys-Patching Builtins

Jedna od najuzbudljivijih, ali možda i najopasnijih tehnika u Pythonu je monkey-patching. Ova metoda vam omogućava da prepravite ugrađene funkcije tokom izvršavanja programa. Na primer, ako želite da promenite način na koji funkcija print radi, možete to uraditi ovako:

import builtins

_real_print = print

def custom_print(*args, **kwargs):
    _real_print("🚀", *args, **kwargs)

builtins.print = custom_print
print("Pozdrav, Svete!")

Ova tehnika je veoma korisna za debugging, ali je važno napomenuti da je ne preporučuje u produkcionom kodu bez dubinskog razumevanja onoga što radite.

2. Funkcijska Overloading bez @overload

Python ne podržava overloading funkcija nativno, ali uz pomoć functools.singledispatch, možete simulirati ovu funkcionalnost. Ovo je korisno kada želite da pišete različite implementacije za različite tipove podataka.

from functools import singledispatch

@singledispatch
def process(arg):
    raise NotImplementedError("Nepodržani tip")

@process.register
def _(arg: int):
    return f"Celobrojni {arg * 2}"

@process.register
def _(arg: str):
    return f"String {arg.upper()}"

print(process(5))      # Celobrojni 10
print(process("hej"))  # String HEY

3. Dinamičko Umetanje Koda s exec i AST

Zamislite da možete generisati i izvršiti Python kod u runtime-u. To je moguće s modulima ast i exec.

import ast

code = "x = 2 + 3"
tree = ast.parse(code)
compiled = compile(tree, filename="<ast>", mode="exec")
exec(compiled)
print(x)  # 5

Ova tehnika može biti korisna za situacije koje zahtijevaju runtime transformaciju koda.

4. weakref - Reference bez Vlasništva

“weakref” omogućava referencu na objekt bez zadržavanja njegovog postojanja u memoriji. Ova tehnika se često koristi u caching sistemima ili kada želite izbjeći ciklične reference.

import weakref

class Data:
    pass

obj = Data()
weak = weakref.ref(obj)
print(weak())  # <__main__.Data object>
del obj
print(weak())  # None

5. Protokol Deskriptora

Dekoratora za svojstva (@property) je samo sintaktički šećer iznad deskriptora. Kreiranje vlastitog deskriptora može vam pomoći da u potpunosti razumijete strukture podataka u Pythonu.

class Celsius:
    def __init__(self, temp=0):
        self._temp = temp

    def get_temp(self):
        return self._temp

    def set_temp(self, value):
        if value < -273.15:
            raise ValueError("Ispod apsolutne nule!")
        self._temp = value

    temperature = property(get_temp, set_temp)

t = Celsius()
t.temperature = 25
print(t.temperature)

6. Thread-Safe Brojači uz collections.Counter

U višedretvenim okruženjima, standardni brojači mogu postati problematični. Koristeći threading.Lock, možemo osigurati da su naši brojači thread-safe.

import threading
from collections import Counter

counter = Counter()
lock = threading.Lock()

def safe_increment(key):
    with lock:
        counter[key] += 1

threads = [threading.Thread(target=safe_increment, args=("python",)) for _ in range(100)]
[t.start() for t in threads]
[t.join() for t in threads]

print(counter)  # Counter({'python': 100})

7. Import Hooks

Python omogućava da presreo importe tokom izvršavanja, što može biti korisno za alate kao što su pytest i IPython.

import sys

class ImportInterceptor:
    def find_spec(self, name, path, target=None):
        if name == "math":
            print("Intercepted import of math!")
        return None

sys.meta_path.insert(0, ImportInterceptor())
import math

8. Kreiranje Neizmjenjivih Rečnika sa MappingProxyType

Ako želite da kreirate rečnik koji se ne može menjati, možete koristiti MappingProxyType.

from types import MappingProxyType

data = {"a": 1, "b": 2}
frozen = MappingProxyType(data)

print(frozen["a"])  # 1
# frozen["a"] = 99  # ❌ TypeError

9. Time Travel Debagovanje

Možete „zakačiti“ svaku liniju koda koju Python izvršava, što vam omogućava da kreirate svoj vlastiti debager.

import sys

def tracer(frame, event, arg):
    if event == "line":
        print(f"Executing line {frame.f_lineno} in {frame.f_code.co_name}")
    return tracer

sys.settrace(tracer)

def test():
    x = 1
    y = x + 2
    return y

test()

10. Deljena Memorija između Procesa

Zaboravite spore redove, sa multiprocessing.shared_memory, možete deliti sirovu memoriju između procesa.

from multiprocessing import shared_memory
import numpy as np

a = np.array([1, 2, 3, 4])
shm = shared_memory.SharedMemory(create=True, size=a.nbytes)
b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
b[:] = a[:]  # Share data

print(b)  # [1 2 3 4]
shm.close()
shm.unlink()

11. Prilagođene getattr na Modulima

Definisanjem __getattr__ na nivou modula, možete dinamički obrađivati nepoznate atribute.

# mymodule.py
def __getattr__(name):
    if name == "magic":
        return 42
    raise AttributeError(f"No attribute {name}")

# main.py
import mymodule
print(mymodule.magic)  # 42

12. Speeds Hacks sa slots

Korišćenje __slots__ može dramatično smanjiti potrošnju memorije. U velikim OOP kodnim bazama, ovo može biti značajno korisno.

class A:
    __slots__ = ("x",)

class B(A):
    __slots__ = ("y",)

b = B()
b.x, b.y = 1, 2
print(b.x, b.y)  # 1 2

Često Postavljana Pitanja (FAQ)

Koji su glavni benefiti ovih trikova?
Ove tehnike poboljšavaju modularnost, sigurnost i efikasnost koda, a takođe mogu pomoći u smanjenju grešaka tokom razvoja.

Mogu li koristiti ove trikove u produkciji?
Mnoge od ovih tehnika, poput monkey-patching-a ili exec-instrukcija, treba koristiti s oprezom u produkcionim okruženjima. Preporučljivo je prvo testirati kako bi ste izbegli nepredviđene probleme.

Gdje mogu naučiti više o Pythonu?
Postoji mnogo resursa, uključujući kurseve na platformama kao što su Coursera, Udacity i različite video tutorijale na YouTube-u.

Da li je Python najbolji jezik za početnike?
Python se često preporučuje početnicima zbog svoje čitljivosti i jednostavnosti. Takođe je široko korišćen u različitim industrijama, što omogućava studentima i novim programerima mnoge mogućnosti.

Kako mogu nastaviti unapređivati svoje veštine?
Vežbajte redovno, učestvujte u hackathonima, doprinosite open-source projektima i povežite se sa drugim programerima putem online zajednica ili lokalnih meetupa.