الخميس، 1 أكتوبر 2015

الفرق بين print و return

الفرق بين print و return
أنهيت كتابة المقالة بتاريخ:
12:39 AM 1-10-2015


بسم الله الرحمن الرحيم

كثير من الأسئلة والأفكار تدور في ذهن المتعلم حول هاتين الإفادتين(statments)، فعندما تقرأ في كتاب أو دورة ما لا يتم أخذهما بتعمق فيصبح المتعلم مشوشا ولا يعرف كيفية الإستفادة الحقيقية من خواصهما، في هذه المقالة سأتحدث عن هذا الأمر مدعما كتاباتي بالأمثلة، راجيا من الله عز وجل التوفيق.

أولا.. سأبدأ بلمحة عامة عن هاتين الإفادتين.
الإفادة print‏ ‏:
هي إفادة في بايثون 2 ولكنها أصبحت دالة(function) في بايثون 3 لأسباب وجيهة، تقوم بطباعة الخرج الناتج عن عملية ما أو بطباعة قيمة ما مخزنة في متغير على سبيل المثال.

الإفادة return‏ ‏:
تعود بقيمة من دالة ما؛ تقوم بعملية إستعادة قيمة دالة ما، هذا ما يجب أن تركز عليه وسأشرح بتفصيل أكثر.
#################################################################################

قبل البدء سأعرض سؤالين أكاد أجزم أنهما راوداك وسأجيب لك عنهما؛ لكنهما ليسا الصورة الكاملة إن صح التعبير. ستضح الكثير من الأمور ولكن ليس كلها o‎_O.

س1: أين تستخدم الإفادتان؟
تستخدم الإفادة print في كل مكان تقريبا، وتستخدم الإفادة return داخل الدوال حصرا‎‏ وإذا استخدمت خارج الدوال فإن الخطأ SyntaxError سيعتلي.
مثال 1.0: شفرة تعمل بنجاح

مثال 1.1: شفرة خاطئة
 
#################################################################################

س2: متى تستخدم الإفادتين؟
تستخدم الإفادة print عند الحاجة لطباعة الخرج مباشرة على الشاشة، وتستخدم الإفادة return عند الحاجة لحفظ الخرج في الذاكرة(مثلا: إسناد الخرج إلى متغير) أو إستخدام الخرج في عملية أخرى مباشرة(مثلا: إستخدام خرج دالة ما في عمليات دالة أخرى) أو أشياء أخرى من هذا القبيل.
مثال 2.0: طباعة الخرج مباشرة على الشاشة
مثال 2.1: إسناد الخرج إلى متغير
هذه الطريقة تجنبنا مشاكل إستخدام متغيرات عالمية global.

مثال 2.2: إستخدام الخرج في عمليات أخرى
الدالة multiply2 عادت بالدالة sum2 وهذا يعد أحد أنواع مزينات/مزخرفات decorators بايثون(دالة تعود بدالة أخرى).
======================================================================
======================================================================

*. أعتقد أن جواب السؤال الأول وضح المقصد بيسر وسهولة!
*. برأيي جواب السؤال الثاني لم يوضح بالشكل المطلوب فالأمر أوسع من هذا..!، ما رأيك أنت؟
==> لذا سأستطرد بالشرح أكثر إعتمادا على أمثلة جواب السؤال الثاني.
- إذا لاحظت في المثال 2.0 ، جسم الدالةsum1 ‎‏ يعطي الخرج مطبوعا على مباشرة عند تنفيذ الشفرة وهذا نقيض للمثال 2.1 حيث أن جسم الدالة المعدلة فيه sum2 لا يعطي الخرج مطبوعا بل يمسك به.، لتوضيح الفكرة أكتب/إلصق الشفرة التالية على محررك ونفذها(أكتب قبله الدالتين المستخدمتين)‎:
 
