با توجه به اینکه در چند سال اخیر دانشگاهها و برنامهنویسان ایرانی به شکل جدی پایتون را مورد توجه قرار دادهاند انتظار میرود در چند سال آینده بر تعداد برنامهنویسان داخلی این زبان افزوده شود. اما اگر تازه به دنیای برنامهنویسی پایتون قدم گذاشتهاید، پیشنهاد میکنیم این مطلب را مطالعه کنید تا اشتباهاتی که در ادامه مشاهده خواهید کرد در کار شما وقفه ایجاد نکنند.
بهکارگیری متغیرهای تغییرپذیر به عنوان پارامترهای پیشفرض در زمان تعریف یک تابع
شما تابعی در اختیار دارید که به منظور جستوجوی لینکهای روی یک صفحه جاری بهکار گرفته شده و لینکها را به فهرست دیگری اضافه میکند. به مثال زیر نگاه کنید.
def findlinks(onepage, add_to=[]):
new_links = onepage.search_for_links()
add_to.extend(new_links)
return add_to
در ظاهر همه چیز خیلی خوب و عادی به نظر میرسد. این قطعه کد کار میکند. اما مشگلی در این زمینه وجود دارد. اگر ما یک فهرست را به پارامتر add_to اضافه کنیم، قطعه کد مطابق انتظار ما کار میکند. با این وجود اگر به تابع اجازه دهیم از مقادیر پیشفرض استفاده کند، اتفاق جالب دیگری رخ میدهد. قطعه کد را با مقدار زیر آزمایش کنید.
def fn(var1, var2=[]):
var2.append(var1)
print var2
fn(3)
fn(4)
fn(5)
شما انتظار دارید تا مقادیر [3]، [4] و [5] را مشاهده کنید. اما در مقابل [3]، [3,4] و [3,4,5] را دریافت خواهید کرد. چرا این اتفاق رخ داد؟ شما فهرست یکسانی را در هر زمان اجرا مشاهده میکنید. در پایتون، زمانی که ما یک تابع شبیه به این مورد مینویسیم، فهرست به عنوان بخشی از تعریف تابع به کار میرود. در نتیجه هر زمان تابع فراخوانی میشود، فهرست جدیدی ساخته نشده و از همان فهرست قبل استفاده میشود. البته این مشگل زمانی به وجود میآید که از مقادیر پیشفرض یا مقادیر تغییرپذیر در تابع استفاده کنیم یا تابع را با مقدار پیشفرض فراخوانی کنیم. برای حل این مشگل باید در زمان تعریف تابع از نوع تغییرناپذیر (Immutable) استفاده کنیم. در نتیجه از قطعه کد زیر باید استفاده کنیم.
def search_for_links(page, add_to=None):
if not add_to:
add_to = []
new_links = page.search_for_links()
add_to.extend(new_links)
return add_to
بهکارگیری نوعهای دادهای تغییرپذیر در قالب متغیرهای کلاس
این مشگل یکی از رایجترین و مرسومترین خطاهایی است که اغلب برنامهنویسان پایتون با آن روبرو هستند. به قطعه کد زیر توجه کنید.
class URLCatcher(object):
urls = []
def add_url(self, url):
self.urls.append(url)
این کد به نظر عادی است. ما یک شی با آدرسهای اینترنتی ذخیرهساز در اختیار داریم. زمانی که متد add-url را فراخوانی میکنیم، یک آدرس اینترنتی را برای ذخیرهسازی اضافه میکند. به نظر میرسد قطعه کد کامل است! اجازه دهید تابع را در عمل مشاهده کنیم.
a = URLCatcher()
a.add_url('http://www.google.com')
b = URLCatcher()
b.add_url('http://www.mysite.co')
b.urls
['http://www.google.com', 'http://www.mysite.co']
a.urls
['http://www.google.com', 'http://www.mysite.co']
صبر کنید چه اتفاقی افتاد؟ ما انتظار این مورد نداشتیم. ما دو شی جداگانه a و b را معرفی کنیم. یکی از اشیا یک آدرس اینترنتی ارائه میکند و شی b آدرس دیگری را ارائه میکند. اما چگونه است که این اشیا هر دو آدرس اینترنتی دارند؟ به نظر میرسد همان مشگل مثال قبل را تکرار کردهایم. فهرست آدرسهای اینترنتی در زمان تعریف کلاس ساخته شده و معرفی میشود. همه نمونههای تعریف شده از کلاس از یک فهرست یکسان استفاده میکنند. برای حل این مشگل قطعه کد زیر را میتوانیم همانند مثل زیر ویرایش کنیم.
class URLCatcher(object):
def __init__(self):
self.urls = []
def add_url(self, url):
self.urls.append(url)
اکنون آدرسهای اینترنتی زمانی که شی ساخته میشود به درستی مقداردهی اولیه میشود. زمانی که دو شی جداگانه را تعریف میکنیم، آنها از دو فهرست جداگانه استفاده میکنند.
ماهنامه شبکه را از کجا تهیه کنیم؟
ماهنامه شبکه را میتوانید از کتابخانههای عمومی سراسر کشور و نیز از دکههای روزنامهفروشی تهیه نمائید.
ثبت اشتراک نسخه کاغذی ماهنامه شبکه
ثبت اشتراک نسخه آنلاین
کتاب الکترونیک +Network راهنمای شبکهها
- برای دانلود تنها کتاب کامل ترجمه فارسی +Network اینجا کلیک کنید.
کتاب الکترونیک دوره مقدماتی آموزش پایتون
- اگر قصد یادگیری برنامهنویسی را دارید ولی هیچ پیشزمینهای ندارید اینجا کلیک کنید.
دیدگاهها
با سلام.
بسیار آموزنده بود.لطفا اینگونه مطالب را به صورت مستمر بیان نمائید.