Ingat tahun 2016? Semasa dunia sibuk dengan Pokemon Go dan Sukan Olimpik Rio, saya seorang pelajar kolej yang terbeliak, menulis "Hello, World!" dalam Python. Pada masa itu, saya tidak tahu apa yang dimaksudkan dengan pemeliharaan pesanan kamus, apatah lagi mengapa komuniti Python sibuk dengan kemasukannya dalam keluaran 3.6 yang akan datang. Kini, melihat kembali sebagai pembangun yang berpengalaman, sangat mengagumkan untuk melihat sejauh mana Python dan saya telah melangkah.
Daripada f-strings dalam 3.6 kepada padanan corak perubahan permainan dalam 3.10, dan kini kepada ciri thread bebas dalam 3.13, Python telah secara konsisten menolak sempadan perkara yang boleh kami capai dengan kod yang lebih bersih dan lebih ekspresif. Ia seperti menonton wira-wira kegemaran anda mendapat kuasa baharu dengan setiap filem – kecuali daripada merakam web atau menggunakan tukul, kami mendapat alatan yang lebih baik untuk melawan penjahat sebenar: kerumitan kod dan keterlaluan.
Dalam artikel ini, kami akan menghidupkan mesin masa kami dan melakukan perjalanan melalui ciri paling penting yang diperkenalkan dalam setiap versi Python daripada 3.6 hingga 3.13. Kami akan melihat ciri teratas daripada setiap keluaran, meneroka cara ia telah mengubah cara kami menulis kod Python. Sama ada anda seorang Pythonista berpengalaman yang ingin mengimbau kembali atau seorang pemula yang ingin tahu tentang evolusi bahasa, sandarkan diri – kami bersedia untuk perjalanan yang menarik melalui sejarah Python!
Menjelang akhir perjalanan ini, anda mungkin mendapati diri anda melihat kod lama anda dan berfikir, "Wah, bagaimana kita boleh hidup tanpa ciri-ciri ini?" Mari kita selami dan lihat bagaimana kegemaran kami ular telah kehilangan kulitnya selama bertahun-tahun, muncul lebih kuat dan lebih berkuasa dengan setiap transformasi.
Jika ada satu ciri yang membuatkan pembangun Python secara kolektif menghela nafas lega, ia adalah f-strings. Ingat hari pemformatan .format() dan %? F-strings masuk untuk menyelamatkan kita daripada mimpi ngeri pemformatan rentetan kata kerja.
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
Bagi kami yang berurusan dengan jumlah yang besar, ciri ini adalah pengubah permainan. Tiada lagi mengira sifar pada skrin anda!
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
Petua jenis telah wujud sebelum ini, tetapi Python 3.6 menjadikannya lebih fleksibel dengan anotasi berubah-ubah. Ia membenarkan pembayang jenis yang lebih bersih, membuka jalan untuk analisis statik yang lebih baik.
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
Petua bonus: Anotasi ini tidak menjejaskan gelagat masa jalan - ia adalah petunjuk untuk pembangun dan alatan. Tetapi mereka menjadikan autolengkap IDE anda berfungsi seperti sihir! ✨
Ingat kelas menulis dengan sekumpulan parameter __init__ dan kemudian bersusah payah menetapkan setiap satu? Dataclasses memudahkan penciptaan kelas dengan menjana kod boilerplate secara automatik seperti __init__, __repr__ dan __eq__.
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
Ciri ini kedengaran membosankan tetapi menyelesaikan masalah pening: mendayakan rujukan ke hadapan dan prestasi yang dipertingkatkan dengan penilaian yang malas.
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
Sudahlah hari-hari menaip import pdb; pdb.set_trace(). Kini kita hanya boleh melepaskan titik putus() dan meneruskan kehidupan kita!
from __future__ import annotations from typing import List class ChessGame: def __init__(self): self.players: List[Player] = [] # This now works! self.board: Board = Board() # This too! def add_player(self, player: Player) -> None: self.players.append(player) def get_winner(self) -> Player | None: # Python 3.10 union type just for fun! # Game logic here return None class Player: def __init__(self, name: str, rating: int): self.name = name self.rating = rating class Board: def __init__(self): self.moves: List[tuple[Player, str]] = []
Petua Penyahpepijatan: Tetapkan pembolehubah persekitaran PYTHONBREAKPOINT untuk mengawal tingkah laku titik putus:
def calculate_universe_answer(): numbers = list(range(43)) breakpoint() # Your IDE probably supports this better than pdb! return sum(numbers) - 903 def main(): print("Calculating the answer to life, universe, and everything...") result = calculate_universe_answer() print(f"The answer is: {result}") # When you run this, you'll drop into a debugger at the breakpoint # Try these in the debugger: # - 'numbers' to see the list # - 'len(numbers)' to check its length # - 'n' to go to next line # - 'c' to continue execution
Python 3.7 mungkin tidak sehebat 3.6, tetapi ia membawa beberapa peningkatan kualiti hidup yang serius. Kelas data sahaja mungkin menyelamatkan berjuta-juta ketukan kekunci di seluruh dunia! Apa-apa sahaja yang memudahkan penyahpepijatan berbaloi dengan beratnya dalam ular sawa bersalut emas.
Tambahan Python yang paling kontroversi namun berkuasa. Ia membolehkan anda memberikan nilai kepada pembolehubah sebagai sebahagian daripada ungkapan yang lebih besar.
Pengendali walrus membolehkan anda melakukan dua perkara serentak:
# Disable all breakpoints export PYTHONBREAKPOINT=0 # Use a different debugger (like IPython's) export PYTHONBREAKPOINT=IPython.embed
Apabila anda ingin mengatakan "args ini pergi ke sini, tiada soalan yang ditanya!". Anda boleh menentukan hujah yang mesti diluluskan mengikut kedudukan, bukan dengan kata kunci. Ciri ini meningkatkan fleksibiliti reka bentuk API dan boleh menghalang perubahan pecah dalam tandatangan fungsi.
# Consider this code example: while True: user_input = input("Enter something (or 'quit' to exit): ") if user_input == 'quit': break print(f"You entered: {user_input}") # We can simplify above code using walrus operator like this: while (user_input := input("Enter something (or 'quit' to exit): ")) != 'quit': print(f"You entered: {user_input}")
Tambahan sokongan untuk = dalam f-strings, menjadikan penyahpepijatan lebih mudah.
def create_character(name, /, health=100, *, special_move): return f"{name}: {health}HP, Special: {special_move}" # These work player1 = create_character("Pythonista", special_move="Code Sprint") player2 = create_character("Bug Slayer", health=120, special_move="Debug Strike") # This fails - name must be positional # player3 = create_character(name="Syntax Error", special_move="Crash Game")
Pengendali walrus membenarkan kami menulis kod yang lebih ringkas (walaupun dengan kuasa yang besar datang tanggungjawab yang besar!), parameter kedudukan sahaja memberi kami lebih kawalan ke atas antara muka fungsi kami dan penyahpepijatan rentetan f menjadikan penyahpepijatan cetak sebenarnya menyenangkan.
Akhirnya, Python memberi kami cara yang bersih untuk menggabungkan kamus! Ingat hari ketika kita terpaksa menulis dict1.update(dict2) atau menggunakan {**dict1, **dict2}? Hari-hari itu sudah ketinggalan sekarang.
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
Tambahan ini menghapuskan keperluan untuk menaip.Senaraikan, menaip.Dict, dsb., memudahkan anotasi jenis.
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
Ini mungkin kelihatan mudah, tetapi ia sangat berkuasa untuk pemprosesan teks. Tiada lagi panggilan kikuk menghiris atau menggantikan() dengan panjang berkod keras!
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
Python 3.10 (dikeluarkan Oktober 2021), membawa beberapa ciri padanan corak yang sangat hebat ke meja.
Kes suis adalah dekad yang lalu. Padanan corak tiba seperti pisau Swiss Army untuk struktur data. Ia bukan hanya mengenai nilai yang sepadan; ia mengenai menyahbina data dengan keanggunan kod sommelier.
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
Python 3.10 memperkenalkan cara yang bersih untuk mengendalikan berbilang pengurus konteks menggunakan kurungan.
from __future__ import annotations from typing import List class ChessGame: def __init__(self): self.players: List[Player] = [] # This now works! self.board: Board = Board() # This too! def add_player(self, player: Player) -> None: self.players.append(player) def get_winner(self) -> Player | None: # Python 3.10 union type just for fun! # Game logic here return None class Player: def __init__(self, name: str, rating: int): self.name = name self.rating = rating class Board: def __init__(self): self.moves: List[tuple[Player, str]] = []
Python memutuskan bahawa "AttributeError" tidak cukup membantu dan memilih cadangan "Adakah anda maksudkan...". Ia seperti mempunyai penyemak kod terbina dalam yang sebenarnya mahu membantu dan bukannya hanya menunjukkan kesilapan anda.
def calculate_universe_answer(): numbers = list(range(43)) breakpoint() # Your IDE probably supports this better than pdb! return sum(numbers) - 903 def main(): print("Calculating the answer to life, universe, and everything...") result = calculate_universe_answer() print(f"The answer is: {result}") # When you run this, you'll drop into a debugger at the breakpoint # Try these in the debugger: # - 'numbers' to see the list # - 'len(numbers)' to check its length # - 'n' to go to next line # - 'c' to continue execution
Fakta menyeronokkan: Sintaks padanan corak diilhamkan oleh Rust dan bahasa pengaturcaraan berfungsi lain, tetapi Python menjadikannya lebih Pythonic. Jika anda berasal daripada bahasa seperti Scala atau Elixir, anda akan berasa seperti di rumah sendiri!
Python 3.11 membawa sesuatu yang kita semua dambakan – peningkatan kelajuan yang serius! Keluaran ini bukan sahaja pantas; ia adalah "sehingga 60% lebih pantas daripada Python 3.10" pantas, dan 25% lebih pantas secara purata. Tetapi bukan itu sahaja ia dibawa ke meja. Biar saya membimbing anda melalui ciri paling menarik yang menjadikan versi ini istimewa.
Walaupun ini bukan ciri yang anda boleh "lihat" dalam kod, ciri ini pasti anda akan rasai. Python 3.11 memperkenalkan penterjemah adaptif khusus yang menjadikan kod anda berjalan dengan lebih pantas. Berikut ialah contoh pantas untuk ditunjukkan:
# Disable all breakpoints export PYTHONBREAKPOINT=0 # Use a different debugger (like IPython's) export PYTHONBREAKPOINT=IPython.embed
Peningkatan kelajuan amat ketara dalam tugas intensif CPU, pengendalian ralat dan panggilan fungsi bersarang dalam. Ia seperti Python memukul gim dan kembali penampan berbanding sebelum ini! ?
Ciri ini adalah penyelamat apabila berurusan dengan operasi serentak yang berbilang ralat mungkin berlaku serentak. Daripada menangkap hanya satu pengecualian, kami kini boleh mengendalikan berbilang pengecualian sebagai satu kumpulan!
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
Python 3.11 meningkatkan produktiviti pembangun dengan menentukan ralat dengan lebih tepat. Ia seperti mempunyai pembantu penyahpepijat terbina dalam!
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
Mesej ralat ini amat membantu apabila berurusan dengan operasi matematik yang kompleks atau panggilan kaedah bersarang. Tiada lagi mengira kurungan secara manual!
Python 3.11 bukan sekadar satu lagi kemas kini tambahan – ia merupakan lonjakan besar ke hadapan dari segi prestasi dan pengalaman pembangun. Peningkatan kelajuan sahaja menjadikannya peningkatan yang menarik, tetapi masukkan keupayaan pengendalian pengecualian baharu dan mesej ralat yang dipertingkatkan, dan anda telah mendapat keluaran yang benar-benar layak mendapat gelaran "The Speedster"!
Dengan Python 3.12, f-strings telah menjadi lebih baik! Versi terdahulu mempunyai beberapa had—tiada garis miring ke belakang atau ulasan dalam rentetan f dan ungkapan kompleks kadangkala memerlukan penyelesaian.
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
Anda tidak perlu lagi mengimport TypeVar atau Generic secara eksplisit, mengurangkan boilerplate dan meningkatkan kebolehbacaan kod tanpa mengorbankan fungsi.
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
Salah satu titik kesakitan Python yang paling lama wujud ialah Global Interpreter Lock (GIL), mekanisme yang membenarkan hanya satu utas untuk melaksanakan kod bait Python pada satu masa. Ini telah menyebabkan kesesakan prestasi dalam program berbilang benang, terutamanya untuk tugas terikat CPU. Walau bagaimanapun, Python 3.12 memperkenalkan peningkatan yang ketara: Per-Interpreter GIL.
Dalam istilah mudah, GIL menghalang Python daripada benar-benar melaksanakan berbilang benang secara serentak. Walaupun benang sering digunakan untuk operasi terikat I/O (seperti membaca fail atau membuat permintaan rangkaian), GIL mengehadkan faedah berbilang benang untuk beban kerja berat CPU. Ini telah lama menjadi cabaran bagi pembangun Python yang perlu memanfaatkan pemproses berbilang teras.
Dengan Python 3.12, jurubahasa kini mempunyai GIL mereka sendiri, membenarkan berbilang jurubahasa dalam proses yang sama berjalan selari tanpa dikekang oleh satu kunci global. Ini amat berguna untuk pemprosesan berbilang teras. Walau bagaimanapun, Python 3.12 hanya akan menyokong GIL per-jurubahasa melalui C-API. Sokongan penuh Python-API akan ditambah dalam Python 3.13.
Lagi tentang ciri ini:
Python 3.12 mungkin tidak mempunyai impak prestasi segera 3.11, tetapi penambahbaikannya pada ergonomik sistem menaip dan keupayaan f-string menjadikannya keluaran penting untuk menulis kod yang boleh diselenggara dan selamat jenis. Ciri ini amat berharga dalam projek yang lebih besar di mana kejelasan kod dan keselamatan jenis adalah penting.
Python 3.13 mempertingkat Read-Eval-Print-Loop (REPL), menjadikannya lebih pintar dan lebih mesra pengguna. Kini, REPL boleh melaksanakan berbilang baris kod dengan lebih berkesan, memaparkan cadangan sintaks yang lebih baik dan memberikan pengalaman autolengkap yang lebih baik.
REPL baharu mempunyai ciri baharu berikut:
Selama bertahun-tahun, pembangun Python telah terperangkap dalam tarian halus di sekitar Global Interpreter Lock (GIL), mekanisme yang menghalang berbilang benang asli daripada melaksanakan kod bait Python sekaligus. Walaupun GIL mempunyai kelebihannya, ia juga menjadi halangan untuk aplikasi berbilang benang.
Mod free-threading dalam Python 3.13 bertujuan untuk memutuskan rantaian ini dengan melumpuhkan GIL. Ini membolehkan keselarian sebenar dalam program Python berbilang benang. Pada asasnya, urutan anda kini boleh berjalan serentak, memanfaatkan sepenuhnya pemproses berbilang teras. Dalam versi sebelumnya, GIL akan memaksa urutan ini berjalan satu demi satu, dengan berkesan mensiri pelaksanaan.
Anda boleh memuat turun pemasang untuk macOS atau Windows – mereka mempunyai pilihan threading percuma, atau anda boleh menggunakan pyenv untuk membina dan memasang daripada sumber (disyorkan): pyenv install 3.13.0t
Nota: Walaupun mod berbenang bebas merupakan kemajuan besar dalam evolusi Python, adalah penting untuk mengingati status percubaannya (jangkakan beberapa pepijat). Selain itu, binaan berbenang percuma datang dengan prestasi berbenang tunggal sebanyak 40% disebabkan oleh penterjemah adaptif pengkhususan orang kurang upaya (PEP 659).
Pengkompil Just-In-Time (JIT) eksperimen menandakan satu lagi peristiwa penting dalam evolusi Python. Pengkompil JIT berfungsi dengan menterjemah secara dinamik kod bait Python ke dalam kod mesin semasa masa jalan. Ia melakukan ini menggunakan teknik yang dipanggil "copy-and-patch". Ini bermakna laluan kod yang kerap dilaksanakan dihimpun dengan segera, yang boleh secara teorinya membawa kepada peningkatan prestasi yang ketara untuk bahagian kritikal kod anda.
Sekarang, jangan terlalu teruja dulu. Dalam bentuk semasanya, pengkompil JIT tidak bertujuan untuk menjadikan kod anda lebih pantas – ia hanya bertujuan untuk bersaing dengan prestasi Python biasa. Tetapi ia melakukan ini sambil menambah langkah tambahan kepada proses itu, yang sangat mengagumkan. Pasukan Python mempunyai rancangan besar untuk enjin kecil ini, dengan harapan untuk mengubahnya dalam versi akan datang untuk memberi kami beberapa keuntungan kelajuan sebenar tanpa memonopoli memori. Pada masa ini, ia lebih kepada membuktikan konsep dan meletakkan asas untuk pengoptimuman masa hadapan.
Semasa kami menandakan keluaran Python 3.13, satu perkara yang jelas: evolusi Python bukan hanya tentang menambah ciri – ia mengenai menjadikan kehidupan pembangun lebih mudah, satu keluaran pada satu masa. Ia bukan hanya tentang menulis kod; ia mengenai menulis kod yang lebih baik, lebih elegan dan dengan lebih sedikit sakit kepala.
Jadi, rakan-rakan Pythonista, janganlah kita berpuas hati. Python hari ini bukanlah Python yang kita pelajari semalam, dan Python esok mungkin mengejutkan kita lagi. Teruskan meneroka, terus belajar dan terus menolak sempadan perkara yang mungkin dengan dua perkataan mudah tersebut: import ini
Artikel ini pada asalnya diterbitkan pada blog peribadi saya.
Atas ialah kandungan terperinci Kapsul Masa Pythonic: Ciri Mesti Diketahui daripada Setiap Versi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!