سنحصل بعد التنفيذ على الخرج التالي:
6
حسنا، شيء غريب حصل، إن 6 نتاج الدالة الأولى لكن أين نتاج الدالة الثانية؟ يفترض أن يطبع تحت '6' الناتج: 8 ، أين ذهب؟ ماذا حصل؟
سأقول لك ما الذي حدث، في الدالة الأولى لا يتم إعادة أي قيمة بل يتم إخراج القيمة مباشرة على الشاشة والقيمة المعادة عندها: 'لا شيء' None‏ ‏، أما في الدالة الثانية لا يتم إخراج أي قيمة مباشرة على الشاشة بل يتم إعادة القيمة ،والقيمة المعادة عندها: 8 لكنها لا تطبع.. إذا لتطبعها على الشاشة ستحتاج لإستخدام print‏ ، فالنرى إذا التالي ‏(قم بتنفيذ الشفرة):
 
بعد التنفيذ سنحصل على التالي:
6
None
8
كما ترى فهناك قيمتان جديدتان ظهرتا على شاشتنا، هما: None‏ و 8، إن None‏ القيمة المعادة من الدالة الأولى و 8 هي القيمة المعادة من الدالة الثانية.. هذا ما أردت أن أريك إياه :)

*. سؤال يطرح نفسه الآن، لعلك فكرت به:
س3: متى تكون قيمة الدالة المعادة 'لا شيء' None‏ ؟
صراحة هناك عدة حالات، لا أعلم لعلي سأوردها كلها الآن أو قد يغيب عن ذهني بعضها، سأوردها الآن فركز معي:
-> أول حالة، أن يكون جسم الدالة فارغا!، سأستخدم الإفادة pass‏ لهذا الغرض.
مثال 3.0: دالة ذات جسم فارغ(دالة فارغة)
-> ثان حالة، أن يكون جسم الدالة ليس فارغا لكن يتم إخراج القيم مباشرة، عد إلى المثال 2.0 وتمعن به ==> لم نعطي الدالة قيمة لتقوم بإعادتها.
-> ثالث حالة، أن تكتب في جسم الدالة إفادة return فارغة!
مثال 3.1: دالة ذات إفادة  return فارغة!

======================================================================

إذا كنت تظن أننا إنتهينا، فأنت مخطئ فكل الذي سبق كان أول جزء، الآن سنتابع حديثنا الشيق..

سأتحدث عن حاجز return، نعم لا تستغرب، هذا الحاجز يوجد عند إقحام return‏ في جسد أي دالة، وكما في الجزء الأول أعلاه؛ سأطرح عدة أسئلة واضعا الإجابات بعون الله.
س4: بماذا يقوم حاجز return‏ ‏؟ ماذا يفعل؟
ببساطة، هذا الحاجز يسمح بتنفيذ الشفرات التي تسبقه كالمعتاد(عد إلى المثال 3.1 وإقرأ الدالة الثانية بتمعن) ويمنع تنفيذ الشفرات التي تأتي بعده أي يتجاهلها!
بينما الإفادة print‏ لا تضع هكذا حاجز فهي تسمح بتنفيذ الشفرات التي قبلها والتي بعدها أيضا.
مثال 4.0 : تجاهل الشفرات اللاحقة
ستحصل على الخرج التالي:
I Love Allah
And All Its Messengers
Praying Is The Food Of My Soul
كما لاحظت، لم يتم تنفيذ الشفرة التي تلي return‏ ‏؛ توقف تنفيذ الدالة عند شفرة return.

س5: بماذا يفيد هذا الحاجز؟
عند وجود هذا الحاجز فإنه يعطي الدالة إشارة أن هذه قيمتك المعادة وقد حصلتي على مرادك أخيرا عندها تتوقف الدالة عند هذا السطر وينتهي عمل الدالة -لكن هناك إستثناءات-.
*. عادة أستفيد من هذه الخاصية في دالة كتبتها لمعرفة فيما إذا كانت القيمة التي حصلت عليها من عملية ما قابلة-للترديد iterable‏ أم لا (مثلا: كأن أحصل على قائمة من أرقام مختلفة أو أحصل على رقم لوحده)، هذه دالتي:
مثال 5.0 : دالة لها أكثر من إفادة return واحدة.

