[h=2][/h] احمد شريفپور اشاره: اول: زمانی به برنامهنویسی به دید امری عجیب، پیچیده و حتی جادویی نگریسته میشد که تنها درتوان خورههای کامپیوتر و نوابغ علوم الکترونیک و کامپیوتر بود. با سادهتر شدن زبانهای برنامهنویسی و کاربرد روزافزون کامپیوتر در زندگی روزمره این دیدگاه بهسرعت در حال منسوخ شدن است. تقریباً هر کاربر ساده کامپیوتر ممکن است در شرایطی قرار گرفته باشد که آرزو کند کاش برنامهای برای انجام عملی خاص وجود داشت یا چه خوب میشد سیستم را برای انجام چنین عملی برنامهریزی کرد. امروزه، این آرزو بیشاز هر زمان دیگری قابل تحقق است. دوم: میگویند یادگیری هر زبان تازه، بعد جدیدی به شخصیت فرد میافزاید. اگرچه این مَثل ممکن است درباره زبانهای برنامهنویسی درست نباشد، اما آشنا شدن با هر زبان برنامهنویسی جدید و پارادایمهای حاکم بر آن، بهیقین به تعالی منطق برنامهنویس، افزایش قابلیتهای وی و از همه مهمتر بهبود روش حل مسئله توسط وی منجرخواهدشد. دراينميان، پایتون انتخابی مناسب برای کاربران مبتدی و حرفهای خواهد بود (کمی بعد با دلایل این انتخاب آشنا خواهید شد). اين مقاله گزيدهاي است از مجموعه مقالاتي در شمارههای مختلف مجله Full Circle Magazine (مجله رسمی توزیع لینوکس اوبونتو) كه بهصورت بسیار ساده و درعينحال کاربردی به معرفی این زبان و قابلیتهای آن خواهد پرداخت. يكي دو قسمت ابتدايي اين مجموعه به معرفي زبان پايتون و آشنايي ابتدايي با آن اختصاص داده شده است. مطالب سایر قسمتها کاملاً مستقل از یکدیگر بوده و هریک با ارائه مثالهای کاربردی به بررسی جنبهای خاص از پایتون خواهد پرداخت. انتخاب اول مجموعه عظیم زبانهای برنامهنویسی موجود را براساس ویژگیها و قابلیتهایشان به دستههای مختلفی طبقهبندی کردهاند. دستهبندیهایی نظیر شيءگرا در برابر روالگرا یا اپنسورس در برابر منبع بسته، مستقل از پلتفرم در برابر وابسته به پلتفرم، ترجمهای در برابر تفسیری و . . . هر یک از این دستهها نشانگر ویژگیها و امکاناتی هستند که ممکن است از یک دیدگاه خاص بسیار مفید و ارزنده محسوب شده و از دیدگاهی دیگر بهعنوان محدودیت شناختهشوند. همین امر انتخاب یک زبان را برای شروع یادگیری به انتخابی دشوار تبديل ميكند. دراينميان، زبانهای مشهور یا زبانهای پرکاربرد لزوماً انتخابهای مناسبی نخواهندبود. بهعنوانمثال، زبانهایی نظیر C یا ++C به برنامهنویس این امکان را میدهند که برنامههای خود را با جزئیات بسیار بالا نوشته و با سرعت فوق العادهای اجرا كنند. اما این سرعت بالا و کنترل شدید برنامهنویس بر تمام جزئیات به قیمت صرف زمان بیشتر برای کدنویسی و رفع اشکال کد تمام خواهد شد. نکته جالبتوجه اينكه در بسیاری از موارد سرعت اجرای برنامهها چندان مهم نیست. درحالحاضر نیز با ارزان شدن مداوم قدرت پردازش سیستمها، بسیاری از برنامهنویسان معتقدند، هدر رفتن درصدی از نیروی پردازش پردازنده در اثر استفاده از زبانهای سطح بالا و درعوض فراهمشدن زمان بیشتر برای تمرکز برنامهنویس بر فعالیت اصلیاش یعنی کدنویسی، معاملهای مقرونبهصرفه است. زبانی که برای شروع یادگیری انتخاب میشود در ابتدا باید ساده باشد، به برنامهنویس تفکر سیستمی و منطقی را بیاموزد، اصول کدنویسی درست را به کاربر آموزش دهد، قادر به پاسخگویی به غالب نیازهای کاربر باشد و درنهايت اینکه بهتراست به سیستمعامل یا ابزار خاص و پیچیدهای وابسته نباشد. برهمیناساس، بسیاری پایتون را بهترین زبان برای شروع یادگیری برنامهنویسی میدانند. پایتون زبانی سطح بالا، داینامیک، اسکریپتی، تفسیری، شيءگرا، آزاد، اپنسورس و مستقل از پلتفرم است که در سال 1991 توسط گوئيدو وان روسوم ابداع شد. باید توجه داشت که معرفی پایتون بهعنوان زبان مناسب مبتدیان بهمعنای کم بودن قابلیتهای آن نیست. هماکنون پایتون بهعنوان یکی از قدرتمندترین ابزارهای برنامهنویسی سیستمی، برنامهنویسی وب و... مورد استفاده قرار میگیرد. چرا پایتون؟ اگرچه ممكن است بسیاری از برنامهنویسان قديمي که با زبانهایی نظیر جاوا و C سروکار داشتهاند، برنامهنویسی با پایتون را چندان جدی نگیرند و حتی آن را کودکانه بدانند، اما این امر از قابلیتهای این زبان نخواهد کاست. درعوض، تعداد زیادی از برنامهنویسان (کسانی نظیر برنامهنویسان گوگل) پایتون را بهدلیل سادگی، خوانایی و امکانات فراوان به هر زبان دیگری ترجیح میدهند. طرفداران پایتون که غالباً Pythonistas نامیده میشوند، معتقدند، این زبان بهقدری کامل و کار با آن بهقدری لذتبخش است که برای تمام نیازهای برنامهنویسی میتوان به آن مراجعهکرد. آنها برای این ادعا دلایل فنی هم ارائه میکنند که برخی از آنها بهشرح زیر است: سادگی پایتون زبانی بسیار ساده و مینیمالیستی است. خواندن یک برنامه خوب پایتون همانند خواندن یک متن انگلیسی است. این طبیعت شبهکد (Pseudo-Code) یکی از بزرگترین نقاط قوت پایتون است و به شما این امکان را میدهد که بهجای تمرکز روی زبان بر روش حل مسئله تمرکز کنید. سهولت یادگیری سادگی این زبان باعث میشود، یادگیری آن از غالب زبانهای موجود سادهتر باشد. برخی عقیده دارند ، یک روز تعطیلي آخر هفته برای یادگیری دستور و قواعد زبان پایتون و بخشی از کتابخانه استاندارد آن کافی است. آزاد و اپنسورس بودن (FLOSS) یکی از بارزترین نمونههایFLOSS (سرنام Free/Libre and Open Source Software) پايتون است. بهعبارتسادهتر، شما میتوانید نسخههایی از این نرمافزار را آزادانه توزیع کنید، کدهای منبع آن را بخوانید، تغییر دهید و از آن در برنامههايتان استفاده کنید. اساس FLOSS برجامعهای بنا شده که افراد آن دانش خود را با یکدیگر بهاشتراک میگذارند. یکی از دلایل برتری پایتون نیز همین است که بهصورت مداوم توسط جامعهای که تنها خواستهاش بهتر شدن این زبان است، بررسی شده و بهبود داده میشود. سطح بالا بودن (High-Level) هنگام کدنویسی در پایتون لازم نیست نگران جزئیات سطح پایین باشید. مدیریت حافظه، جمعآوری پسماندها (Garbage Collection) و... همه توسط خود زبان انجام خواهدشد. قابلیت حمل (Portable) بهواسطه طبیعت اپنسورس پایتون، این زبان به بسیاری از پلتفرمها انتقال داده شدهاست. تمام برنامههای شما میتوانند بدون هیچ تغییری روی تمامی این پلتفرمها اجرا شوند. البته بهشرطی که با هوشیاری از قابلیتهای خاص وابسته به پلتفرم پرهیزکنید. برنامههای پایتون شما بهسادگی روی لینوکس، ویندوز، FreeBSD، مک، سولاریس، آمیگا، پلیاستیشن، Pocket PC و... قابل اجرا هستند. تفسیری بودن (Interpreted) برنامهای که با یکی از زبانهای ترجمهای نظیر C یا #C نوشته میشود، توسط کامپایلر و تنظیم تعداد زیادی گزینه و Flag به زبان قابل فهم ماشین تبدیلمیشود. وقتی برنامه را اجرا میکنید، Loader/Linker برنامه، آن را به حافظه کپی کرده و اجرا میکند. برخلاف این زبانها پایتون به مترجم نيازي ندارد و برنامه شما بهطورمستقيم از روی کد اجرا میشود. درواقع در پشت پرده، مفسر پایتون برنامه شما را بهحالتی واسطهای بهنام ByteCode تبدیل کرده و سپس اجرامیكند. تمام اینها باعث میشود که استفاده از پایتون سادهتر شود. زیرا لازم نیست نگران چرخه کدنویسی، کامپایل، کنترل، اصلاح کد، کامپایل دوباره یا نگران گزینههای کامپایلر، در دسترس بودن و لینک شدن کتابخانههای موردنظر و... باشید. این سیستم قابلیت حمل برنامه را نیز افزایش میدهد. زیرا کافی است شما کد را به سیستم دیگری کپی کنید و برنامه بدون نیاز به کامپایل دوباره بهسادگی اجرا میشود. شيء گرایی (Object Oriented) پایتون از هر دو شیوه برنامهنویسی شيءگرا و روالگرا بهخوبی پشتیبانی میکند. در زبانهای روالگرا، برنامه برمبنای تعدادی روال یا تابع ساخته میشود که درواقع چیزی جزء قطعات کد با قابلیت استفاده دوباره نیستند. در زبانهای شيءگرا برنامه برپایه اشیايی ساخته میشود که اطلاعات و عملکرد را یکجا نگهداری میکنند. پایتون در مقایسه با زبانهایی نظیر #C یا جاوا روش بسیار سادهتری برای برنامهنویسی OOP دارد. قابلیت توسعه (Extensible) اگر در برنامه شما قطعه کدی حساس وجود دارد که لازم است با سرعت بالایی اجرا شود یا میخواهید الگوریتم بهکاررفته در آن را مخفی کنید، میتوانید آن قسمت را به زبانC یا #C بنویسید و آن را از داخل برنامه پایتون اجرا کنید. قابلیت جاسازی (Embeddable) میتوان پایتون را بهصورت توکار (Embedded) در برنامههای C یا #C یا زبانهای دیگر بهکار برد و از اين طريق به استفادهكنندگان برنامه قابلیت اسکریپتنویسی را هدیه کرد. کتابخــانــه استــانــــدارد غنــــــی (Extensive Library) کتابخانه استاندارد پایتون بسیار گسترده و غنی است. این کتابخانه که بههمراه نصب استاندارد پایتون در دسترس خواهد بود، میتواند گستره عظیمی از امور را نظیر Regular Expression، Document Generation، UnitTesting،Threading،Database،Web Browsing،FTP، XML، HTML ،Cryptography ،GUI وEmail پوشش دهد. در کنار کتابخانه استاندارد پایتون، تعداد زیادی کتابخانه خوشساخت دیگر نظیر wxPython (برای ساخت رابط گرافیکی)، Twisted (فریم ورک توسعه اینترنت)، PIL یا Python Imaging Library (برای ویرایش تصاویر) نیز در دسترس شما است.اما درنهایت شاید مهمترین دلیل طرفداران پایتون هیچ یک از موارد فوق نباشد. آنچه آنها را شیفته این زبان میکند لذتی است که از کار با چنین زبان ساده و قدرتمندی نصیب برنامهنویس خواهد شد. چه کسانی از پایتون استفاده میکنند؟ بهدلیل ماهیت اپنسورس و رایگانبودن، آمار دقیقی از استفادهکنندگان این زبان در دسترس نیست، اما شاید نامبردن تعدادی از بزرگترین شرکتهای مرتبط و غیرمرتبط با IT که از این زبان استفاده میکنند تا حدینشاندهنده عمومیت و قدرت این زبان باشد. مشهورترین کاربر زبان پایتون غول دنیای اینترنت یعنی گوگل است. پایتون بهعنوان زبان موردعلاقه برنامهنویسان گوگل شناخته میشود. موتور پردازش ابری گوگل با نام Google App Engine از پایتون پشتیبانی میکند. شما میتوانید برنامههایی را که بهمحاسبههاي سنگین و پیچیده نياز دارند با پایتون نوشته و از طریق App Engine اجرای آن را به سرورهای قدرتمند گوگل بسپارید. ناسا نیز از دیگر استفادهکنندگان پایتون است. بهصورت دقیقتر شرکت United Space Alliance شرکت اصلی پیمانکار مسئول نگهداری شاتلها در ناسا از پایتون برای برنامهنویسیهای علمی، طراحی رابط کاربر و توسعه سریع نرمافزار بهره میبرد. همچنین شرکت اتودسك که از بزرگترین تولیدکنندگان نرمافزارهای طراحي به كمك كامپيوتر (CAD) و مصورسازي است، از پایتون برای ایجاد قابلیت اسکریپتنویسی در محیط مايا استفاده میکند. اما تصور نکنید که استفاده از پایتون تنها بهمحاسبههاي علمی و کاربردهای مهندسی محدود است؛ جرج لوكاس شرکت ILM (سرنام Industrial Light and Magic) را در سال 1975 برای ایجاد جلوههای ویژه فیلم اصلی جنگ ستارگان تأسیس كرد. اين شركت هم اکنون برای ایجاد جلوههای ویژه، گرافیک کامپیوتری و مدیریت سیستمها از پایتون استفاده میکند. و درنهایت میتوان از شرکت فيليپس نام برد. این توليدكننده سرشناس وسایل الکترونیکی و مصرفی برای توسعه سریع نرمافزار، کنترل خط تولید و سیستم کنترل کیفیت خود از پایتون بهره میبرد. براي مشاهده فهرست کاملی از کاربران مشهور پایتون براساس زمینه فعالیت بههمراه خلاصهای کوتاه از نحوه استفاده و دلایل بهکارگیری این زبان ميتوانيد کدام پایتون ؟ کدام ابزار؟ زبان پایتون درحالحاضر در دو ويرايش متفاوت منتشر میشود. ويرايش اول سری2.x پایتون است که اکنون توزیع استاندارد پایتون بهشمارميآيد وبه نسخه 7/2 رسیده است. توسعه در این دسته برمبنای حفظ سازگاری با نسخههای قبلی انجام میشود. ويرايش دوم سری 3.x پایتون است که از ابتدا بدون سازگاری با نسخههای 2.x و با هدف ایجاد قابلیتهای بیشتر و بهروزتر در زبان تولیدشده و اکنون به نسخه 1/3 رسیده است. این نسخه هنوز همانند سری دوم عمومیت نیافته و بههمیندلیل در این مجموعه مقالهها از سری 2.x استفاده خواهدشد. بهيقين تمام کدهای نوشته شده در این مجموعه با هر نسخهاي بالاتر از 2/2 سازگار بوده و قابل اجرا هستند.این سری مقالهها برمبنای سیستمعامل لینوکس (بهصورت خاص اوبونتو) نوشته شدهاند. اما تمام کدها روی تمام سیستمها قابل اجرا هستند. اگر در کدها از توابع و ویژگیهای خاص وابسته به سیستمعامل استفاده شده باشد، دركنار کد به آن اشارهخواهدشد. درصورتیکه شما از یکی از توزیعهای مشهور لینوکس استفاده میکنید، به احتمال زیاد پایتون از پیش روی سیستم شما نصب شده است. برای سیستمعاملهای ویندوز و مک میتوانید با مراجعه به سایت رسمی پایتون(نسخه مناسب سیستمعامل خود را دانلود کرده و نصب كنيد. کار با زبان برنامهنویسی پایتون بههیچ ابزار یا امکانات خاصی احتیاج ندارد. تنها با داشتن یک ویرایشگر متن ساده نظیر Gedit در لینوکس یا Notepad در ویندوز میتوانید شروع به کدنویسی کنید. اما درصورتیکه ویرایشگر شما از رنگبندی کد (Syntax Highlight) و سیستم تورفتگی خودکار (Auto Indent) پشتیبانی کند، سرعت کدنویسی و تصحیح شما بسیار بالاتر خواهدرفت. غالب ویرایشگرهای متن لینوکس نظیر Kate (در محيط KDE)و (Gedit (GNOME از هر دوی این قابلیتها پشتیبانی میکنند. در ویندوز میتوانید از ++Notepad که نرمافزاری آزاد و رایگان است استفادهکنید. همچنین در ویندوز و مک نصب استاندارد پایتون محیط برنامهنویسی پیشفرض پایتون یا IDLE را نیز بههمراه خواهدداشت که بسیار فراتر از یک ویرایشگر متن ساده در نوشتن و تصحیح کد به شما کمک خواهدکرد. در تمام توزیعهای لینوکس، این برنامه از مخازن سیستم بهسادگی قابل نصب است. با مراجعه بهآدرس میتوانید فهرست ویرایشگرها و محیطهای توسعه موجود را برای پایتون مشاهده کنید. مثال مقدماتی 5 دقیقهای نمونه کد پایتون فرض کنید میخواهیم حاصل عبارت (g(x)=x/(1-x را برای مقادیر x معادل 0.9 ، ...، 0.3 ، 0.2 ، 0.1 بیابیم. کافی است در یک فایل متنی مثلاً با نام fme.py کد موجود در فهرست 1 را نوشته و در خط فرمان با تایپ دستور زیر آن را اجرا کنید. python fme.py $ خروجی برنامه مانند فهرست 2 خواهد بود (میتوانید این عملیات را در IDLE نیز انجام دهید. کافی است پس از بازکردن برنامه از منوی File گزینه New Window را انتخاب كرده، کد موردنظر را تایپ كرده و پس از ذخیره کردن با F5 اجرا كنيد). for i in rage (10) : x=0.1*i print x print x/ (1-x*x) فهرست 1 >>> 0.0 0.0 0.1 0.10101010101 0.2 0.208333333333 0.3 0.32967032967 0.4 0.47619047619 0.5 0.666666666667 0.6 0.9375 0.7 1.37254901961 0.8 2.22222222222 0.9 4.73684210526 >>> فهرست 2 ليستها در پایتون این برنامه چگونه کار میکند؟ در ابتدا تابع ()range پایتون نمونهای از استفاده ليستها را در این زبان نشان میدهد. در زبان پایتون ليست چیزی شبیه آرایه است. ليستها یکی از انواع بنیادی پایتون هستند. تابع ()range درواقع یک ليست را برمیگرداند که در اینجا عبارت است از [0,1,2,3,4,5,6,7,8,9] . به علامتهای [] توجه کنید. این روش رسمی پایتون برای نشان دادن یک ليست است. ليست درواقع ردیفی از اشیاي مختلف (هر تعداد شيء با هر ترتیب و هر نوعی) است که داخل [] قرار دارند و با کاما از یکدیگر جدا شدهاند. پس دستور اول کد ما در واقع معادل عبارت زیر است: :[for i in [0,1,2,3,4,5,6,7,8,9همانطور که حدس میزنید این کد باعث ده بار گردش حلقه میشود که در بار نخست i برابر صفر و در بار دهم برابر9 است. پایتون یک ساختار while هم دارد (البته بدون until). همچنین مانند C++/C دستور break برای خروج کامل از حلقه دردسترس است (فهرست3). >>> x=5 >>> while 1: x += 1 if x == 8: print x break 8 >>> فهرست 3 تعریف بلوک در پایتون حال به علامت دونقطه انتهای دستور for توجه کنید که شروع یک بلوک کد را اعلام میکند. برخلاف زبانهایی نظیر C++/C یا حتی Perl ، که از {} برای تعریف بلوک استفاده میکنند، پایتون از ترکیب دونقطه و تورفتگی برای تعریف بلوکها استفاده میکند. ما با دونقطه به پایتون میگوییم که قصد داریم یک بلوک کد را آغاز کنیم و با تورفتگی ابتدای خطوط دستورات آن بلوک را تعریف میکنیم. برای تورفتگی میتوانیم از 3 یا 4 یا 10 فضای خالی استفاده کنیم. میزان این فضای خالی تا زمانی که در تمام کد رعایت شود، اهمیتی ندارد. بنابراین، درصورت وارد کردن کد (فهرست4) با خطای دستوری پایتون مواجه میشویم، زیرا تنها در صورتی میتوانیم در یک بلوک از تورفتگی استفاده کنیم که بخواهیم بلوک دیگری در دل آن ایجادکنیم (فهرست5). >>> for i in range (10) : print 0.1*i print g(0.1*i) File “<pyshell#18>”, line 3 print g(0.1*i) IndentationError: unexpected indent >>> فهرست 4 >>> for i in range (10) : if i%2 == 1 : print 0.1*i 0.1 0.3 0.5 0.7 0.9 >>> فهرست 5 در این حالت فقط زمانی که متغیر i یک عدد فرد است ما دستور چاپ را اجرا ميكنيم. عملكرد % یا mod همانند C++/C باقیماندهتقسیم را بازمیگرداند. دوباره به علامت دونقطه در انتهای دستور if و فاصلهگذاری ابتدای دستور print دقت کنید. همینطور دقت داشته باشید که مانند C++/C/perl احتیاجی به علامت نقطه کاما در انتهای دستورات نیست. هر خط جدید بهمعنای دستوری جدید خواهد بود. درصورتیکه خطی طولانی دارید میتوانید برای شکستن آن از علامت"\" استفاده کنید (فهرست 6). >>> y=7 >>> z=12.5 >>> x = y + \ z >>> >>> x 19.5 فهرست 6 پوسته تعاملی (خط فرمان پایتون) یکی از قابلیتهای جذاب پایتون خط فرمان تعاملی آن است. شما بهصورت معمول زیاد از این قابلیت استفاده نمیکنید، اما برای بررسی برخی امکانات و آزمايش سریع دستورات بسیار مفید خواهد بود. هرگاه بهعملکرد درست قسمتی شک دارید باید از سیستم آزمایش و خطا استفاده کنید و بهترین و سریعترین روش آزمودن استفاده از خط فرمان تعاملی پایتون است. بهجای نوشتن کد در فایل متنی و اجرای آن ما کد را در پوسته پایتون نوشته و اجرا میکنیم. با تایپ دستور Python بهتنهایی یا اجرای IDLE به پوسته پایتون دسترسی خواهیم داشت (شکل زير). در اینجا با اجرای پایتون اعلان حالت تعاملی یعنی >>> بهنمایش درمیآید. سپس شروع به تایپ خط به خط کد میکنیم. هر زمان که داخل یک بلوک کد باشیم اعلان ویژه " ..." بهنمایش درمیآید. وقتی درانتهای کد یک خط خالی را وارد کنیم، پایتون متوجه اتمام کد شده و آن را اجرا میكند. درباره پوسته تعاملی توجه داشته باشید که بین پلتفرمهای مختلف تفاوتهای کمی وجود دارد. بهعنوانمثال، ممکن است فاصلهگذاری بهصورت خودکار انجام نشود یا در ویندوز شما با تایپ CTRL + Z از پوسته خارج میشوید، اما در لینوکس باید از CTRL + D استفاده کنید. همچنین توجه کنید که در IDLE اعلان " . . ." بهنمایش درنمیآید. در حالت تعاملی ارجاع به یک شیء یا ساخت یک شیء یا نوشتن یک عبارت بدون نسبت دادن آن به یک متغیر باعث چاپ شدن مقدار آن میشود (فهرست7). >>>for i in range (4) : 3*i 0 3 6 9 >>> open (“x.txt”) <open file ‘x.txt’ , mode ‘r’ at 0x01944390> >>> فهرست 7 در مثال دوم ما فایل x.txt را باز کردهایم که نتیجه حاصل یک شیء فایل است و چون آن را بهمتغیری (معمولاً f) نسبت ندادهایم، شیء فایل چاپ شده است (فایل x.txt باید در مسیر جستوجوی پایتون موجود باشد).پایتون بهعنوان یک ماشین حساب یکی از قابلیتهای دیگر پوسته تعاملی امکان استفاده از آن بهعنوان یک ماشین حساب سریع است. بهعنوانمثال، برای محاسبه مقدار 88.88 بهعلاوه پنج درصد کافی است، عبارت اول را تایپ کنیم (فهرست8 ) یا برای تبدیل اعداد بین مبنای 10 و 16 از دستورات قسمت دوم استفاده کنیم. >>> 1.05*88.88 93.323999999999998 >>> >>> >>> 0x12 18 >>> hex (18) '0x12' >>> فهرست 8اگر به محاسبههاي ریاضی خاصی احتیاج داشته باشیم باید ابتدا کتابخانه math را از مجموعه کتابخانههای استاندارد پایتون import کنیم. دقیقاً همانند سیستمی که در سييا سيشارپ با دستور include# پیادهمیشود، سپس میتوانیم با سیستم نشانهگذاری نقطهای از توابع تعریف شده در کتابخانه math استفاده کنیم. در شكل زير استفاده از توابع ()sin و ()sqrt نشاندادهشدهاست. همچنین توجه کنید که در محیط IDLE با تایپ math و علامت نقطه و مکثی کوتاه فهرست توابع موجود کتابخانه ظاهرمیشود. شما اکنون تا حدودی با زبان پایتون آشنا شدهاید و کموبیش تواناییها و قابلیتهای آن را میشناسید. اگر در قسمتهای بعدی این مجموعه با ما همراه باشید، در هر قسمت با جنبهای تازه و کاربردی از این زبان آشنا خواهیدشد. قسمتهای بعدی درعینسادگی و کاربردی بودن مستقل از یکدیگر بوده و برای مطالعه و استفاده از آنها به مهارت خاصی نياز ندارید و حتی لازم نیست به پایتون چندان مسلط باشید، زیرا در هر قسمت مطالب پایهای مرتبط آورده خواهندشد. اما درصورتیکه زیبایی پایتون توجه شما را جلب کرده و مشتاق یادگیری بهتر این زبان هستید، بهترتیب دو منبع زیر را به شما پیشنهاد میکنیم: 1- A Byte of Python (Swaroop
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون آشنايي و كار با زبان برنامهنويسي پايتون -2 اشاره: در قسمت قبلی این مجموعه به طور خلاصه به معرفی زبان برنامهنویسی پایتون پرداختیم و چند نمونه ساده و ابتدایی از برنامههای پایتون را بررسی کردیم. در این قسمت با مفاهیم جدیدی آشنا خواهیم شد و برنامه به نسبت کاملی را پیادهسازی خواهیم کرد. این برنامه یک بازی بسیار ساده Tic-Tac-Toe را شبیهسازی میکند. اگرچه این بازی منطق پیچیده و خاصی ندارد، اما سیستم تفکیک کد، فراخوانی توابع، وارد کردن ماجولها و... را به شما خواهد آموخت. در قسمت قبلی این مجموعه به طور خلاصه به معرفی زبان برنامهنویسی پایتون پرداختیم و چند نمونه ساده و ابتدایی از برنامههای پایتون را بررسی کردیم. در این قسمت با مفاهیم جدیدی آشنا خواهیم شد و برنامه به نسبت کاملی را پیادهسازی خواهیم کرد. این برنامه یک بازی بسیار ساده Tic-Tac-Toe را شبیهسازی میکند. اگرچه این بازی منطق پیچیده و خاصی ندارد، اما سیستم تفکیک کد، فراخوانی توابع، وارد کردن ماجولها و... را به شما خواهد آموخت. این بازی از یک صفحه شطرنجی 3 × 3 تشکیل شده که بازیکنان به نوبت با حروف X یا O یکی از خانههای آن را اشغال میکنند. هدف هر بازیکن قرار دادن سه علامت در کنار هم به صورت سطری، ستونی یا قطری است. در بازی شبیهسازی شده ما بازیکن با حرف X در برابر کامپیوتر با حرف O بازی خواهد کرد. تقسیم و غلبه (Divide & Conquer) یکی از روشهای بسیار پرکاربرد در حل مسئله و طراحی الگوریتم، روش تقسیم و غلبه است. در این روش هر مسئله به مسائلی ریزتر تقسیم میشود و این روند آنقدر ادامه مییابد تا به مسائلی بسیار ساده با راهحل آسان برسیم. حل هر مسئله ریز، به صورت جداگانه پیادهسازی شده و سپس از جمع آنها راهحل نهایی به دست میآید. در برنامهنویسی پایتون این تقسیمبندیها در مرحله نخست شامل تفکیک کل برنامه به تعدادی ماجول و سپس تفکیک ماجولها به تعدادی شیء (Object) يا تابع (Function) است. ما مسئله بازی Tic-Tac-Toe را به صورتی مانند شکل زير تفکیک میکنیم تفكيك بازي به قسمتهاي مختلف ابتدا کل مسئله به سه بخش اساسی تقسیم میشود که عبارتند از: حلقه اصلی روند اجرای بازی، بخشی جهت تعامل با بازیکن (کاربر) و در نهایت بخشی برای كنترل و مديريت صفحه بازی. هر یک از این بخشها در فایل جداگانهای به نام ماجول نوشته میشوند و وظایف مربوط به خود را از طریق تعدادی تابع به انجام میرسانند. فعلاً نگران این اصطلاحات نباشید. در پایتون همه چیز سادهتر از آن است که به نظر میرسد. ماجول مربوط به بازیکن کد فهرست 1 را در IDLE یا هر ویرایشگر متن دلخواهی نوشته و آن را با نام player.py ذخیره کنید. شمارههای خطوط را وارد نکنید. ما از آنها برای توضیحات بعدی استفاده کردهایم.خط 1، یک توضیح یا Comment است. علامت # در هر کجای خط قرار بگیرد، پایتون عبارات بعد از آن را نادیده میگیرد. از توضیحات به طور معمول برای تقسیمکردن کد به بخشهای قابل فهم برای انسان و شرح روند اجرای برنامه استفاده میشود تا مطالعه کد و ویرایشهای بعدی آن سادهتر شود. ######### Getting Player›s Name ########## def Get_Player_Name(): name = raw_input(“Enter your name plaese: “) print “Hi %s , you will play against computer. \ \nyour mark is ‹X›” %name return name ######### Play One Turn ################## def Play_One_Turn(b,player): while 1: # Player Turn place=input(“Your Turn %s.Enter Location:\n\ (Enter comma seperated values like 2,3): “ %player) x,y = place[0] , place[1] if x < 1 or x > 3: print “Error . . . \nX is invalid” continue if y < 1 or y > 3: print “Error . . . \nY is invalid” continue if b[x-1][y-1] == “ “: b[x-1][y-1] = “X” break else: print “This point is aquired by: %s” %b[x][y] return فهرست 1- ماجول مربوط به بازيكنخط 2 یک تابع را تعریف میکند. تابع یا function یکی از عناصر اساسی هر زبان برنامهنویسی است. حتی در زبانهای برنامهنویسی شیءگرای کنونی نیز توابع یا روالها (subroutine) وظیفه اصلی تقسیمبندی و تفکیک کد را انجام میدهند. تابع قسمتی از کد است که با گرفتن ورودیهای مشخص، خروجی مشخصی را تولید میکند یا کاری را به انجام میرساند. تابع به خودی خود اجرا نمیشود. برای استفاده از یک تابع باید آن را صدا زد یا به اصطلاح فراخواند. در پایتون تعریف تابع (که دارای مقدار برگشتی است) با تعریف روال (که فاقد مقدار برگشتی است) تفاوتی ندارد. بهطور کلی تعریف تابع در پایتون به شکل زیر انجام میشود: def <function_name> ( [list of arguments] ): function body return [List of values to return] به تورفتگی بدنه تابع، اختیاری بودن آرگومانهای ورودی و مقادیر خروجی توجه کنید1. توجه داشته باشید که نام توابع و متغیرها نباید از بین کلمات کلیدی پایتون (فهرست 2) انتخاب شود. همچنین استفاده از علامتهای _ و __ (زیر خط تکی و زیرخط دوتایی) در ابتدای نام تابع یا متغیر، ویژگیهای خاصی را به آنها نسبت خواهد داد که بررسي آن در اين مقاله نميگنجد. and assert break class continue def del elif else except exec finally for from global if import in is lambda not or pass print raise return try while فهرست 2- كلمات كليدي پايتونهمانگونه که از پرانتز خالی جلوی نام تابع Get_Player_Name مشخص است، این تابع آرگومان ورودی ندارد. ما از این تابع برای دریافت نام بازیکن و نمایش پیغام خوشامد استفاده خواهیم کرد.در خط 3 از فرمان raw_input برای گرفتن یک رشته یعنی نام کاربر استفاده شده است. در سری 2.x پایتون برای گرفتن اعداد از input() و برای گرفتن رشتهها از raw_input() استفاده میشود. اما در سری 3.x پایتون دستور raw_input حذف شده و تنها از دستور input استفاده میشود که در هر صورت یک رشته را برمیگرداند و تبدیل نوع داده ورودی به عدد یا سایر انواع باید توسط برنامهنویس صورت بگیرد. دستورات input و raw_input هر دو از توابع درونی پایتون هستند. این توابع یک آرگومان ورودی دارند که یک رشته است. این رشته بهعنوان پیام برای کاربر نمایش داده شده و جواب کاربر مقدار برگشتی تابع است. در این جا مقدار برگشتی (یا همان پاسخ کاربر) به متغیر name نسبت داده میشود. پایتون تعداد زیادی تابع توکار یا درونی دارد که گستره وسیعی از عملیات پرکاربرد را به انجام میرسانند. در پایتون لازم نیست پیش از استفاده از متغیر آن را تعریف کرد. با نخستين دستور انتساب، متغیر تعریف شده و نوع آن براساس مقدار نسبت داده شده تعیین میشود. در اینجا متغیر name خود به خود از نوع رشته خواهد بود. در خط 4 از دستور print برای چاپ پیام خوشامد استفاده شده است. به علامت ‘\’ در انتهای خط توجه کنید. همانطور که در شماره گذشته اشاره شد، از این علامت برای شکستن خطوط طولانی به تعدادی خط منطقی استفاده میشود. همچنین توجه داشته باشید که انتقال خروجی دستور چاپ به سطر بعد، در حین اجرا با عبارت ‘\n’ انجام میشود. نکته آخر در این دستور علامت ‘%s’ است. برای جای دادن دادههای خاص نظیر اعداد و رشتههای ذخیره شده در یک متغیر، در دل یک رشته (به عنوان مثال، رشتهای که قرار است چاپ شود) از این گونه علامتها استفاده میشود. از ‘%d’ و ‘%f’ نیز برای جایگذاری اعداد صحیح و اعشاری استفاده میشود. سیستم این جایگذاری به فرم زیر است: “ string %<s|d|f|…> string “ % ( <variable> [,variable , variable, . . .] ) يعني هر عبارت بعد از علامت % بيرون رشته، به ترتیب جایگزین یکی از علامتهای موجود در رشته خواهد شد. اگر مجموعه دستورات زیر را در نظر بگیریم: score = 86 field = “mathematic” print “I got %d in %s” % (score , field) خروجی آن برابر «I got 86 in mathematic» خواهد بود.در نهايت، در خط 6 توسط کلمه کلیدی return، مقدار متغیر name به صدا زننده تابع بازگردانده میشود.خط 8 تعریف یک تابع جدید است و همانگونه که از نام آن بر میآید، تعامل با بازیکن برای انجام یک نوبت از بازی را به عهده دارد. پرانتز پس از نام تابع نشان میدهد که این تابع دو مقدار ورودی دارد. ما این دو مقدار را به ترتیب صفحه بازی b و نام بازیکن player در نظر گرفتهایم. مقدار b به اصطلاح به تابع پاس شده است تا از روی آن، نقطه مورد نظر بازیکن با نقاط خالی صفحه مقایسه شود. نام بازیکن هم برای نمایش پیغامها مورد استفاده قرار خواهد گرفت. در خط 9 حلقه تعامل با کاربر آغاز میشود. این حلقه تا زمانی که کاربر یک نقطه مناسب (آزاد و در محدوده صفحه بازی) را انتخاب نکرده باشد، ادامه خواهد یافت. همانگونه که در قسمت قبل دیدهاید یکی از راههای خروج از حلقه دستور break است که کنترل عملیات را به خط بعد از حلقه منتقل میکند. در خط 11 محل مورد نظر کاربر پرسیده میشود. بازیکن باید محل را به صورت یک جفت عدد که با کاما (،) از یکدیگر جدا شدهاند وارد کند. متغیر حاصل یعنی place از دید پایتون یک توپل (tuple) است. توپل در زبان پایتون بسیار شبیه ليست است، اما تفاوت آن با ليست غیر قابل تغییر بودن آن است؛ يعني عناصر یک ليست را میتوان ویرایش کرد، اما عناصر موجود در توپل را نمیتوان تغییر داد. بعدها درباره توپل بیشتر صحبت خواهیم کرد. تنها نکته مهم این است که برای ارجاع به عناصر ليست یا توپل از علامت [] در جلوی نام ليست یا توپل استفاده میشود. توجه کنید که مانند غالب زبانهای برنامهنویسی اندیس توپلها و ليستها از عدد صفر آغاز میشود.بنابراین، در خط 13، place[0] عضو نخست توپل را بهعنوان x و place[1] عضو دوم آن را بهعنوان y جدا میکند. در خطوط 14 تا 19، مقادیر x و y کنترل میشوند تا در محدوده صفحه باشند. اگر اعداد در محدوده صفحه بازی (3×3) نباشد یک پیغام خطا چاپ شده و به کمک دستور continue حلقه گردش بعدی را انجام میدهد. در هر حلقه، چه از نوع for و چه از نوع while، دستور continue باعث میشود که روند فعلی حلقه قطع شده و کنترل دوباره به ابتدای بدنه حلقه بازگردد. در خط 20 کنترل میشود که آیا محل انتخاب شده (که اکنون مطمئن هستیم در محدوده صفحه بازی است) قبلاً اشغال شده یا خير؟ اگر اشغال نشده باشد، علامت مختص بازیکن در آن ثبت شده و با دستور break از حلقه خارج میشویم. چون اندیس ليستها و توپلها از صفر شروع میشود برای کنترل صفحه بازی از x و y یک واحد کم کردهایم. خط 23 استفاده از دستور else را نشان میدهد. در صورتیکه شرط if آخر درست نباشد، کنترل به دستور else منتقل میشود. در این حالت پیامی مبنی بر اشغال بودن نقطه مورد نظر چاپ شده و حلقه دوباره از ابتدا اجرا میشود. همانطور که در خط 25 مشاهده میکنید، این تابع مقدار برگشتی ندارد. نکته مهمی که همیشه باید به خاطر داشته باشید این است که در پايتون ليستهاي پاس شده به تابع نظیر b، بهصورت «ارجاع به محل» یا By Reference مورد استفاده قرار خواهند گرفت و بنابراین هر تغییری در آن به طور مستقيم به متغیر اصلی (اینجا یعنی صفحه اصلی بازی board) اعمال خواهد شد و در نتیجه به مقدار بازگشتی نیازی نخواهد بود. ماجول مربوط به صفحه بازی در فهرست 3، ماجول دوم که سازنده و کنترل کننده صفحه بازی است، نمایش داده شده است. این ماجول را تایپ کرده و با نام board.py ذخیره کنید. با یک نگاه کلی و با توجه به توضیحاتی که تاکنون دادهایم، مشخص میشود که این ماجول سه تابع برای ساخت صفحه نمایش، چاپ آن و کنترل برنده بازی تعریف میکند. ######### Creating the Board ############# def Create_Board(): b=[] for i in range(3): b.append([]) for j in range(3): b.append(“ “) return b ######### Printing the Board ############# def Print_Board(b): s=”” for j in range(2,-1,-1): s=s+”\n-------------\n|” for i in range(3): s= s+ “ “ + b[j]+ “ |” s=s+”\n-------------\n” print s return ########## Checking for Winner ########### def Check_Winner(b): for sign in [“X” , “O”]: #check rows for i in range(3): score=0 for j in range(3): if b[j] == sign : score += 1 if score == 3 : return sign #check columns for j in range(3): score=0 for i in range(3): if b[j] == sign : score += 1 if score == 3 : return sign #check diameters score1=score2 =0 for i in range(3): if b== sign: score1 +=1 if b[2-i] == sign: score2 += 1 if score1 == 3 or score2 == 3: return sign #check if board is full empty = 0 for i in range(3): for j in range(3): if b[j] == « «: empty += 1 if empty == 0: return “No one” return None فهرست 3- ماجول مربوط به صفحه بازيدر خط 3 متغیری به نام b از نوع ليست تعریف میشود. این متغیر در این مرحله هیچ عضوی ندارد.در خط 4 با یک دستور for حلقهای با سه بار تکرار تعریف میشود که در خط 5 به کمک متد append یک ليست تهی دیگر را به ليست b اضافه میکند. در دو خط بعدی با یک حلقه for دیگر، به این ليست داخلی، سه رشته با مقدار “ “ افزوده میشود. در نهایت متغیر b به فرم زیر درخواهد آمد: b= [[“ “,“ “,“ “],[“ “,“ “,“ “],[“ “,“ “,“ “]] همانطور که پیشتر توضیح دادیم برای دسترسی به عناصر داخل ليست از اندیسها و علامت [] استفاده میکنیم. بنابراین، b[0] نخستين عضو b است که خود یک ليست دیگر است و b[1][2] به سومین عضو در دومین عضو b اشاره میکند. ما از این تجرید برای شبیهسازی مختصات یا همان x و y صفحه بازی استفاده کردهایم. به عبارت دیگر، عنصر نخست b نماینده ستون نخست یا x=1 و به عنوان مثال، عنصر دوم نماینده ستون دوم خواهد بود. به همین شکل مقدار b[2][1] نماینده محتویات نقطهای با مختصات (3،2) خواهد بود. ليستها که از قسمت قبل با تعریف آنها آشنا شدهاید، از پرکاربردترین انواع بنیادی پایتون هستند. ليست در واقع چیزی شبیه آرایه در سایر زبانها است، با این تفاوت که لازم نیست از ابتدا اندازه آن را مشخص کنید یا نوع داده آن را تعریف كنيد و همچنین هنگام اجرای برنامه ميتوانيد هم خود ليست و هم عناصر آن را تغییر دهید. همانگونه که دیدید با متد append میتوان هر چیزی را به ليست اضافه کرد.در خط 10 تابع دیگری برای چاپ صفحه نمایش تعریف میشود. در خط 11 متغیر s از نوع رشته و با مقدار تهی تعریف شده است. خط 12 نمونه دیگری از کاربرد range() را نشان میدهد. همانطور که بهاحتمال حدس زدهاید، range() هم یکی از توابع داخلی پایتون است. در این خط، تابع range() سه آرگومان گرفته است که به ترتیب عدد شروع، عدد پایان و میزان تغییر در هر مرحله است. فرم کلی دستور range() مانند زیر است: range ( [start ,] <stop> [,step] ) اکنون میدانید که عبارت فوق يعني آرگومان stop یا پایان ليست تولیدی الزامی ولي آرگومان شروع و مقدار افزایش در هر مرحله اختیاری است. نتیجه خروجی range(2,-1,-1) در اینجا ليستي با مقدار [ 2 , 1 , 0 ] است. دلیل استفاده از این ليست معکوس این است که هنگام چاپ، ليست از بالا به پایین یعنی از خانههايي به مختصات (1,3)، (2,3) و (3,3) چاپ میشود در حالیکه مقادیر موجود در متغیر b به ترتیب از (1,1)، (1,2) و الی آخر شروع میشوند. مجموعه خطوط 13 تا 16 با ترکیب عناصر b و کاراکترهای “-“ و “|” جدولهايي شبیه شکل 2 را برای بازی به وجود آورده و چاپ میکنند شكل 2- شبيهسازي صفحه بازيبه دلیل طولانی بودن تابع سوم ما از توضیح خط به خط آن صرف نظر میکنیم. این تابع به رغم ظاهر طولانی، منطقی بسیار ساده دارد. به طور خلاصه اینکه در خط 21 حلقهای تعریف میشود که تنها دوبار یک بار با مقدار X (نماینده بازیکن) و بار دیگر با مقدار O (نماینده کامپیوتر) اجرا خواهد شد. در خطوط 22 تا 29، با یک سری حلقه for امتیاز X یا O در همه سطرها محاسبه میشود که اگر تنها در یک سطر برابر 3 بود، علامت X یا O با دستور return به عنوان برنده به صدا زننده تابع بازگردانده شده و عملکرد تابع تمام میشود. در خطوط 31 تا 37 همین کار برای ستونها انجام میشود. در نهایت در خطوط 39 تا 46، قطرهای صفحه بازی کنترل ميشود. رسیدن کنترل اجرا به خط 48، به این معنی خواهد بود که بازی تاکنون هیچ برندهای نداشته است. در اینجا کل صفحه برای وجود خانههای خالی بررسي میشود که درصورت عدم، وجود بازی مساوی اعلام خواهد شد. درصورتیکه صفحه بازی هنوز جای خالی داشته باشد، مقدار None یا هیچ، که از مقادیر از پیش تعریف شده پایتون است، برگشت داده میشود. ماجول اصلی فهرست 4 ماجول اصلی یا کنترل کننده برنامه را نشان میدهد. این مجموعه کد را تایپکرده و با نام main.py در کنار سایر فایلها ذخیره کنید. به خط 1 که با علامت #! شروع شده است، به اصطلاح شیبنگ یا shebang گفته میشود. این خط در محیطهای لینوکسی به سیستم عامل اعلام میکند که برای اجرای این اسکریپت (در صورتیکه به آن مجوز اجرا داده شده باشد) از چه مفسر یا مترجمی استفاده کند. در سیستم ویندوز یا سایر موارد این خط همانند یک توضیح یا comment دیده میشود. #! /usr/bin/env python ######### importing required modules ##### import random from board import Create_Board , Print_Board , Check_Winner from player import Get_Player_Name , Play_One_Turn ########## Main Section ##################### player=Get_Player_Name() board = Create_Board() Print_Board(board) while 1: Play_One_Turn(board,player) Print_Board(board) winner = Check_Winner(board) if winner <> None: print “Game Over \n%s won the game . . . “ %winner break while 1: # Computer Turn x = random.randint(1,3) y = random.randint(1,3) if board[x-1][y-1] == “ “: board[x-1][y-1] = “O” print “Computer Turn . . .” break Print_Board(board) winner = Check_Winner(board) if winner <> None: print “Game Over \n%s won the game . . . “ %winner break فهرست 4- ماجول اصليخطوط 4 و 5 و6 ماجولها و توابع مورد نظر را بارگذاری ميكنند. دستور import برای استفاده از ماجولها به کار میرود. این دستور برای یافتن ماجول مورد نظر نواحی خاصی از سیستم را جستوجو میکند. یکی از این نواحی پوشه یا فولدری است که فایل import کننده در آن قرار دارد. ناحیه دیگر کتابخانه استاندارد یا Standard Library است. دستور import به دو صورت قابل اجرا است. روش اول به شكل زير است: import <module> [,module ,module , . . .] روش دوم نيز مطابق نمونه زير است: from <module name> import <function|variable|class> [,function|variable|class, . . .] تفاوت این دو حالت در این است که روش نخست خود ماجول را به صورت یک موجوديت وارد اسکریپت فعلی میکند و برای استفاده از اجزای آن باید از سیستم نقطهگذاری استفاده کرد. نظیر آنچه در خط 21 و دستور random.randint() دیده میشود. اما در حالت دوم بخش مورد نظر به طور مستقيم وارد اسکریپت فعلی شده و بدون نام بردن ماجول مادر آن قابل استفاده است. همانند خط 11 که در آن Print_Board() که از ماجول board وارد شده بود، به طور مستقيم مورد استفاده قرار گرفته است. در خط 4، random که یکی از کتابخانههای استاندارد پایتون است، بارگذاری میشود. همانطور که قبلاً گفته شد، کتابخانه استاندارد پایتون طیف وسیعی از کاربردها را بهسادگی برای کاربر فراهم ميكند. کتابخانه random توابعی در زمینه کار با اعداد تصادفی فراهم کرده است. سه خط نخست بخش اصلی، نام بازیکن را پرسیده و پس از خوشامدگویی، صفحه بازی را ایجاد و چاپ میکند. پس از آن حلقه بازی شروع میشود. این حلقه در خطوط 15 تا 18 و خطوط 28 تا 31 درصورت برنده شدن یک بازیکن یا پرشدن صفحه شکسته میشود. در این حلقه به ترتیب در خط 13 بازیکن از طریق تابع Play_One_Turn() یک نوبت بازی میکند. سپس در خطبعدی صفحه بازی چاپ شده و وجود یا عدم وجود برنده بررسي میشود. سپس نوبت به کامپیوتر میرسد که با یک حلقه while و استفاده از اعداد تصادفی سعی میکند، یک خانه صفحه را انتخاب کند. تابع randint() که در کتابخانه random تعریف شده است، با گرفتن دو عدد صحیح، یک عدد صحیح تصادفی بین آن دو (یا مساوی یکی از آنها) تولید خواهد کرد. پس از خروج از این حلقه، صفحه بازی دوباره چاپ شده، برنده کنترل میشود و حلقه اصلی از نو شروع به کار خواهد کرد. اگرچه این برنامه چندان کاربردی نبود و در بسیاری از قسمتها میتوان آن را به گونهای بهتر پیاده سازی کرد، اما حاوی نكتههاي بسیار مهمی درباره کار با زبان پایتون است. اگرچه کل کدهای این مقاله از سایت مجله قابل دریافت است، اما توصیه میکنيم دستكم یک بار آنها را تایپ کنید تا با خطاهای احتمالی حین تایپ و رفع اشکال برنامه نیز آشنا شوید. در قسمت بعدی با بخشهایی پرکاربرد از کتابخانه استاندارد پایتون آشنا خواهید شد و برنامه قسمت بعد، استفاده مفیدتر و جالبتری از چرخههای پردازنده شما خواهد کرد. پی نوشت: 1- در نوشتن فرم کلی دستورات علامت < > به معنای اجباری، [ ] به معنای اختیاری و علامت | به معنای یا است.
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون احمد شریف پور اشاره: انسان ناخودآگاه و به شیوهای نوستالژیک سعی دارد پدیدههای تازه اطرافش را به موارد شناخته شده ربط داده یا تبدیل کند و آنها را بر اساس قوانین شناخته شده توضیح دهد. به عنوان مثال، اتومبيلها را با صفاتی مانند خشمگین، هیولا و.... بخواند، برنامههای مخرب کامپیوتری را ویروس بنامد و حتی در برنامهنویسی سعی کند همهچیز یک برنامه را به شیء تبدیل کند. گویی در این دنیای صفر و یکی هم مانند زندگی روزمره با خردهریزهای فیزیکی سروکار دارد. انسان ناخود آگاه و به شیوهای نوستالژیک سعی دارد پدیدههای تازه اطرافش را به موارد شناخته شده ربط داده یا تبدیل کند و آنها را بر اساس قوانین شناخته شده توضیح دهد. به عنوان مثال، اتومبيلها را با صفاتی مانند خشمگین، هیولا و.... بخواند، برنامههای مخرب کامپیوتری را ویروس بنامد و حتی در برنامهنویسی سعی کند همهچیز یک برنامه را به شیء تبدیل کند. گویی در این دنیای صفر و یکی هم مانند زندگی روزمره با خردهریزهای فیزیکی سروکار دارد. بیشتر شما به یقین اصطلاح برنامه نویسی شیءگرا یا OOP (سرنام Object Oriented Programming) را شنیدهاید. این اصطلاح بهطورمعمول در برابر اصطلاح برنامهنویسی تابعگرا یا Functional مطرح میشود و به نوعی از برنامهنویسی اشاره دارد که بهصورت خلاصه سعی دارد مجموعه دادههای دارای خواص و عملکرد یکسان را به عنوان یک نوعداده یا DataType طبقهبندی کرده و از این راه مدیریت کد را سادهتر کند. بهواسطه قولی که در قسمت پیشین داده بودیم، این شماره را به بررسی برنامهنویسی شیءگرا و بهویژه شیءگرایی در پایتون اختصاص دادهایم. میانه راه نكته جالب توجه اين كه شما استفاده از اشیا، کلاسها، متدها و خلاصه تمام جنبههای برنامهنویسی شیءگرا را زمانی که نخستین خط کد به زبان پایتون را نوشتهاید، شروع کردهاید. بنابراين، شما اکنون در میانه راه هستید! تمام اجزاي پایتون براساس سیستم شیءگرا نوشته شدهاند. در پایتون هرچیزی، حتی یک مقدار عددی نظیر 1,67 نیز یک شیء است. اما تمام این هیاهو بر سر چیست؟ کلاس و شیء چیستند؟ در تعاریف برنامهنویسی «شیء» مجموعهای از دادهها است که دارای تعدادی خصوصیت یا Attribute و تعدادی عملکرد یا Method است. خواص، نگهدارنده مشخصات و وضعیت شیء هستند و متدها، قابلیتها و عملیات ممکن روی یک شیء را نشان میدهند. کلاس نیز درواقع دستورالعمل ساخت یک شیء جدید است. اگر یک اتومبیل را به عنوان یک شیء در نظر بگیریم، دارای خصوصیاتی نظیر نام، مدل، حداکثر سرعت، تاریخ ساخت و... خواهد بود. عملیات استارت زدن، حرکت به جلو، ترمز گرفتن و... نیز متدهای این شیء به شمار میآیند. در این حالت مستندات و طرحهای موجود در کارخانه، که اتومبیل از روی آنها ساخته میشود، کلاس این شیء خواهد بود. به خط فرمان پایتون بروید و متغیر s را برابر “ABCD” (به بزرگ بودن تمام حروف دقت کنید) تعریف کنید. میدانید که این متغیر از نوع رشته خواهد بود. بهصورت دقیقتر s يك شیء (Object) از نوع (Class) رشته شكل 1 class Point: x=0 y=0 p1= Point() p2= Point() p1.x=7 p2.x=9 p1.name = “Start Point” print p1.x , p2.x print p1.name print p1 فهرست 1است. دستور (dir(s را تایپ کنید. همانگونه که در شکل 1 میبینید، فهرست تمام خواص و عملکردهای شیء s برای شما نمایش داده خواهد شد. برای استفاده از خواص و متدها، از نماد نقطهگذاری معمول استفاده میکنیم. تنها توجه داشته باشید که برای فراخوانی متدها به علامت () نیاز خواهیم داشت.. به عنوان نمونه دستور s.__doc__ را تایپ کنید. (علامت __ از دو زیر خط پیوسته تشکیل شده است). همانطور که میبینید این خاصیت توضیحات مربوط به شیء رشته را چاپ خواهد کرد. اکنون از دستور () s.isupper استفاده کنید. این یکی از متدهای شیء رشته است که اگر تمام حروف رشته بزرگ باشند، مقدار True وگرنه False را بازخواهد گرداند. اگر این متد را بدون پرانتز فراخواني كنيد، پایتون تنها نوع و آدرس آن را برای شما نمایش خواهد داد. از() dir میتوان برای استخراج خواص و متدهای تمام اشيا، دادهها، توابع، ماجولها و... استفاده کرد. کاربرد استفاده از سیستم شیءگرا در برنامهها مزیتهای فراوانی را به همراه خواهد داشت. ابتدا اینکه اجزای برنامه به سیستم ادراکی روزمره ما نزدیکتر شده و به همین دلیل درک منطق برنامهنویسی در بسیاری موارد سادهتر از حالت تابعی (روشی که در برنامههای قسمتهای قبل بهکار میبردیم) خواهد بود. همچنین در این روش به دلیل پیادهسازی متدها و دادهها در خود شیء، نیاز به انتقال اطلاعات بین توابع مختلف و ارجاعهای متعدد از میان خواهد رفت و دیگر اینکه با فراهم شدن امکان ارثبری خصوصیات میان اشیا، پیاده سازی اشیا جدید و کلاسهای پیچیده راحتتر میشود. فرض کنید با برنامهای سروکار داریم که قرار است مشخصات و روابط هندسی میان تعدادی نقطه را پردازش و محاسبه كند. به مفهوم ریاضی نقطه فکر کنید که عبارت است از دو عدد (مختصات) که در مجموع به عنوان یک شیء واحد در نظر گرفته میشوند. در پیادهسازی برنامه و به عنوان یک راهحل ساده میتوانید مختصات نقاط را در یک توپل یا یک لیست قرار دهید. اگرچه این کار میتواند تا حدودی نیاز برنامه را برآورده کند، اما برای کار با دادههای زیاد، اصلاً مناسب نخواهد بود. بهترین کار تعریف یک نوع داده (Data Type) اختصاصی جدید برای کار با نقطه است. فهرست 1 را در ویرایشگر دلخواه خود وارد کرده، با نام Points01.py ذخیره کرده و آن را اجرا کنید. خروجی باید همانند شکل 2 باشد. شكل 2در خط اول با کلمه کلیدی class و سپس نام نوع داده جدید، آن را تعریف کردهایم. در خطوط بعدی، مختصات طول و عرض در داخل خود این کلاس تعریف شده و برابر صفر مقدار داده شدهاند. تعاریف کلاس بهطورمعمول در ابتدای برنامه و بعد از دستورات import آورده میشوند و رسم بر این است که نام کلاسهای جدید همواره با حروف بزرگ آغاز شوند. در خطوط 5 و 6 دو متغیر جدید از نوع نقطه تعریف شده و سپس مقدار x و y آنها دستکاری شده است. تعریف متغیر از یک نوع جدید را به اصطلاح وهلهسازی، نمونهسازی یا Instantiation مینامند. در خطوط 12 تا 14 مقادیر برخی خصوصیات این اشیا چاپ خواهد شد. همانگونه که در خط 10 مشاهده میکنید، به کمک نماد نقطهگذاری میتوان داده جدیدی (نظیر نام) را نیز به یک نمونه از یک کلاس اضافه کرد. اگر تلاش کنید تا خود شیء p1 را چاپ کنید، پایتون نوع یا کلاس سازنده آن را باز خواهد گرداند. به سادگی میتوان نمونههای یک شیء را همانند یک مقدار یا یک متغیر به یک تابع پاس کرد. فایل قبلی را همانند فهرست 2 ویرایش کرده و با نام Points02.py ذخیره کنید. پس از اجرای این کد خروجی برنامه همانند شکل 3 خواهد بود. class Point: x=0 y=0 #### Functions def PrintPoint(p): text=»Point at %d,%d» %(p.x,p.y) print text def MoveLeft(p,how_much): p.x = p.x - how_much def MoveRight(p,how_much): p.x = p.x + how_much #### Instantiation p1= Point() p1.x = 5 p1.y = 9 p2= Point() p2.x = -9 p2.y = 4 PrintPoint(p1) PrintPoint(p2) #### Moving points MoveLeft(p1,3) MoveRight(p2,10) #### Printing results print print “P1 after moving . . . “ PrintPoint(p1) print “P2 after moving . . . “ PrintPoint(p2) فهرست 2 در خط 5 تابعی تعریف کردهایم که یک نقطه را به عنوان ورودی گرفته و با استخراج مقادیر x و y، آن را در قالب بهتری نسبت به دستور print چاپ میکند. توابع Move Left و/ Move Right هم نقطه را در جهت X چپو راست ميكنند. توجه داشته باشید که تابع تعریف شده هیچ اطلاعی از نوع یا مقداری که در آینده به آن ارجاع خواهد شد ندارد و فعلاً برنامهنویس باید کنترل کند که آیا مقدار پاس شده با کارکرد تابع همخوانی دارد یا خیر. میتوانید برای امتحان یک مقدار عددی را به تابع پاس کنید و نتیجه را ببینید. همچنین در این قطعه کد توابعی تعریف شدهاند که نقطه را به اندازه مشخصی به چپ یا راست میبرند و نتیجه عملیات آنها توسط خطوط . . . . چاپ خواهد شد. کمی پیشرفتهتر اما همانگونه که از ابتدا گفتیم، یکی از مهمترین قابلیتهای شیءگرایی، انتقال توابع و محاسبات و اطلاعات به داخل خود شیء است. در واقع ما میتوانیم توابع تعریف شده در فهرست 2 را به داخل خود کلاس Point منتقل کنیم تا نیازی به پاس کردن نقطهها به توابع مختلف وجود نداشته باشد. فهرست3 را وارد کرده و با نام Points03.py ذخیره کنید. نتیجه اجرای این کد در شکل4 آورده شده است.class Point: def __init__(self,input_x,input_y): self.x = input_x self.y = input_y def PrintPoint(self): text=”Point at %d,%d” %(self.x,self.y) print text def MoveLeft(self,how_much): self.x = self.x - how_much def MoveRight(self,how_much): self.x = self.x + how_much #### Instantiation p1= Point(6,13) p2= Point(9,11) #### p1.PrintPoint() p2.PrintPoint() #### Moving points p1.MoveLeft(3) p2.MoveRight(10) #### Printing results print print “P1 after moving . . . “ p1.PrintPoint() print “P2 after moving . . . “ p2.PrintPoint() فهرست 3در این تعریف جدید از کلاس Point توابع مورد نیاز برای دستکاری یک نقطه به داخل خود کلاس منتقل شدهاند. در خط2 شما یکی از اساسیترین توابع یک کلاس یعنی __init__ را مشاهده میکنید. هربار که نمونه جدیدی از یک کلاس ساخته میشود، این تابع اجرا خواهد شد. اگر نمونههای شما در همان هنگام ساخت احتیاج به مقداردهی اولیه یا تنظیم برخی ویژگیها داشته باشند، محل انجام تمام این عملیات بدنه تابع __init__ است. به خاطر داشته باشید که معرفی آرگومانهای تابع __init__ (به جز self) در هنگام ایجاد یک نمونه جدید از کلاس الزامی است. (خطوط 13 و 14 را ببينيد)با این سیستم انتقال توابع به داخل کلاس، خطوط 13 تا 19 از فهرست 2 به سادگی به خطوطي شبيه 13 و 14 از فهرست 3 تبدیل میشود. نکتهای که به یقین توجه شما را جلب کرده، آرگومانی به نام self است. این آرگومان همواره به خود شیء اشاره میکند. اگرچه این آرگومان باید در تمام توابع موجود در کلاس آورده شود، اما هنگام فراخوانی این توابع، به وارد کردن آن نيازي نیست و پایتون بهصورت خودكار، خود شیء را به تابع ارسال میکند. از کلمه self در تمام قسمتهای تعریف یک کلاس برای ارجاع به خود شیء استفاده میشود. تابع خاص دیگری که در این کد وجود دارد __str__ است که تنها آرگومان آن هم خود شیء، یعنی self است. همانگونه که در ابتدای بحث اشاره شد، پایتون زبانی کاملاً شیء گراست و تمام اجزای آن در حقیقت شیء هستند. هنگامی که شما شیء، متغیر یا عبارتی را در برابر کلمه کلیدی print قرار میدهید، پایتون در واقع تنها متد __str__ آن شیء را فراخوانی میکند. بنابراین، به جای تعریف یک تابع مستقل PrintPoint با تعریف __str__ میتوانیم رفتار دستور print را برای شیء موردنظرمان يعني نقطه، به دلخواه تغییر دهیم. به همین ترتيب، ما در انتهای کد به سادگی از کلمه کلیدی print استفاده کردهایم که درواقع مقدار برگشتی تابع __str__ را نمایش خواهد داد. سایر توابع با همان فرمت قبل و فقط با افزوده شدن یک آرگومان self مورد استفاده قرار گرفتهاند. به خاطر داشته باشید که پس از این کار، این توابع متعلق به شیء نقطه هستند و برای فراخوانی آنها باید از روش نشانهگذاری نقطهای استفاده کرد. بار اضافی برای انجام عملیات ریاضی نظیر جمع و ضرب هم میتوان مانند مثال قبلی توابعی جداگانه ایجاد کرد یا برای سادهتر شدن کار با اشیا میتوان عملگرهای معمول ریاضی را به گونهای تغییر داد که با اشیا نیز کار کنند. به عنوان مثال، اگر بخواهید عمل جمع بین دو شیء نقطه را برای پایتون تعریف کنید، کافی است تابعی با نام __add__ را مانند فهرست 4 در تعریف کلاس آن بگنجانید. در اینصورت هنگامی که پایتون با عبارتی نظیر p1+p2 روبهرو شود که در آن p1 و p2 هردو از جنس نقطه باشند، تنها متد (p1.__add__(p2 را اجرا خواهد کرد. این کار را باردهی اضافی عملگر یا Operator Overloading مینامند. برای باردهی اضافي تفریق، ضرب و تقسیم باید به ترتیب توابعی با نامهای __sub__ ، __mul__ و __div__ را در کلاس موردنظر پیاده کنیم. برای بررسی تساوی یا بزرگتر و کوچکتر بودن هم باید تابعی با نام __cmp__ را تعریف و تنظیم کرد. def __add__(self,Second_Point): result_x = self.x + Second_Point.x result_y = self.y + Second_Point.y return Point(result_x,result_y) فهرست 4اشیاي مرکب اشیا میتوانند در ترکیب با یکدیگر به ساخت اشیا جدید و پیچیدهتر کمک کنند. به عنوان مثال، اگر مدلسازی یک مستطیل مدنظر باشد، برای تعیین مشخصات آن میتوانیم از نقطه گوشه و طول اضلاع آن استفاده کنیم. در اینصورت کافی است کلاس Rectangle را ایجاد کنیم و برای نگهداری اطلاعات مربوط به گوشه مستطیل از یک شیء نقطه استفاده کنیم. کد فهرست 5 را تایپ، با نام Rectangle.py ذخیره و اجرا کنید. نتیجه خروجی باید همانند شکل 5 باشد. همانگونه که در خط 11 مشاهده میکنید، برای نگهداری نقطه گوشه مستطیل از یک شیء نقطه استفاده شده است. همینطور به خط 15 نیز توجه کنید که برای ساخت خروجی __str__ مستطیل تابع __str__ مربوط به نقطه گوشه هم فراخوانده شده است. class Point: def __init__(self,input_x,input_y): self.x = input_x self.y = input_y def __str__(self): text=»Point at %d,%d» %(self.x,self.y) return text class Rectangle: def __init__(self,x,y,w,h): self.corner = Point(x,y) self.width = w self.height = h def __str__(self): text = “Rectangle corner is %s” %self. corner.__str__() text += “\nWidth = %d \t Height = %d” %(self. width , self.height) return text r1= Rectangle(2,3,10,12) print “r1 is:\n” , r1 r2=r1 print “r2 is: \n” , r2 r2.width = 40 print “\nr2 changed to \n” , r2 print “\nr1 changed too !! \n” , r1 فهرست 5نکتهای که همیشه باید درباره اشیا به یاد داشته باشید این است که استفاده از علامت مساوی برای انتساب یک شیء به شیء دیگر، درواقع به محل آن شیء در حافظه ارجاع میدهد. به عبارت دیگر، در خط شماره 22 r2 مستطیلی جداگانه نیست، بلکه دقیقاً به همان محل نگهداری r1 در حافظه اشاره میکند و بنابراین، هر تغییری در r2 یا r1 (همانند خط شماره 24) به هردوی آنها اعمال میشود. برای تهیه کپیهای مجزا از اشیا، باید از ماجولی به نام copy استفاده کنیم. این ماجول دو متد بسیار پرکاربرد دارد؛ یکی متد copy و دیگری متد deepcopy. تفاوت این دو متد در هنگام برخورد با اشیا جاسازی شده در یک شیء مرکب مشخص میشود. به شکل 6 توجه کنید شكل 6این دیاگرام وضعیت r1 و r2 را در حالتهای مختلف نشان میدهد. همانگونه که مشاهده میکنید با استفاده از عبارت r2=r1 به طور عملي شیء جدیدی ایجاد نخواهد شد، بلکه شیء r2 تنها به محل r1 در حافظه اشاره خواهد کرد. در صورت استفاده از متد ()copy.copy اگرچه r2 یک شیء جدید خواهد شد، اما همانند r1 برای نگهداری نقطه گوشه همچنان به محل شیء p1 در حافظه اشاره خواهد کرد. يعني اشيا داخل شيء اصلي كپي نميشوند.بنابراین، تغییر گوشه مستطیل r2 باعث تغییر r1 هم خواهد شد و برعكس. اما استفاده از متد() copy.deepcopy نه تنها خود شیء که تمام ارجاعات و اشیا موجود در آن را نیز بهصورت مستقل کپی خواهد کرد. class Point: def __init__(self,input_x,input_y): self.x = input_x self.y = input_y def __str__(self): text=”Point at %d,%d” %(self.x,self.y) return text def MoveLeft(self,how_much): self.x = self.x - how_much def MoveRight(self,how_much): self.x = self.x + how_much class NewPoint(Point): def MoveUp(self,how_much): self.y = self.y + how_much p=NewPoint(5,6) print p ,”\n” p.MoveLeft(2) print p ,”<-- Moved left\n” p.MoveUp(5) print p ,’’<-- Moved Up\n” فهرست 6 ارثبری خصوصیات هر شیء در پایتون میتواند والد شیء دیگری باشد و تمام یا برخی خصوصیات خود را برای این شیء جدید به ارث بگذارد. برای درک این موضوع کد فهرست 6 را تایپ کرده و با نام Points05.py ذخیره و اجرا کنید. خروجی این قطعه کد باید همانند شکل 7 باشد. توجه کنید که همه اشیا، حتی آنهاییکه خود شما بهصورت مستقل ایجاد میکنید، در نهایت فرزند يك شيء مادر به نام object هستند و خصوصیاتی نظیر __doc__ و __module__ را از آن به ارث میبرند. در واقع object والد تمام اشیا پایتون است. همانگونه که در خط 12 مشاهده میکنید، برای مشخص کردن والد یک کلاس جدید کافی است نام کلاس والد را پس از نام کلاس جدید در یک پرانتز ذکر کنید. در این مثال کلاس NewPoint تمام خصوصیات و متدهای کلاس Point (همانند MoveLeft) را به ارث برده است. این کلاس متد جدیدی (MoveUp) دارد که والد آن، یعنی Point فاقد آن است. اگر قصد تغییر یکی از متدهای کلاس والد را در این کلاس جدید دارید، کافی است آن متد را بازنویسی کنید. در قسمت بعدی به کمک سیستم شیء گرا و نرمافزار Boa Constructor به سراغ ساخت برنامههای گرافیکی خواهیم رفت.
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون آشنايي و كار با زبان برنامه نويسي پايتون (قسمت پنجم) اشاره: بسیاری از کاربران معمول کامپیوتر، بهویژه تازهواردان دنیای لینوکس، به خط فرمان به دیده امری عجیب و ترسناک مینگرند که به کارگیری آن و تسلط بر آن تنها از عهده خبرگان و کهنهکاران دنیای کامپیوتر برمیآید. این کاربران و حتی بسیاری از استفادهکنندگان حرفهای کامپیوتر ترجیح میدهند به جای تایپ دستورات و تعامل از طریق «متن»، دکمهای را کلیک كرده، اسلایدری را جابهجا كرده یا پنجرهای را باز و بسته کنند. به عبارت سادهتر آنها ترجیح میدهند که با یک رابط بصری سروکار داشته باشند تا یک رابط متنی. آنها GUI (سرنام Graphical User Interface) را بیشتر میپسندند. به همین دلیل نحوه پیادهسازی GUI از طریق زبان پایتون را بررسی میکنیم. بسیاری از کاربران معمول کامپیوتر، بهویژه تازهواردان دنیای لینوکس، به خط فرمان به دیده امری عجیب و ترسناک مینگرند که به کارگیری آن و تسلط بر آن تنها از عهده خبرگان و کهنهکاران دنیای کامپیوتر برمیآید. این کاربران و حتی بسیاری از استفادهکنندگان حرفهای کامپیوتر ترجیح میدهند به جای تایپ دستورات و تعامل از طریق «متن»، دکمهای را کلیک كرده، اسلایدری را جابهجا كرده یا پنجرهای را باز و بسته کنند. به عبارت سادهتر آنها ترجیح میدهند که با یک رابط بصری سروکار داشته باشند تا یک رابط متنی. آنها GUI (سرنام Graphical User Interface) را بیشتر میپسندند. به همین دلیل و بر اساس وعدهای که در شماره پیشین داده بودیم، نحوه پیادهسازی GUI از طریق زبان پایتون را بررسی میکنیم. کدام جعبه ابزار؟ برای ایجاد رابطهای گرافیکی در پایتون، گزینههای متعددی وجود دارد که با توجه به سکوی مورد استفاده، محیط گرافیکی موردنظر و حتی کاربرد مورد نیاز میتوانید از بین آنها گزینه مناسب را انتخاب کنید. در ادامه چند نمونه از Toolkit یا جعبه ابزارهای مشهور ساخت رابط بصری بر مبنای پایتون را معرفی میکنیم. TK Inter: سادهترین و در عین حال در دسترسترین جعبه ابزار ساخت رابطهای بصری است که به طورمعمول به همراه غالب بستههای پایتون و بهصورت پیشفرض نصب میشود. ویرایشگر IDLE بهوسیله همین ابزار ساخته شده، اما سادگی و ظاهر نه چندان زیبای آن، به کاهش علاقه به استفاده از این جعبه ابزار منجر شده است. PyGTK: این جعبه ابزار در واقع wrapper یا پوستهای است که به دور ابزار گرافیکی GTK+ پیچیده میشود تا آن را برای پایتون قابل استفاده سازد. ابزار GTK+ خود مادر تمام برنامهها و پنجرههای میزکار Gnome است و برنامههای ساخته شده با PyGTK هم دقیقاً ظاهری همانند برنامههای میزکار Gnome خواهد داشت. برای این جعبه ابزار IDE خاصی وجود ندارد، اما طراحی ظاهر برنامه و فرمهای آن برمبنای این جعبه ابزار (بدون امکان ویرایش یا ایجاد کد) توسط برنامههایی نظیر Glade و Gazpacho در میزکار Gnome امکانپذیر است. PyQt: این جعبه ابزار نیز wrapper یا پوستهای است که به دور ابزار گرافیکی Qt پیچیده میشود تا آن را برای پایتون قابل استفاده سازد. ابزار Qt ابزاری است که کل میزکار KDE بر مبنای آن بنا شده است و برنامههای تولید شده با PyQT نیز دقیقاً ظاهری همانند برنامههای میزکار KDE خواهد داشت. برای کار با این جعبه ابزار میتوانید از IDE قدرتمند eric در میزکار KDE استفاده کنید. wxPython: این جعبه ابزار براساس wxWidget (یا wxWindows) ساخته شده است و یکی از قدرتمندترين جعبه ابزارهای طراحی رابط بصری است. مهمترین مزیت آن مستقل بودن از پلتفرم و ظاهر بومی برنامههای تولید شده با آن است. IDE قدرتمند Boa Constructor یکی از بهترین گزینهها برای توسعه رابط بصری کاربر با زبان پایتون است که در مطالب این قسمت و قسمت بعدی نیز از همین برنامه استفاده خواهد شد. برای مقایسه سریع آنها میتوانید به جدول 1 مراجعه کنید. [TABLE="class: cms_table"] [TR] [TD="width: 92"]نام ToolKit[/TD] [TD="width: 302"]مزایا[/TD] [TD="width: 300"]معایب[/TD] [/TR] [TR] [TD="width: 92"]TkInter[/TD] [TD="width: 302"]به همراه غالب نسخههای پایتون نصب ميشود و توسعه رابط بصری با آن بسیار ساده است.[/TD] [TD="width: 300"]تعداد ابزارکها یا ویجتهای آن کمتر از سایر بستهها است. رابطهای حاصل از آن زیبایی چندانی ندارد.[/TD] [/TR] [TR] [TD="width: 92"]PyGTK[/TD] [TD="width: 302"]براساس کتابخانه توابع GTK+ نوشته شده و برای توسعه در محیطهایی نظیر Gnome بسیار مناسب است. ابزارهای مناسب زیادی برای طراحی رابط بصری با استفاده از آن وجود دارد. ظاهر آن همانند تمام برنامههای GTK است.[/TD] [TD="width: 300"]علاوه بر پایتون، به نصب بسته PyGTK و ابزارهای مرتبط با آن نياز دارد. ظاهر رابطهای ساخته شده با آن، با محیطهایی نظیر KDE چندان همخوان نیست.[/TD] [/TR] [TR] [TD="width: 92"]PyQt[/TD] [TD="width: 302"]براساس کتابخانه توابع Qt نوشته شده و برای توسعه در محیط KDE بسیار مناسب است. یک IDE تمام عیار با نام Eric برای آن موجود است.[/TD] [TD="width: 300"]علاوه بر پایتون، به نصب بسته PyQt و ابزارهای مرتبط با آن نياز دارد. ظاهر رابطهای ساخته شده با آن، با محیطهایی نظیر Gnome چندان همخوان نیست.[/TD] [/TR] [TR] [TD="width: 92"]wxPython[/TD] [TD="width: 302"]براساس کتابخانه WxWindow نوشته شده، کاملاً روی تمام پلتفرمهای ویندوز و لینوکس پشتیبانی میشود. در تمام محیطها ظاهر آن همانند نرمافزارهای بومی همان پلتفرم دیده خواهد شد. در لینوکس یک IDE مناسب به نام Boa Constructor دارد.[/TD] [TD="width: 300"]علاوه بر پایتون، به نصب بسته WxPython و ابزارهای مرتبط با آن نياز دارد. پیادهسازی اجزای رابط کاربر بیش از سایر ابزارها به کدنویسی نياز دارد.[/TD] [/TR] [/TABLE] نصب ابزارها همانطور که گفته شد، برای ادامه این مبحث به Boa Constructor و WxPython نياز خواهیم داشت. برای نصب آنها به Software Center اوبونتو رفته و از طریق بخشهای Developer Tools و پس از آن Graphic Interface Design نرمافزار Boa Constructor را نصب کنید. معمولاً انتخاب این بسته برای نصب، به نصب خود به خود WxPython نیز منجر خواهد شد. همچنین میتوانید در خط فرمان دستورات زیر را تایپ کنید: sudo apt-get install wxpython sudo apt-get install boa-constructor در هر دو حالت پس از وارد کردن گذرواژه سیستم، دانلود و نصب نرمافزارها آغاز خواهد شد. پس از اتمام کار نصب از طریق منوی Application، سپس گزینه Programming برنامه Boa Constructor را اجرا کنید. ظاهر برنامه پس از اجرا همانند شکل 1 خواهد بود.همانگونه که مشاهده میکنید این برنامه از سه پنجره یا به اصطلاح فریم تشکیل شده است. قاب یا فریم بالایی قاب ابزار یا Tool Frame نامیده میشود. قاب سمت چپ پایینی، قاب بازرسی یا Inspector Frame و قاب سمت راست پایین، قاب ویرایشگر یا Editor Frame است. قاب ابزار زبانههای متعددی نظیر مانند New، Container/Layout و... دارد. از این قاب میتوانید برای ایجاد پروژههای جدید، افزودن قاب یا پنجره به پروژههای موجود یا افزودن کنترلهای مختلف به قابها استفاده کنید. قاب بازرسی پس از افزودن قابها و کنترلهای مختلف به پروژه بسیار مورد استفاده قرار خواهد گرفت. بهصورت معمول این قاب ساختار درختی و روابط بین کنترلهای مختلف را به ما نشان خواهد داد و در نهایت قاب ویرایشگر، امکان ویرایش کد، ذخیره پروژه و کارهایی از این قبیل را فراهم خواهد کرد. برای شروع کار ما ابتدا به سراغ قاب ابزارها خواهیم رفت. در زبانه New گزینههای مختلفی برای شروع کار وجود دارد اما در این بخش ما تنها از دکمههای پنجم و ششم، یعنی wx.App و wx.Frame استفاده خواهیم کرد. آیتم نخست، یعنی wx.App امکان ساخت یک پروژه کامل را فراهم میکند که از دو فایل Frame و Application تشکیل شده است و خود این دو فایل را نیز بهصورت خودكار تولید میکند. دکمه دوم یا wx.Frame امکان افزودن یک فرم به پروژه موجود را فراهم میکند. پر كاربردترين ابزارها در زبانه دوم یا Container/Layout ابزار wx.Panel (اولین آیتم از سمت چپ) و انواع مختلف کنترل کننده اندازه یا Sizer (دکمههای دوم تا ششم از سمت راست) هستند. در زبانه Basic Controls شما کنترلهای متداول نظیر جعبه متن، جعبه چک، کنترلهای لیست و... را مشاهده خواهید کرد و زبانه Utilities نیز برای دسترسی به ابزارهای منو و تایمر مورد استفاده قرار خواهد گرفت. قبل از شروع کار با Boa لازم است به دو نکته کوچک، اما مهم توجه کنید. نخست اینکه برخی کنترلها در پنجره طراحی یا Designer قابل جابهجایی نیستند. در صورت روبهرو شدن با چنین مشکلی، پس از انتخاب آنها از ترکیب کلیدهای Ctrl و جهتنما برای حرکت دادن آنها استفاده کنید. نکته دیگر اینکه هنگام قرار دادن یک کنترل از جنس panel روی یک فریم، پنل به سادگی دیده نخواهد شد. در اینصورت به دنبال مربعهای کوچک سیاه رنگی روی فریم بگردید یا از طریق قاب بازرسی و زبانه اشیا یا Objs این کنترل را انتخاب کنید. شروع کار برای مرحله اول، در قاب ابزار و در زبانه New دکمه wx.App را کلیک کنید تا یک پروژه جدید ایجاد شود. در این حالت دو برگه جدید یکی با نام *(App1)* دیگری با نام *(Frame1)* به قاب ویرایشگر شما اضافه خواهد شد. مناسبترین اقدام در این زمان ذخیره کردن پروژه ایجاد شده است. این کار را از برگه *(Frame1)* آغاز میکنیم. در قاب ویرایشگر، دکمه Save را بزنید و این فایل را در یک پوشه دلخواه با نام Frame1.py ذخیره کنید. همانطور که مشاهده میکنید نام برگه به Frame1 تغییر خواهد کرد. علامتهای *()* به معنای ذخیره نشدن تغییرات برگه جاری است. همین کار را برای برگه *(App1)* نیز انجام دهید. در قاب ویرایشگر به غیر از دکمه Save چندین دکمه مهم دیگر نیز وجود دارد که یکی از آنها دکمه Run Application (به شکل یک مثلث زرد رنگ) برای اجرای برنامه است. در حال حاضر، حتی بدون یک خط کدنویسی نیز برنامه شما قابل اجرا است. با زدن همین دکمه شما میتوانید نتیجه اجرای برنامه (که یک پنجره ساده و خالی است) را ببینید. در صورتیکه شما در حال ویرایش یک فایل مربوط به یک قاب یا فریم باشید (همانند Frame 1) دکمههای دیگری نیز به نوار ابزارها افزوده میشود که مهمترین آنها دکمه Frame Designer است. (برای یافتن نام هر یک از دکمهها، نشانگر ماوس را روی آنها برده و کمی صبر کنید(. فشردن این دکمه شمارا به حالت طراحی میبرد که در این وضعیت میتوانید ظاهر فرم موردنظر را به دلخواه و با استفاده از ابزارهای گرافیکی تغییر دهید. این دکمه را کلیک کنید تا با ظاهری همانند شکل 2 روبهرو شوید. فرم نمایش داده شده در واقع بستری است که میتوانید کنترلهای دلخواه خود را به آن اضافه کنید. نخستين آیتمی که باید به فرم اضافه کنید، یک کنترل از نوع پنل است. یک رسم نانوشته در توسعه رابطهای گرافیکی وجود دارد که شما را از قرار دادن مستقیم هر کنترلی بهجز پنل روی یک فریم منع میکند. پس در قاب ابزارها به برگه Container/Layout بروید. روی دکمه wx.Panel در محل دلخواهی از فریم کلیک کنید. اگر کار را به درستی انجام داده باشید، فریم 1 باید به صورت شکل 3 دارای تعدادی مربع سیاه رنگ کوچک باشد. همانطور که پیشتر هم هشدار داده بودیم، خطوط بدنه پنل دیده نمیشود و برای ویرایش و جابهجایی آن باید به دنبال این 8 مربع کوچک بگردید. برای تغییر اندازه پنل ميتوانيد از اين مربعها استفاده كنيد. در این تمرین ما میخواهیم پنل تمام سطح فریم را پوشش دهد. فریم را کمی کوچکتر و پنل را اندکی بزرگتر کنید تا پنل تمام سطح فریم را پوشش دهد. حال پنلی در اختیار داریم که سایر کنترلها روی آن قرار داده خواهند شد. اگر فریم را کمی جابه جا کنید، خواهید دید که دو دکمه جدید به نوار ابزار قاب ویرایشگر اضافه شده است. یکی به شکل یک تیک و با نام Post و دیگری به شکل ضربدر با نام Cancel. کلیک دکمه Post باعث میشود تا از حالت Design خارج شوید و تغییرات اعمال شده در فریم به صورت کدهای پایتون به فایل آن منتقل شود. البته هنوز وظیفه ذخیره کردن فایل به عهده خود شما است. دکمه Post دیگری هم روی قاب بازرسی دیده میشود که بعدها به آن خواهیم پرداخت. اگر Post را کلیک کردهاید، دوباره به حالت Design برگردید و در قاب ابزارها به برگه دکهها یا Buttons مراجعه کنید. روی نخستین دکمه سمت راست (wx.Button) کلیک و آن را جایی تقریباً در مرکز فریم قرار دهید.در این حالت فریم شما باید شبیه شكل 4 باشد. همانند پنل، 8 مربع کوچک برای تغییر اندازه دکمه در اطراف آن وجود دارد. اگر برای جابهجا کردن دکمه با مشکل مواجه شدید، براساس توضیح داده شده، از ترکیب کلیدهای Ctrl و جهتنما استفاده کنید. اكنون زمان آن رسیده که به سراغ قاب بازرسی برویم. در حالیکه کنترل دکمه در حالت انتخاب است، به سراغ این قاب و برگه Constr میرویم. در این قسمت میتوانید مشخصات و خواص کنترل انتخاب شده را ویرایش کنید. فعلاً نام کنترل دکمه را به btnShowDialog و برچسب یا Label آن را به Click Me! تغییر دهید. ظاهر برگه Constr باید همانند شکل 5 باشد. ما به بقیه تنظیمات این برگه کاری نداریم و به طور مستقيم به سراغ برگه Objs میرویم.در این برگه شما تمام کنترلهای استفاده شده و روابط والد و فرزندی آنها را مشاهده خواهید کرد. همانگونه که در شكل 6 مشاهده میکنید، کنترل دکمه فرزند پنل و پنل خود فرزند فریم است. با زدن دکمه Post در قاب بازرسی تغییرات را به فایل اعمال کرده و آن را ذخیره کنید. دوباره به حالت Design بازگشته و به برگه Objs از قاب بازرسی مراجعه کنید. اگر فریم انتخاب نشده است آن را انتخاب کرده و به زبانه Constr بروید. در آنجا عنوان فریم را به My First GUI تغییر دهید. تغییرات را Post کرده، سپس فایل را ذخیره کنید.در ادامه با استفاده از مثلث زرد رنگ Run Application برنامه را اجرا کنید. فرمی همانند شکل 7 ظاهر خواهد شد، اما کلیک دکمه روی فرمی هیچ عکسالعملی ایجاد نخواهد کرد، زیرا ما هنوز هیچ عملکردی را به آن دکمه نسبت ندادهایم. برای این کار ما باید یک رویداد یا Event را تعریف کرده و به دکمه نسبت بدهیم. پنجره فعلی را بسته و دوباره به حالت Design بروید. پس از کلیک و انتخاب دکمه به برگه Evts در قاب بازرسی مراجعه کنید. از لیست سمت چپ ButtonEvent را انتخاب کرده و از لیست سمت راست wx.EVT_BUTTON را دوباره کلیک کنید. همانگونه که در شكل 8 مشاهده میکنید، در زیر پنجره رویدادی با نام OnBtnShowDialog ساخته شده است. تغییرات را Post و ذخیره کنید. در پایینترین قسمت قاب ویرایشگر باید تابعی با نام OnBtnShowDialog ساخته شده باشد. کاری که اکنون میخواهیم انجام دهیم، فراخوانی یک جعبه متن یا MessageBox است که متنی را برای ما به نمایش درآورد. در اینجا ما از تابع داخلی wx.MessageBox استفاده میکنیم. در قاب ویرایشگر خط زیر را جایگزین event.Skip() کنید: wx.MessageBox(“You clicked the button !” , “Info”,wx.ICON_QUESTION) تغییرات را ذخیره کرده و با مثلث زردرنگ برنامه را اجرا کنید. این بار کلیک دکمه وسط فرم باید پیغامی همانند شكل 9 را به نمایش درآورد. توجه کنید که آیکون علامت سؤال ممکن است با توجه به تنظیمات ظاهر سیستم شما شکل متفاوتی داشته باشد. در تابع MessageBox سه آرگومان وارد شده به ترتیب عبارتند از، متن پیغام، عنوان پنجره پیغام و نوع آیکون مورد استفاده. برای تنظیم آیکون گزینههای دیگری نظیر wx.ICON_EXCLAMATION ، wx.ICON_INFORMATION و wx.ICON_ERROR را نیز در اختیار دارید که میتوانید آنها را نیز به سادگی امتحان کنید. این مثال در عین سادگی، نخستین برنامه کامل شما بر مبنای یک رابط بصری بود. در قسمت بعدی بیشتر با امکانات wxPython و Boa Constructor آشنا خواهیم شد و نمونههای پیچیدهتری را پیاده خواهیم کرد.
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون آشنايي و كار با زبان برنامهنويسي پايتون (قسمت ششم) احمد شریف پور اشاره: در مقاله قسمت قبلي برنامهای ایجاد کردیم که با کلیک یک دکمه، یک پیغام را به نمایش در میآورد. امیدواریم که تا انتشار این شماره، فرصت کافی را برای کار با Boa-Constructor پيدا كرده باشيد. در این شماره میخواهیم سیستم کار با برنامههایی را یاد بگیریم که از چندین پنجره یا به اصطلاح فریم مجزا و مستقل استفاده میکنند. هرچند برنامه این قسمت تنها از دو فریم استفاده میکند و کار پیچیدهای انجام نمیدهد، اما اصول ساخت فریمهای جدید و برقراری ارتباط بین آنها را به شما آموزش خواهد داد. در مقاله قسمت قبلي برنامهای ایجاد کردیم که با کلیک یک دکمه، یک پیغام را به نمایش در میآورد. امیدواریم که تا انتشار این شماره، فرصت کافی را برای کار با Boa-Constructor پيدا كرده باشيد. در این شماره میخواهیم سیستم کار با برنامههایی را یاد بگیریم که از چندین پنجره یا به اصطلاح فریم مجزا و مستقل استفاده میکنند. هرچند برنامه این قسمت تنها از دو فریم استفاده میکند و کار پیچیدهای انجام نمیدهد، اما اصول ساخت فریمهای جدید و برقراری ارتباط بین آنها را به شما آموزش خواهد داد. شروع برنامه Boa Constructor را اجرا کنید و در قاب Editor تمام زبانهها بهجز Shell و اكسپلورر را با استفاده از ترکیبکلیدهای CTRL + W ببندید. با این کار مطمئن میشویم، کار را از پایه و روی فایلهای تازه شروع کردهایم. حال با کلیک دکمه wx.App یک پروژه جدید بسازید. در صورت نیاز به راهنمايي به مقاله شماره قبل مراجعه کنید. پیش از هر کار دیگری، Frame1 را با نام FrameMain.py و App1 را با نام Gui2.py ذخیره کنید. در حالیکه زبانه GUI2 در قاب Editor انتخاب شده است، به نوار ابزارها مراجعه کنید و در زبانه New و با کلیک دکمه wx.Frame که درست در کنار wx.App قرار گرفته است، یک قاب یا پنجره دیگر به پروژه اضافه کنید. اطمینان حاصل کنید که زبانه Application در زیر ستون Module همانند شکل1 هر دو فریم را نمایش میدهد. شكل 1- افزودن فريم به برنامه پايتونحال به فریم جدید مراجعه كرده و آن را با نامFrameSecond.py ذخیره کنید. سپس FrameMain را در Designer باز کنید و از زبانه Container/Layout در قاب اصلی، یک wx.Panel به آن اضافه کنید. اندازه آن را طوری تنظیم کنید که تمام فریم را بپوشاند. حال باید برخی از خصوصیات فریم را دستکاری کنیم. در قاب Inspector و در زبانه Objs شیء Frame را انتخاب کنید و در زبانه Constr مقدار title را به Main Frame تبدیل کنید. در انتهاي مقاله درباره قوانین نامگذاری صحبت خواهیم کرد. با کلیک علامت تیک آیتم Size اندازه فریم را به 400x340 تغییردهید. با کلیک روی این علامت، لیستی باز میشود که در آن مقدار Height باید برابر 340 و مقدار Width برابر چهارصد تنظیم شود (به شكل 2 دقت کنید). شكل 2- تنظيم اندازه فريمحال زبانه Props را کلیک كرده و مقدار خاصیت Centered را به wx.BOTH تنظیم کنید. دکمه Post را (شکل یک تیک که تغییرات انجام شده را به فایل اصلی اعمال میکرد) کلیک كرده و کل پروژه را ذخیره کنید. حال با کلیک دکمه زردرنگ مثلثی برنامه را اجرا کنید. فریم اصلی برنامه ما باید درست در وسط صفحه نمایش و با عنوان Main Frame ظاهر شود. فعلاً برنامه را با کلیک دکمه Close در قسمت بالا و سمت راست پنجره ببندید. دوباره فریم Main Frame را در Designer باز کنید. از زبانه Buttons قاب اصلی، دو دکمه wx.Button را به فریم اضافه کنید، به گونهای که يكي در نزدیکی مرکز فریم و یکی بالای دیگری قرار بگیرند. دکمه بالایی را انتخاب كرده و با استفاده از قاب Inspector و زبانه Constr نام آن را به btnShowNew و خاصیت Label آن را به «Show the other frame» تنظیم کنید. با استفاده از ترکیب کلیدهای Shift و کلیدهای جهتنما، اندازه دکمه را به گونهای تنظیم کنید که تمام نوشته Label آن قابل رؤیت باشد، سپس از ترکیب CTRL و کلیدهای جهتنما برای بازگرداندن آن به مرکز فریم استفاده کنید. حال دکمه پایینی را انتخاب كرده و همانند دکمه قبلی نام آن را btnExit و Label آن را برابر Exit تنظیم کنید. تغییرات را با دکمه Post (که آیکون آن شبیه یک تیک است) به فایلهای محتوای کد ارسال كرده و برای مشاهده تغییرات برنامه را دوباره اجرا کنید. ظاهر برنامه شما باید همانند شکل 3 باشد. اکنون برنامه را ببندید. شكل 3- فريم اصلي برنامه رویدادها به احتمال برای شما هم تعجبی نداشته است که دکمه Exit هنوز کار نمیکند و عملیات بستن برنامه را باید با دکمه Close نوار عنوان برنامه انجام دهید. غالب برنامههای مبتنی بر GUI از سیستم هدایت رویداد (Event Driven) استفاده میکنند. در این روش، برنامه بهصورت مداوم رویدادهای سیستم را نظیر کلیکها، ضربههای کلید، حرکات ماوس، تغییر زمان و... بررسی میکند و اگر با رویدادی مواجه شود که برای آن عملیاتی تعریف شده باشد، آن عملیات را به اجرا در خواهد آورد، پس دلیل کار نکردن دکمههای برنامه ما این است که هنوز عملکردی را به رویداد کلیک آنها نسبت ندادهایم. برای نسبت دادن عملکردهای مناسب به دکمهها، فریم اصلی برنامه را در Designer باز کرده، سپس دکمه بالایی را انتخاب کرده و در قاب Inspector به زبانه Evts مراجعه کنید. روی ButtonEvent کلیک کرده، سپس روی wx.EVT_BUTTON دوبار کلیک کنید. دقت کنید که اکنون در قسمت زیرین عبارت OnBtnShowNewButton ظاهر خواهد شد (شکل4). سپس این روال را برای دکمه Exit اجرا كرده و اطمینان حاصل کنید که عبارت OnBtnExitButton در قسمت زیرین بخش Evts قاب Inspector به نمایش درآمده است. تغییرات را Post کرده و فایلها را ذخیره کنید. پس از آن به قاب Editor رفته و به قسمت انتهایی کد مربوط به FarmeMain مراجعه کنید. شكل 4- افزودن رويداد كليك به يك دكمهدر اینصورت باید دو «متدي» را که به تازگی برای دکمهها ساختهاید، ببینید. اکنون زمان آن رسیده که به سراغ فریم دوم برویم. فریم FramwSecond را که در ابتدای کار ساخته بودید، در Designer باز كرده و نام آن را به FrameSecond و عنوان آن را به Second Frame تنظیم کنید. به احتمال دیگر میدانید که خاصیت Name اسمی است که ما در کدهایمان برای ارجاع به اشیا از آن استفاده میکنیم و Label یا Title عنوانی است که روی شیء و برای کاربر نمایش داده میشود. اندازه فریم را به 180 ×400 و وضعیت Centered را روی wx.BOTH تنظیم کنید. یک دکمه wx.BUTTON به فرم اضافه كرده و آن را در وسط قسمت پایینی فریم قرار دهید. نام این دکمه را به btnF***it و Label آن را به Exit تبدیل کنید و در نهایت مانند دکمههای قبلی، یک رویداد کلیک برای آن تعریف کنید. حال یک کنترل از نوع wx.StaticText به بخش بالایی فریم اضافه كرده و نام آن را به stHiThere و Label آن را به «Hi There . . . I›m the second frame !» تبدیل کنید. با مراجعه به زبانه Props و برداشتن تیک کنار Fonts فونت این برچسب متنی را به Sans با اندازه 14 و Weight آن را به wxBOLD تنظیم کنید. حال این نوشته را درست به وسط قسمت بالایی فریم ببرید. برای این کار میتوانید در قسمت Position از زبانه Constr با تنظیم مقادیر X و Y محل این متن را تعیین کنید. فریم شما باید همانند شکل 5 باشد. شكل 5- ظاهر فريم دوم اين برنامهچسباندن اجزا حال که ظاهر اجزاي مختلف برنامه را آماده کردهایم، زمان آن رسیده تا چسبی را که تمام این اجزا را به هم متصل میکند، بهوجود آوریم. در قاب Editor روی زبانه GUI2 کلیک کنید و در قسمت زیرین زبانه Source را انتخاب کنید. در زیر خطی که دستور Import FrameMain را در خود دارد، خطی دیگر با دستور import FrameSecond اضافه کنید. تغییرات را ذخیره كرده و حالا زبانه FrameMain را فعال کنید و در زیر خط محتوای دستور import wx شما نیز خط زیر را اضافه کنید: import FrameSecond اکنون کد را به سمت پایین پیمایش کنید تا خط زیر را بیابید. def __init__(self,parent): در زیر خط محتوای دستورم( self._init_ctrls(parent ، شما نیز خطی را با دستور زیر وارد كنيد. self.Fs=FrameSecond.FrameSecond(self) حال در زیر بخش تعریف توابع کلیک، یعنی def OnBtnShowNewButton(self,event) با قرار دادن یک علامت # دستور ()event.Skip را به کامنت تبدیل کنید و دو خط زیر را به ادامه آن بیافزایید. self.Fs.Show() self.Hide() در انتها و در قسمت مربوط به متد OnBtnExitButton دوباره دستور ()event.Skip را به کامنت تبدیل کرده و خط زیر را اضافه کنید: self.Close() چرا؟ اما تمام اینها برای چیست؟ در ابتدا ما باید اطمینان مییافتیم که برنامه ما «میداند» که ما قصد داریم از دو فرم استفاده کنیم و به همین دلیل بود که با دستور import هر دو فریم FrameMain و FrameSecond را در فایل GUI2 وارد کردیم. پس از آن دوباره با دستور import FrameSecond ارجاعی به فریم دوم را در کدهای FrameMain ایجاد کردیم تا بعدها بتوانیم از آن استفاده کنیم. به عبارت دیگر، میخواستیم FrameMain هم از وجود FrameSecond آگاه شود. در بخش _init_ ما برای راحتی کار، متغیری به نام Fs تعریف کردیم که محتوای فریم FrameSecond است. پس از آن و در متد مربوط به کلیک دکمه ShowNew را تعریف کردیم که در صورت کلیک شدن این دکمه، فریم دوم نمایش داده شده و فریم اول یا اصلی مخفی شود. در آخر هم تعیین کردیم که با کلیک دکمه Exit برنامه بسته شود. حال به سراغ کدهای فریم FrameSecond میرویم. تغییراتی که باید در این کدها اعمال شود به نسبت اندک است. در قسمت مربوط به متد __init__ خطی مانند زیر اضافه کنید: self.parent=parent این کار متغیری به نام parent ایجاد میکند که به فرم والد FrameSecond (فریمی که آن را صدا زده است) اشاره میکند. پس از آن در زیر متد مربوط به رویداد کلیک روي دکمه F***it دستور event.Skip() را به کامنت تبدیل کرده و دو خط زیر را اضافه کنید: self.parent.Show() self.Hide() حتماً به خاطر دارید که ما هنگام نمایش FrameSecond فریم اصلی، یعنی FrameMain را مخفی کردیم. به همین دلیل، هنگام بسته شدن FrameSecond باید دوباره FrameMain را (که با نام parent معرفی شده بود) دوباره به نمایش درآوریم. حال برنامه را اجرا کنید. اگر همه چیز به درستی پیش رفته باشد، شما باید بتوانید با کلیک دکمه btnShowNew فریم اصلی را مخفی و فریم دوم را ظاهر کنید و با کلیک دکمه Exit در فریم دوم، به حالت قبل بازگردید. دکمه Exit در فریم اول هم تمام برنامه را خواهد بست. قوانین نامگذاری پیشتر گفته بودیم که درباره قوانین نامگذاری بیشتر صحبت خواهیم کرد. با نامگذاری درست کنترلهای یک برنامه، کد شما خود به خود مستندسازی خواهد شد. به عبارت دیگر، با استفاده از نامهای درست درک سازوکار برنامه و عملکرد بخشهای مختلف آن برای سایر «افراد» (استفادهکنندگان، ویرایشکنندگان یا توسعه دهندگان همکار) سادهتر خواهد شد. اگر شما نامهای پیشفرض کنترلها نظیر StaticText1، button1 یا هر چیز دیگری را بپذیرید، در حین ساخت یک فرم پیچیده که شامل تعداد زیادی متن و دکمه و... است، به یقین با مشکل و سردرگمی مواجه خواهید شد. تازه این به شرطی است که شما تنها کسی باشید که با کد سروکار دارید. اگر کسی پس از شما قصد ادامه کار با این کد را داشته باشد، مشکل چندین برابر خواهد شد. بنابراین، پیشنهاد میشود که برای برطرف كردن این مشکل از نامگذاری دو قسمتی استفاده کنید. بخش اول، باید نوع کنترل را مشخص کند و بخش دوم بايد بهصورت خلاصه عملکرد آن را بیان کند. نامهایی که ما در این برنامه استفاده کردیم، نظیر btnExit یا FrameSecond نمونههایی از این سیستم هستند. دو بخش نامها میتوانند با یک “_” از یکدیگر جدا شوند یا تنها با کوچک و بزرگ نوشتن حروف اول هر بخش. براي كنترل درستي عملكردتان ميتوانيد كدهاي سه فايل Gui2.py و Framemain.py و FrameSecond.py را از سايت ماهنامه دريافت كنيد
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون برنامهنویسی به زبان پایتون (قسمت هفتم) احمد شریف پور اشاره: هرچند استفاده از سرویسهای مبتنی بر شبکههای کامپیوتری، اینترنت، سیستمهای اشتراک فایل و... پدیدههایی مدرن محسوب میشوند، اما ایده استفاده از منابع پردازشی و اطلاعاتی موجود در سایر کامپیوترهای یک شبکه، قدمتی به اندازه قدمت صنعت کامپیوتر دارد. نكته جالب توجه اينکه اصول انجام این کار نیز طی چندین دهه گذشته تغییر چندانی نکرده است. ایده برنامههای کلاینت/ سرور یکی از قدیمیترین روشهای انجام این کار است هرچند استفاده از سرویسهای مبتنی بر شبکههای کامپیوتری، اینترنت، سیستمهای اشتراک فایل و... پدیدههایی مدرن محسوب میشوند، اما ایده استفاده از منابع پردازشی و اطلاعاتی موجود در سایر کامپیوترهای یک شبکه، قدمتی به اندازه قدمت صنعت کامپیوتر دارد. نكته جالب توجه اينکه اصول انجام این کار نیز طی چندین دهه گذشته تغییر چندانی نکرده است. ایده برنامههای کلاینت/ سرور یکی از قدیمیترین روشهای انجام این کار است. برای شروع کار باید بدانیم که اصولاً یک برنامه کلاینت/ سرور چیست؟ برنامههای کلاینت/ سرور در واقع دو برنامه مجزا هستند که بهصورت همزمان اجرا شده و یکی از آنها (سرور) اطلاعات یا منابعی را در اختیار برنامه دیگر (کلاینت) قرار میدهد. این دو برنامه میتوانند در یک ماشین واحد اجرا شده یا در دو کامپیوتر مجزا در دو سوی متفاوت جهان به اجرا دربیایند. به زبان ساده، هر زمانی که شما از یک برنامه (یا یک رابط وب) برای دسترسی به منابع یا دادههای یک کامپیوتر یا یک برنامه دیگر استفادهمیکنید، در حال کار با یک سیستم کلاینت/سرور هستید. نمونه ملموس چنین سیستمی زمانی است که از طریق یک کارتخوان خرید میکنید. در این هنگام دستگاه کارتخوان به عنوان یک کلاینت (که قصد انجام کاری را دارد) از یک سو و کامپیوترهای بانک (که نگهدارنده اطلاعات و انجام دهنده کار است) به عنوان سرور از سوی دیگر وارد عمل میشوند تا فرآیند خرید شما را تکمیل کنند. اگرچه فرآیندهایی نظیر این، بسیار پیچیده و حساس هستند و ما نخواهیم توانست چنین برنامههای پیچیدهای را ایجاد کنیم، اما میتوانیم با مثالهای سادهتر اصول کلی کار را دریابیم. برای استفاده از یک سیستم کلاینت/ سرور ابتداییترین کار، اتصال از ماشین کلاینت به ماشین سرور است. ما این کار را از طریق یک پایپ (pipe) یا یک سوکت (socket) انجام میدهیم. اگر در دوران کودکی با قوطیهای خالی كنسرو، تلفن ساخته باشید، به سادگی میتوانید اصول این کار را درک کنید. در این تلفنها ارتباط بین دو قوطی خالی (سرور و کلاینت) از طریق یک رشته (اتصال یا connection) که به سوراخی در انتهای هر قوطی (سوکت) متصل است، برقرار میشود. ایده سوکتها و اتصال بین کلاینت و سرور دقیقاً به همین شکل است. کلاینت اتصال (connection) مستقیمی به سرور دارد که این اتصال به سوکت معینی با شماره پورت مشخص در سرور متصل میشود. برای ساختن برنامه کلاینت/ سرور خودمان، ابتدا از سرور شروع میکنیم. در نخستين و سادهترین تجربه ما، اتفاقاتی که در سرور رخ میدهد، در یک شبه کد ساده به صورت زیر خواهد بود: یک سوکت بساز نام ماشین میزبان سرور را بپرس یک پورت انتخاب کن سوکت را به كامپيوتر ميزبان در پورت مشخص متصل کن منتظر یک اتصال باش اگر اتصال برقرار شد: اتصال را قبول کن دریافت اتصال را اعلام کن اتصال را قطع کن کد واقعی چنین سروری در فهرست 1 آورده شده است. #!/usr/bin/env python #server1.py import socket soc=socket.socket() hostname=socket.gethostname() print “My hostname is “, hostname port =21005 soc.bind((hostname,port)) soc.listen(5) while True: con,address = soc.accept() print “I,m now connected to “ , address con.send(“Hello and Goodbye”) con.close() فهرست 1- سادهترين نمونه يك سروردر خط 3 ماجول سوکت را Import کردهایم، سپس یک سوکت ساختهایم. تابع ()socket که برای ساخت سوکت مورد استفاده قرار میگیرد، تعدادی آرگومان اختیاری دارد که کمی بعدتر به آن اشاره خواهیم کرد. پس از آن با کمک تابع ()gethostname نام ماشینی که این سرور را اجرا میکند، به دست آوردهایم. تابع ()bind که در خط 8 از آن استفاده کردهایم، آدرس و پورت موردنظر را به سوکت نسبت میدهد. در حالت پیشفرض (شبکههای مبتنی بر IPv4) آرگومان ورودی این تابع باید یک توپل دوتایی محتوای نام ماشین میزبان و شماره پورت (hostname,port) باشد. در انتها و در خط 9 با تابع ()listen در انتظار برقراری یک اتصال نشستهایم. سوکتی را که خود اقدام به برقراری ارتباط نمیکند و در انتظار اتصال سایر سوکتها میماند «سوکت گوش دهنده» یا Listener Socket مینامند. آرگومان تابع ()listen تعیین کننده حداکثر تعداد سوکتهای در صف انتظار برای اتصال به سوکت «گوش دهنده» است و بیشترین مقدار ممکن برای آن به سیستم مورد استفاده بستگی دارد. پس از آن سرور در یک حلقه بیپایان، در صورت برقراری اتصال آن را میپذیرد (خط 11)، دریافت اتصال را اعلام میکند (خط 12)، پیغامی را به کلاینت ارسال کرده (خط 13) و اتصال را قطع میکند (خط 14). همانطور که مشاهده میکنید، خروجی تابع ()accept یک توپل دوتایی محتوای شیء سوکت متقاضی اتصال (con) و آدرس آن (address) است. ما برای ارسال اطلاعات و قطع ارتباط به این دو نیاز خواهیم داشت. شكل 1- خروجي سرور شماره 1حال به یک کلاینت نیاز داریم تا پازل را تکمیل کند. در حالتی بسیار ساده این کلاینت همانند فهرست 2 خواهد بود. این کد کاملاً شبیه کدهای سرور است با این تفاوت که، در این جا، بهجای انتظار برای اتصال، سوکت ما اتصال را برقرار میکند و آنچه را که دریافت کرده است، چاپ کرده و اتصال را قطع میکند. #!/usr/bin/env python #clinet1.py import socket soc=socket.socket() hostname=socket.gethostname() port = 21005 soc.connect((hostname,port)) print soc.recv(1024) soc.close فهرست 2- سادهترين نمونه يك كلاينتبرخلاف سوکتهای گوشدهنده که باید توسط تابع ()bind به یک پورت یا آدرس بچسبند، سوکتهایی که قصد برقراری تماس را دارند، از تابع ()connect استفاده خواهند کرد. در خط 9 مشاهده میکنید که تابع ()connect نیز همانند تابع ()bind از یک توپل محتوای نام میزبان و شماره پورت برای برقراری اتصال استفاده میکند. در خط 10 نيزتابع ()recv نیز برای دریافت اطلاعات از اتصال برقرار شده مورد استفاده قرار میگیرد. در این تابع آرگومان داده شده اندازه بافر است که درواقع تعیینکننده حداکثر اندازه بلوک دادهای است که میتواند یکباره دریافت شود. این آرگومان برای هماهنگی بهتر با سختافزارها و پروتکلهای شبکه بهتر است توانی از 2 مثلاً 4096 باشد. توجه کنید که برای کار کردن این سیستم، باید هر دو برنامه به صورت همزمان به اجرا در بیایند. بنابراین، از دو پنجره مجزای کنسول یا دو نسخه مجزای محیط IDLE برای اجرای آنها استفاده کنید. همچنین توجه داشته باشید که اگر در یک برنامه سوکت را نبندید، پورت به کار رفته در آن حتی پس از بستن IDLE یا کنسول اجرا کننده، در اجراهای بعدی باز و قابل استفاده نخواهد بود. در چنین وضعیتی برای اجراهای بعدی، باید از اعداد پورت جدید، اما یکسان در هر دو سمت سرور و کلاینت استفاده کنید. خروجی این برنامهها کاملاً قابل پیشبینی است. در سمت سرور خروجی چیزی همانند شکل 1 و در سمت کلاینت فقط عبارت Hello and Goodbye خواهد بود ( نام ميزبان ياشماره IP در سیستم شما به احتمال زیاد متفاوت خواهد بود). همانطور که مشاهده کردید، پیادهسازی چنین نمونه محدودی بسیار ساده است. در مرحله بعدی قصد داریم سروری بسازیم که قادر به انجام کار مفیدی به جز سلام و خداحافظی باشد. کد این سرور را در فهرست 3 مشاهده میکنید. در خطوط 6 الی 9 و پس از import کردن ماجولهای مورد نظر (در قسمتهای بعدی درباره ماجولهای os و sys بیشتر صحبت خواهیم کرد)، تعدادی متغیر را برای استفادههای بعدی مقداردهی کردهایم. متغیر BUFSIZ اندازه بافر مورد استفاده را برای دریافت اطلاعات ورودی از سمت کلاینت تعیین میکند. همچنین ما پورتی را که روی آن به انتظار اتصال خواهیم بود، در خط 8 تعریف کردهایم و پس از آن توپلی را برای نگهداری نام کامپیوتر میزبان و شماره پورت بهوجود آوردهایم. #!/usr/bin/env python # server2.py from socket import * import sys import os BUFSIZ = 4096 HOST = ““ PORT = 29876 ADDR = (HOST,PORT) class ServCmd: def __init__(self): self.serv = socket(AF_INET,SOCK_STREAM) self.serv.bind((ADDR)) self.cli = None self.listeningloop = 0 self.processingloop = 0 self.run() def run(self): self.listeningloop = 1 while self.listeningloop: self.listen() self.processingloop = 1 while self.processingloop: self.procCmd() self.cli.close() self.serv.close() def listen(self): self.serv.listen(5) print “Listening for Client” cli,addr = self.serv.accept() self.cli = cli print “Connected to “, addr def procCmd(self): cmd = self.cli.recv(BUFSIZ) if not cmd: return print “Received command: “, cmd self.servCmd(cmd) if self.processingloop: proc = os.popen(cmd) outp = proc.read() if outp: self.cli.send(outp) else : self.cli.send(“OK”) def servCmd(self,cmd): cmd = cmd.strip() if cmd == “GOODBYE”: self.processingloop = 0 if __name__ == “__main__”: serv = ServCmd() فهرست 3- نسخه پيشرفتهتر يك سرورسپس در خط 10 کلاسی با نام ServCmd تعریف کردهایم و در تابع ()__init__ سوکت را ساخته و آن را به نام و آدرس فعلی متصل میکنیم. در خط 12 مشاهده میکنید که این بار برای ساخت سوکت دو آرگومان به آن ارسال کردهایم. همانگونه که پیشتر نیز اشاره کردیم، تابع سازنده سوکت چهار آرگومان عددی اختیاری دارد که نخستين آنها تعیین کننده نوع آدرسدهی سوکت است. زیرا نحوه آدرسدهی در شبکههای یونیکس، IPv4 و IPv6 با یکدیگر متفاوت است. حالت پیشفرض این آرگومان مقدار عددی 2 یا شبکههای مبتنی بر IPv4 است. آرگومان دوم تعیین کننده نوع خود سوکت است و در واقع بیان کننده فرمت انتقال اطلاعات روی اتصال ایجاد شده توسط این سوکت است. حالت پیشفرض آن عدد 1 یا انتقال اطلاعات از طریق جریان (Stream) است. آرگومانهای سوم و چهارم فراتر از مجال این مقاله هستند. در مثال این قسمت به جای آرگومانهای عددی برای خواناتر بودن کد، از ثابتهایی استفاده شده که توسط خود ماجول Socket در دسترس قرار میگیرند. این ثابتهاي عددي، یعنی AF_INET و SOCK_STREAM توسط ماجول socket تعریف و مقداردهی میشوند. به عبارت دیگر، دستور خط 12 در واقع معادل self.serv=socket(2,1) خواهد بود. شكل 2- خروجي نسخه دوم برنامههاي كلاينت و سرورسپس با تعريف تابع Run (در خط 18) روی ورودیهای سوکت موردنظر به انتظار اتصال و دریافت دستور خواهیم نشست. در خط 27 تابعی برای شنود پورت و آدرس مورد نظر تعریف کردهایم. آدرس و شي کلاینت مربوط به سوکت متصلشونده را در خط 30 و به کمک تابع ()accept دریافت کردهایم. توجه کنید که برای در دسترس بودن شی سوکت متصل شونده در تمام قسمتهای کد، در خط 31 آن را به یکی از خاصیتهای شی ServCmd تبدیل کردهایم. در خط 33 تابعی برای پردازش دستورات دریافتی ایجاد شده است. در بخش اول این تابع وجود یا عدم وجود ورودی را چک کردهایم. اگر دستوری دریافت شده باشد آن را به تابع ()servCmd ارسال میکنیم. به تفاوت میان ServCmd که یک کلاس است با تابع ()servCmd که در همان کلاس تعریف شده است دقت کنید. این تابع به کمک متد ()strip در خط 47 که مختص نوع داده رشته است، فضاهای خالی احتمالی در ابتدا و انتهای رشته را حذف کرده و دستور را بصورت خالص بازمیگرداند. همچنین در صورت دریافت دستور GOODBYE چرخه اجرای برنامه را متوقف میکند. هنگامی که دستوری را از جانب کلاینت دریافت کردیم، از تابع ()popen متعلق به ماجول os برای پردازش آن استفاده میکنیم (خط40 ). این تابع در واقع یک پوسته خط فرمان ایجاد کرده و دستور دریافتی را در آن اجرا میکند. پس از اجرای دستور خروجی حاصل از آن را در خط 41 دریافت کرده و در خط 42 کنترل میکنیم. در صورتیکه دستور دارای خروجی باشد، آن را به سوکت برقرار کننده اتصال بازمیگردانیم و در غیر این صورت پیغام OK بازگردانده میشود (خطوط 42 تا 45). حال نوبت کدهای سمت کلاینت است که آنها را در فهرست 4 مشاهده میکنید. این کدها بسیار سادهتر از کدهای سمت سرور هستند. در اینجا از همه قسمتها به جز بخش ارسال دستور صرفنظر میکنیم، زیرا خود شما دیگر میتوانید آنها را تجزیه و تحلیل کنید. در قسمت ارسال دستور و در خط 234 دستور ساده ls را برای دریافت فهرست فایلهای موجود در سمت سرور اجرا کردهایم (در صورت استفاده از ماشینهای ویندوزی باید آن را به dir تغییر دهید).نتیجه اجرای این دو برنامه در ماشین من همانند شکل 3 است. برای برقراری ارتباط بین ماشینهای متفاوت در یک شبکه کافی است در فایل مربوط به کلاینت، در خط 53245 عبارت localhost را به نام یا آدرس IP ماشینی که برنامه سرور را اجرا میکند، تغییر دهید. به این ترتیب، امکان انتقال اطلاعات بین ماشینهای مختلف را در اختیار خواهیم داشت. #!/usr/bin/env python # client2.py from socket import * from time import time from time import sleep import sys BUFSIZE=4096 class CmdLine: def __init__(self,host): self.HOST=host self.PORT=29876 self.ADDR=(self.HOST,self.PORT) self.sock=None def makeConnection(self): self.sock=socket(AF_INET,SOCK_STREAM) self.sock.connect(self.ADDR) def sendCmd(self,cmd): self.sock.send(cmd) def getResult(self): data=self.sock.recv(BUFSIZE) print data if __name__==”__main__”: conn=CmdLine(“localhost”) conn.makeConnection() conn.sendCmd(“ls -al”) conn.getResult() conn.sendCmd(“GOODBYE”) فهرست 4- نسخه پيشرفتهتر يك كلاينتاگر میخواهید برنامه کلاینت شما ارتباط با سرور را قطع نکند و بتوانید دستورات دیگری را نیز با این سیستم امتحان کنید، کافی است خطوط 25 تا 30 فایل کلاینت را با قطعه کدهای فهرست 5 تعویض کنید. در این صورت در یک حلقه دائمی تا زمانی که شما دستور finish را صادر نکرده باشید، دستورات جدید از شما پرسیده شده و روی سرور اجرا خواهند شد. با این مثالهای ساده شما بهصورت عملی با مفهوم برنامههای کلاینت/ سرور آشنا شدهاید و میتوانید برنامههایی را بهصورت توزیع شده روی کامپیوترهای شبکه خود به اجرا درآورید. در بخشهای بعدی مجموعه و با تکمیل مباحث مربوط به تعامل پایتون و سیستمعامل بهتر خواهید توانست قابلیتهای سیستمهای کلاینت/ سرور را مورد استفاده قرار دهید. if __name__ == “__main__”: conn=CmdLine(‘localhost’) conn.makeConnection() loop=1 while loop: cmd=raw_input(“Enter a command:”) if cmd==”finish: loop=0 else: conn.sendCmd(cmd) con.getResult() فهرست 5- كد جايگزين براي حفظ ارتباط كلاينت و سرور
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون آشنايي با زبان برنامه نويسي پايتون (قسمت هشتم) احمد شریفپور اشاره: ماهنامه شبكه - سکون و ایستایی در دنیای نرمافزار مترادف مرگ است. همه نرمافزارها برای ادامه حیات خود محتاج به روزآوری و افزوده شدن قابلیتها و ویژگیهای جدید هستند. در این میان با گسترش کاربرد و نفوذ کامپیوترها در جنبههای مختلف زندگی ما، زبانهای برنامهنویسی بیش از سایر نرمافزارها به این پویایی و تحول نیاز دارند. بر همین اساس، زبان پایتون نیز بهصورت مداوم در حال بازبینی و بهینهسازی است... سکون و ایستایی در دنیای نرمافزار مترادف مرگ است. همه نرمافزارها برای ادامه حیات خود محتاج به روزآوری و افزوده شدن قابلیتها و ویژگیهای جدید هستند. در این میان با گسترش کاربرد و نفوذ کامپیوترها در جنبههای مختلف زندگی ما، زبانهای برنامهنویسی بیش از سایر نرمافزارها به این پویایی و تحول نیاز دارند. بر همین اساس، زبان پایتون نیز بهصورت مداوم در حال بازبینی و بهینهسازی است. در این مورد خاص و با توجه به حجم عظیم تغییرات ایجاد شده در نسخه جدید، بنیاد نرمافزار پایتون (Python Software Foundation) تصمیم گرفته، ارتقا به سري جدید را به تدریج انجام دهد، يعني روند توسعه سری جدید در کنار سری جاری و بهصورت همزمان انجام میپذیرد تا زمانی که بنیاد به این نتیجه برسد، بيشتر کاربران آمادگی انتقال به سري جدید را دارند. در این قسمت تصمیم گرفتیم، به معرفی مختصر خصوصیات و تفاوتهای نسل جدید پایتون با نسل قبل بپردازیم. نسل سوم همانگونه که پیشتر اشاره شد، در حالحاضر توسعه پایتون در دو مسیر موازی در حال انجام است. گروه نخست توسعهدهندگان همچنان به کار روی سری دوم پایتون (2.x) مشغول هستند که بهدلیل قدمت و سابقه بیشتر، پرطرفدارتر است. در حال حاضر بيشتر فریمورکها و کتابخانههای رایج و پراستفاده برای این سری توسعه داده شده و پیادهسازی میشوند. تمام مثالها و برنامههایی که تاکنون معرفی کردهایم نیز از همین سری استفاده میکنند. این نسل از زبان پایتون در اکتبر سال 2000 معرفی شد و اکنون به نسخه 2,7,1 رسیده است. گروه دوم توسعهدهندگان به کار روی نسل جدید این زبان، یعنی پایتون 3.x میپردازند که تاکنون نسخه 3,2 آن نیز منتشر شده است. در این سری وان روسوم (Guido van Rossum) خالق پایتون، تصمیم گرفته به بازنگری اساسی در تمام جنبههای این زبان برنامه نویسی و حذف Backward Compatibility (پشتیبانی از اجرای کدهای نوشته شده با نسل دوم این زبان) بپردازد. هدف اين است كه سري جديد پايتون، با بنيادي متفاوت و با شروعي دوباره، علاوه بر سادهسازي دستور زبان افزايش خوانايي، امكانات و ويژگيهاي جديدي را نيز به ارمغان آورد. در این نسخه سینتکس بسیاری از دستورها برای کارایی بهتر، یادگیری سادهتر و یکنواخت شدن با سایر اجزای پایتون تغییر كرده و پارهای از دستورات با همان سینتکس قدیمی، کارایی تازهای پیدا کردهاند. ما در این قسمت تنها به معرفی برخی تغییرات اساسی خواهیم پرداخت که به صورت خاص به دستوراتی مربوط میشوند که در قسمتهای قبلی از آنها استفاده کردهایم. برای آشنایی عمیقتر با جنبههای نو و تغییرات نسل سوم زبان پایتون میتوانید از منابع فراوانی که در اینترنت موجود است، استفاده کنید. دستور PRINT یکی از مهمترین و پرکاربردترین بخشهای پایتون که در این نسخه دستخوش تغییرات اساسی شده، دستور print است. در نسخههای 2.x این زبان به راحتی میتوانستیم آیتم مورد نظر را به فرم زیر چاپ کنیم: print “This is a test” اما در سری جدید پایتون، چنین دستوری با پیغام خطا مواجه خواهد شد. در واقع نسخه جدید دستور print را همانند یک تابع پیادهسازی کرده است و همانند هر تابع دیگری برای ارسال آرگومانها به تابع باید از پرانتز استفاده کنیم. یک دستور ساده print در نسخه سوم به فرم زیر است: print (“This is a test”) هرچند این تغییر به ظاهر ساده است، اما در ادامه خواهیم دید که تغییرات دستور print به همین موارد خلاصه نخواهد شد. قالببندی و جایگذاری متغیرها در نسخه قبلی پایتون ما از کدهایی برای قالببندی و جایگذاری متغیرها در یک رشته استفاده میکردیم (همانند شكل1). اگرچه این عبارت در پایتون 3,2 نیز به درستی کار خواهد کرد، اما این وضعیت در حال تغییر است، زيرا توابع قالببندی %s و %d در نسخههای آینده حذف خواهند شد و سیستم نگارشی {x} جایگزین آن خواهد (شکل2). در این روش عبارتهاي معرفی شده به عنوان آرگومانهای متد format، به ترتیب جایگزین {x}ها خواهند شد. همانطور که مشاهده میکنید، خوانایی این روش جدید بسیار بیشتر از حالت قبلی ارجاع به متغیرها و قالببندی آنها است.شكل 1- قالببندي و جايگذاري متغيرها در پايتون X.2 شكل 2- قالببندي و جايگذاري متغيرها در پايتون X.3اعداد در سری 2.x پایتون عبارت 5/0.2 حاصلی برابر با 5.2 داشت. اما اگر از عبارتی مانند 5/2 استفاده میکردید، بهواسطه تبدیل نتیجه به فرمت عدد صحیح (بهواسطه عدد صحیح بودن هر دو عملوند عبارت 5/2) حاصلی برابر 2 دریافت میکردید. در سری 3.x پایتون استفاده از هر دو فرم قبلی نتیجهای برابر با 5.2 ایجاد خواهد کرد. و در صورتی که نیاز داشته باشید تقسیم را بهصورت صحیح و بدون اجزای اعشاری انجام دهید، باید از فرمت 2//5 استفاده کنید. دستور INPUT در سری 2.x پایتون، دستور input تنها ورودیهای عددی را میپذیرفت و در صورت ورود رشتهها همانند شکل 3 با پیغام خطا روبهرو میشدیم. برای دریافت رشتهها از کاربر مجبور بودیم از دستور raw_input استفاده کنیم. اما در سری 3.x دستور input با تمام ورودیها همانند رشته رفتار میکند و در صورتی که به دریافت اعداد نیاز داشته باشید، باید ورودیهای دستور input را به صورت دستی به عدد تبدیل کنید.
پاسخ : آشنايي و كار با زبان برنامهنويسي پايتون آشنايي با زبان برنامه نويسي پايتون (قسمت نهم) [TABLE="class: cms_table_PageContent"] [TR] [TD="class: cms_table_BoxContentSimple"] اشاره: ماهنامه شبكه - سکون و ایستایی در دنیای نرمافزار مترادف مرگ است. همه نرمافزارها برای ادامه حیات خود محتاج به روزآوری و افزوده شدن قابلیتها و ویژگیهای جدید هستند. در این میان با گسترش کاربرد و نفوذ کامپیوترها در جنبههای مختلف زندگی ما، زبانهای برنامهنویسی بیش از سایر نرمافزارها به این پویایی و تحول نیاز دارند. بر همین اساس، زبان پایتون نیز بهصورت مداوم در حال بازبینی و بهینهسازی است... [/TD] [/TR] [TR] [TD] سکون و ایستایی در دنیای نرمافزار مترادف مرگ است. همه نرمافزارها برای ادامه حیات خود محتاج به روزآوری و افزوده شدن قابلیتها و ویژگیهای جدید هستند. در این میان با گسترش کاربرد و نفوذ کامپیوترها در جنبههای مختلف زندگی ما، زبانهای برنامهنویسی بیش از سایر نرمافزارها به این پویایی و تحول نیاز دارند. بر همین اساس، زبان پایتون نیز بهصورت مداوم در حال بازبینی و بهینهسازی است. در این مورد خاص و با توجه به حجم عظیم تغییرات ایجاد شده در نسخه جدید، بنیاد نرمافزار پایتون (Python Software Foundation) تصمیم گرفته، ارتقا به سري جدید را به تدریج انجام دهد، يعني روند توسعه سری جدید در کنار سری جاری و بهصورت همزمان انجام میپذیرد تا زمانی که بنیاد به این نتیجه برسد، بيشتر کاربران آمادگی انتقال به سري جدید را دارند. در این قسمت تصمیم گرفتیم، به معرفی مختصر خصوصیات و تفاوتهای نسل جدید پایتون با نسل قبل بپردازیم. نسل سوم همانگونه که پیشتر اشاره شد، در حالحاضر توسعه پایتون در دو مسیر موازی در حال انجام است. گروه نخست توسعهدهندگان همچنان به کار روی سری دوم پایتون (2.x) مشغول هستند که بهدلیل قدمت و سابقه بیشتر، پرطرفدارتر است. در حال حاضر بيشتر فریمورکها و کتابخانههای رایج و پراستفاده برای این سری توسعه داده شده و پیادهسازی میشوند. تمام مثالها و برنامههایی که تاکنون معرفی کردهایم نیز از همین سری استفاده میکنند. این نسل از زبان پایتون در اکتبر سال 2000 معرفی شد و اکنون به نسخه 2,7,1 رسیده است. گروه دوم توسعهدهندگان به کار روی نسل جدید این زبان، یعنی پایتون 3.x میپردازند که تاکنون نسخه 3,2 آن نیز منتشر شده است. در این سری وان روسوم (Guido van Rossum) خالق پایتون، تصمیم گرفته به بازنگری اساسی در تمام جنبههای این زبان برنامه نویسی و حذف Backward Compatibility (پشتیبانی از اجرای کدهای نوشته شده با نسل دوم این زبان) بپردازد. هدف اين است كه سري جديد پايتون، با بنيادي متفاوت و با شروعي دوباره، علاوه بر سادهسازي دستور زبان افزايش خوانايي، امكانات و ويژگيهاي جديدي را نيز به ارمغان آورد. در این نسخه سینتکس بسیاری از دستورها برای کارایی بهتر، یادگیری سادهتر و یکنواخت شدن با سایر اجزای پایتون تغییر كرده و پارهای از دستورات با همان سینتکس قدیمی، کارایی تازهای پیدا کردهاند. ما در این قسمت تنها به معرفی برخی تغییرات اساسی خواهیم پرداخت که به صورت خاص به دستوراتی مربوط میشوند که در قسمتهای قبلی از آنها استفاده کردهایم. برای آشنایی عمیقتر با جنبههای نو و تغییرات نسل سوم زبان پایتون میتوانید از منابع فراوانی که در اینترنت موجود است، استفاده کنید. در انتهای این قسمت آدرس تعدادی از این مراجع را ذکر خواهیم کرد. نامساوی و شرطیها در سری 2.x پایتون برای کنترل نامساویبودن عبارتها از عملگر <> استفاده میشد، اما این شیوه در سری 3.x دیگر مجاز نیست و به جای آن باید از عملگر != استفاده کرد. نکته دیگر اینکه در سری 2.x در صورت مقایسه دو عملوند از نوع مختلف (مثلاً مقایسه یک رشته با یک عدد صحیح) همانند شکل 4 نتیجهای برابر با false یا نادرست بازگردانده میشد. به عبارت دیگر، خطایی رخ نمیداد. اما در سری 3.x باید حتماً، از یکسان بودن (به عبارت کلیتر، قابل مقایسه بودن) عملگرها اطمینان حاصل کرد. در غیر این صورت، همانند شکل 5 با خطای Type Error مواجه خواهیم شد.شكل 4- در سري X.2 ميتوان انواع داده نامربوط را با هم مقايسه كرد. شكل 5- در پايتون X.3 تنها انواع داده مشابه قابل مقايسه هستند.سایر تغییرات انواع داده بنیادین در پایتون نیز دستخوش تغییر شدهاند. دو نوع داده int و long در قالب یک نوع داده، یعنی int ادغام شدهاند و متدهای مربوط به دیکشنریها نظیر ()dict.keys به جای بازگرداندن یک لیست، نوع جدیدی به نام view را باز میگردانند. تابعی نظیر() range هم به جای یک لیست یک شمارنده یا Iterator را باز میگرداند. همچنین تغییرات فراوانی نیز در کتابخانههای استاندارد پایتون ایجاد شده است. به عنوان مثال، میتوان به حذف توابع مربوط به گوفر (gopherlib) و جایگزین شدن md5 با hashlib اشاره کرد. البته، همانطور که در ابتدا نیز اشاره شد، تغییرات ایجاد شده بسیار زیاد بوده و توضیح كامل همه آنها در این مقاله نميگنجد. تبدیل برنامهها به سری جدید سری 3.x پایتون با ابزاری برای تبدیل کدهای سریهای قبلی به سری جدید همراه شده است. اگرچه این ابزار در همه موارد به درستی عمل نمیکند، اما در بسیاری از موارد شما را به هدف بسیار نزدیک خواهد کرد. این ابزار نام معنیدار 2to3 را یدک میکشد. در لینوکس برای استفاده از این ابزار از طریق ترمینال دستور زیر را وارد میکنیم: 2to3 [-w] <input_file.py< توجه داشته باشيد كه اين دستور به شرطي عمل خواهد كرد كه سري 3.x پايتون روي لينوكس نصب شده باشد. در اوبونتو براي نصب اين سري جديد از دستور زير استفاده كنيد: sudo apt-get install python3 این ابزار در ماشینهای ویندوزی با نام 2to3.py در پوشه c:\Python3x\Tools\Scripts قرار دارد و برای استفاده از آن باید از خط فرمان و در پوشه گفته شده دستور زیر را صادر کرد: <python.exe 2to3.py [-w] <input_file.py این برنامه در حالت عادی تنها تغییرات لازم را برای تبدیل کد، روی صفحه نمایش چاپ خواهد کرد و فایل را تغییر نخواهد داد. استفاده از سوییچ اختیاری –w باعث میشود، تغییرات مورد نیاز به فایل اصلی اعمال شود. در صورت استفاده از این سوییچ یک نسخه پشتیبان از فایل تهیه شده و تغییرات موردنیاز به طور مستقيم به فایل اعمال ميشود. آیا باید به سری 3.x مهاجرت کنیم؟ تغییرات سینتکس در همه نسخههای جدید زبانهای برنامهنویسی به چشم میخورد. میانبرهایی نظیر =+ ممکن است به سادگی کار ما را در هنگام کدنویسی سادهتر کنند. اما همین تغییرات ساده سینتکس جنبههای منفی نیز در خود دارند. درباره زبان پایتون نیز به دلیل همین تغییرات (گاهي ساده) در سینتکس، بسیاری از ماجولها و کدهایی که قبلاً استفاده ميكرديم، در برنامههايي که با سری 3.x پایتون نوشته میشوند، قابل استفاده نیستند. به عنوان نمونه میتوان به کتابخانههای ElementTree اشاره کرد که در بخش مربوط به xml از آن استفاده کردیم. اما با تمام این مشکلات نباید از مهاجرت به سری 3.x پایتون نا امید شد. خوشبختانه پایتون سری 2.x (حداقل از نسخه 2,6 به بعد) در عین سازگاری با نسخههای قبلی، از تمام سینتکسهای مورد نیاز برای نوشتن کد به سبک سری 3.x پشتیبانی میکند (فهرست 6). پیشنهاد میکنیم که از همین حالا نوشتن کد به سبک سری 3.x را آغاز كرده و اگر میتوانید تنها به کتابخانه استاندارد پایتون بسنده کنید و به ماجولهای دیگر رجوع نكنيد، حتماً به 3.x پایتون مهاجرت کنید. شكل 6 به کمک ابزار انتقالی که پیشتر از آن صحبت کردیم، تقریباً میتوانید به سادگی تمام مجموعه کدهایی را که تاکنون نوشتهاید، به سری 3.x ارتقا دهید. اما حتی اگر نیازمند کتابخانههایی هستید که هنوز به سری 3.x منتقل نشدهاند، همواره گوشه چشمی به این سری جدید داشته باشید. زيرا دیر یا زود کدهای موردنظر شما نیز به سری 3.x ترجمه خواهند شد. [/TD] [/TR] [/TABLE]