======================================================================

قد يتبادر للذهن بأن كل ما كتبته من أمثلة عن return‏ ‏، جعلت فيها return‏ تعود بقيمة واحدة.. أعتقد فهمت مقصدي من هذا الكلام.

[6] إفادة return‏ تعود بأكثر من قيمة واحدة!
حسنا، أعترف القيام بمثل هكذا أمر ليس إلا خداعا، فمهما فعلت سيكون عدد القيم المعادة واحد '1'، سيتم الأمر بأن أعيد أكثر من قيمة داخل حاوية واحدة أو حاويات فرعية لحاوية رئيسية ما.. الفكرة لازالت مشوشة ومبهمة قليلا أليس كذلك؟ فالنرى المثال التالي وسيبدأ الضباب بالإنقشاع:
مثال 6.0: دالة تعود بأكثر من قيمة!
وستحصل على الخرج التالي:
(1, 2, 3)
كما قد لاحظت، حصلنا على قيمة واحدة رئيسية وهي الصف tuple‏ من خلال وضعنا للفاصلة بين القيم المعادة ‏(الصف هو الحاوية الإفتراضية default) وبداخله ثلاثة قيم(أرقام) نستطيع إستخدامها من خلال الولوج إليها عبر المؤشر index الخاص بكل قيمة فرعية.
يمكن أن نعود بالقيم المتعددة بحاويات أخرى غير الصف كالقائمة list مثلا، هكذا:
return [a, b, c]
أو:
return list(a, b, c)

كإستراحة قصيرة تفقد المثال التالي[ليس تعليميا وليس لغرض المقارنة]
مثال 6.1: رؤية قيم متعددة في الخرج!
ستحصل على الخرج التالي:
my name is samer
('my name is', 'samer')


سؤال سأله أحد الذين يتعلمون بايثون، هو كالتالي:
س7: هل يمكن وضع أكثر من إفادة return‏ في دالة واحدة وتعمل بنفس الوقت؟
أعتقد أنك يجب أن تجيب بسهولة: لا
- يمكن وضع أكثر من إفادة لكن كل واحدة تعمل عند حدوث شرط أو حدث ما(عد للمثال 5.0 وتمعن به).
مثال 7.0: عدم عمل الإفادات المتتابعة
ستحصل على الخرج التالي:
I'm The Only Retured Value Here

======================================================================

[8] آخر ما سأتحدث عنه هو إفادة return‏ الحلزونية 'هكذا أحب تسميتها :)' ، على عكس إفادة print‏ فإن الإفادة return‏ تسمح بإعادة العملية ضمن نفس الدالة أكثر من مرة!! (هذا الإستثناء الذي تحدثت عنه في جواب السؤال 5)، هذه الطريقة أستفيد منها في العديد العديد من الأمور من أشهرها دالة لإيجاد: ن عاملي لرقم ما n factorial‏ ‏، تفقد المثال التالي:
مثال 8.0: الإستفادة من إفادة حلزونية


أتممت هذه المقالة بعد عناء بعون وفضل من الله والحمد لله رب العالمين وأفضل الصلاة وأتم التسليم على حبيبنا محمد خاتم الأنبياء والمرسلين صلى الله عليه وسلم.
والسلام عليكم ورحمة الله وبركاته

إذا كانت لديك أي ملاحظة أو إستفسار أو تحسين مقترح أو فكرة غفلت عنها .. رجاء أكتب ذلك في تعليقات المقالة دون تردد.

الثلاثاء، 9 يونيو 2015

الحصول على نطاق Domain رابط ما

مقـدمة:
كلٌّنا يعرف الإعراب في اللُّغة العربية على الأقل!!..
كخلاصة:, الإعراب: هو تحليل للنص ومعرفة مدلولات الكلمات(الزمنية , العاطفية......إلخ)
كمثال:  شمَّ الطفل الزهرة.
شمَّ: ماضٍ مفتوح.....
الطفل: فاعل مرفوع.....
الزهرة: مفعول به منصوب........
(( على كلِّ حالٍ ليس الهدف الإعراب في اللغة العربية.))
=====================================================
=====================================================

سنتطرق إلى إعراب الروابط!! ( نعم إعراب الروابط)..

هناك مكتبة قياسية إسمها: urlparse , سنستعملها لهذا الغرض.
سنحصل كـ خرج على الصف tuple التالي:
(مخطَّط(بفتح الطاء)، موقع، مسار، تساؤل وقطعة)
(scheme, location, path, query and ‏fragment)

قبل البدء سنتطرق لمعرفة معنى الرابط أو URL
(محدد الموارد الفريد/العام - عنوان صفحة على الشبكة العنكبوتية الواسعة)
(url: universal [uniform] resource locator - The address of a World Wide Web Page)


جلب وحدة إعراب الروابط
import urlparse
إسناد العنوان(سلسلة نصية) إلى متغير
url = "http://python.org"
طباعة الخرج العام الذي تحدثنا عنه بداية
print "(scheme, location, path, query and ‏fragment)"
طباعة الخرج العام الناتج من الرابط أعلاه
print urlparse.urlsplit(url)
طباعة سطر فارغ
print # Empty line..

إسناد النطاق إلى متغير
domain = urlparse.urlsplit(url)[1].split(':')[0]

طباعة إسم النطاق
print "The domain name of the url is: ", domain

الخميس، 21 مايو 2015

مثال حول إستخدام وحدة التعابير المنظمة (النمطية) re في مطابقة النصوص

Regular Expressions

مشروح عربيا ووضعته في هذا الرابط من أجل الحفاظ على الإزاحات البيضاء

"""
[-]{3}
تعني ثلاث معترضات hyphen متتالية 
\w{3}
تعني كلمة word من ثلاثة أحرف متتالية (ليست محددة)
\d{3}
تعني ثلاثة أرقام متتالية (ليست محددة)..
|
تعني أي واحدة من القيمتين التي على جانبيها
$
تعني نهاية السلسلة النصية

لنرى التالي كـ مثال:
*. إنتبه للأقواس.....
'((\w{3})|([-]{3}))\d{3}$'
تعني سلسلة نصية تحوي 3 أحرف أو3 معترضات وتنتهي السلسلة بـ 3 أرقام

مثال تطبيقي:
"""
# جلب مكتبة التعابير المنظمة
import re
# القيم التي نريد المطابقة بها
values = ['cat100', '---200', 'xxxyyy', 'jjj', 'box4000', 'tent500']
for v in values:
    # يتطلب 3 أحرف أو 3 معترضات‎ ‎... وأيضا 3 أرقام
    # Require 3 letters OR 3 dashes.
    #... Also require 3 digits
    m = re.match('((\w{3})|([-]{3}))\d{3}$', v)
    if m:
        print 'Ok..', v
    else:
        print 'FAIL', v

"""
Output - الخرج


Ok.. cat100
Ok.. ---200
FAIL xxxyyy
FAIL jjj
FAIL box4000
FAIL tent500
"""


#re

فتح ملف مضغوط zip .. ومعرفة معلومات عن الملفات داخله

جلب مكتبة الملف المضغوط
import zipfile

إسناد المسار(سلسلة نصية) إلى متغير
path = "E://Sample.zip"

تعريف أساس التعامل مع الملف المضغوط!
File = zipfile.ZipFile(path)
----------------------------------------------------------------------------------------------
ملاحظة:: يمكن إضافة معطى parameter آخر إلى: (zipfile.ZipFile(path
فنفتح الملف في وضع القراءة ‎‏ ‏readعلى سبيل المثال فتصبح على الشكل التالي:
File = zipfile.ZipFile(path, 'r')
----------------------------------------------------------------------------------------------

الحصول على قائمة بأسماء الملفات الموجودة ضمن الملف المضغوط
NameList = File.namelist()

طباعة قائمة الملفات على الشاشة
print NameList

طباعة أسماء الملفات عاموديا ومرقمة
for number in range(len(NameList)):
    print number, '|', NameList[number]

طباعة تعريف بما سنقوم به..
print "file name and information:"

طباعة خصائص الملف، إسم الملف وتاريخ التعديل والحجم بالترتيب:
for info in File.infolist():
    print "file name: ", info.filename
    print "date of modifing: ", info.date_time
    print "size: ", info.file_size, "bytes"
    print
أمر الطباعة print لوحده يعني طباعة سطر فارغ!
----------------------------
النتائج بالترتيب:
['Sample.txt', 'Sample.jpg']
0 | Sample.txt
1 | Sample.jpg
file name and information:
file name:  Sample.txt
date of modifing:  (2014, 9, 25, 15, 17, 12)
size:  31 bytes

file name:  Sample.jpg
date of modifing:  (2011, 12, 12, 18, 19, 48)
size:  28351 bytes

#zipfile

قسمة عددين صحيحين ناتج قسمتهما هو عدد عشري

ما ستتعلمه هنا مطبق افتراضيا في بايثون 3
-------------------------------------------------------------------
في بايثون 2
#python2
من أجل قسمة عددين صحيحين ناتج قسمتهما هو عدد عشري(float) والحصول على الناتج بشكل عدد عشري دون الحاجة لوضع فاصلة لأحد أو كلا الرقمين، مثال:
>>> 5/2
2
>>> 5.0/2
2.5

جلب القسمة من مكتبة المستقبل(future)
((ملاحظة: يتم جلب هذه المكتبة في أي سطر من الأسطر الثلاث الأولى من برنامجك))
from __future__ import division

القيام بتجربة..
print 5/9

#__future__

عمليات الفصل في المسارات

جلب مكتبة النظام العملياتي(Operating System)
import os

إسناد المسار(سلسلة نصية) إلى متغير
path = "e://22.txt"

الحصول على لاحقة(امتداد) الملف بشكل منفصل
النتيجة:
(المسار+اسم الملف, الإمتداد)
print "splitext", "=>", os.path.splitext(path)

الحصول على اسم قرص التخزين منفصلا عن المسار
النتيجة:
(قرص التخزين, باق المسار)
print "splitdrive", "=>", os.path.splitdrive(path)

فصل اسم الملف عن المسار
النتيجة:
(المسار, اسم الملف+الإمتداد)
(dirname, basename)
print "split", "=>", os.path.split(path)

الحصول على اسم الملف المراد الوصول إليه في المسار المعطى
((الحصول على اسم الملف النهائي في المسار))
النتيجة:
اسم الملف+الإمتداد
print "basename", "=>", os.path.basename(path)

الحصول على المسار قبل اسم الملف المعطى في المسار
النتيجة:
المسار عدا: اسم الملف+الإمتداد
print "dirname", "=>", os.path.dirname(path)

النتيجة بالترتيب:
splitext => ('e://22', '.txt')
splitdrive => ('e:', '//22.txt')
split => ('e://', '22.txt')
basename => 22.txt
dirname => e://

#os.path

التأكد من وجود ملفات

جلب مكتبة النظام العمليّاتي ( Operating System )
import os

إسناد المسار(سلسلة نصية) إلى متغير
path = "e://22.txt"

التأكد من وجود الملف على الدليل
تعود ب صح إذا كان موجودا أو خطأ إذا لم يكن موجودا
print os.path.exists(path)

التأكد أنه فيما إذا كان الملف ملفا أم دليل
تعود ب صح إذا كان الملف ملفا أو خطأ إذا كان الملف دليلا 
print os.path.isfile(path)

التحقق من وجود دليل
print os.path.isdir(path)

#os.path