لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 11/19/17 في كل الموقع
-
إن اختيار الاسم هو واحد من أصعب المهام في عملية تأسيس شركة ناشئة، كما أنه شيء يمكنك التّعلّق به بسهولة. ونحن نعلم جميعًا أن الأمر الأهم هو المضي قدمًا لبناء مُنتج نضعه أمام المستخدمين. وفيما يلي 3 خطوات أنصح بها عند تسمية شركة ناشئة جديدة: 1. اجعله من مقطعين فقط (Two Syllables) إذا استطعت في كثير من الأحيان تكون القيود مفيدة عندما تقوم بعملية إبداعية مثل تسمية شركتك الناشئة. ومن أفضل القيود التي وجدتها أثناء تسمية الشركات الناشئة هو محاولة الالتزام بتحديد الاسم في مقطعين فقط 2 syllables . وأتذكر هنا المحادثة الطويلة التي أجريتها مع صديقي العزيز ومُؤسّسي الشّريك السّابق "Oo". عمومًا فإن الالتزام بهذه القاعدة ينتج عنه أسماء رائعة. ألق نظرة على بعض الأمثلة لأسماء من مقطعين: Google Twitter Facebook Foursquare DropBox Pocket Tumblr Flickr HipChat Sparrow Tweetbot Reeder كلها شركات ناشئة عظيمة. وهناك دائما استثناءات لأي قاعدة، ولكني أجد صعوبة أكبر في التفكير في شركات ناشئة ناجحة لها أسماء تتكون من أكثر من مقطعين أكثر من تلك التي يتكون اسمها من مقطعين فقط. هناك أيضًا بعض الشركات الناجحة التي يتكون اسمها من مقطع واحد، ولكن هذا أصعب بكثير، مثل: Square Path Box 2. سهّل الأمر على نفسك اعتدت أن أحاول أن أكون ذكيًا قدر الإمكان أثناء تسمية شركتي الناشئة. فكنت أحاول أن أخلط الكلمات بطريقة ذكية ليخرج لي في النهاية اسم يبدو جيدًا وجاذبًا للانتباه بطريقة ذكية . للأسف، أعاني من جانب الإبداع بعض الشّيء، قد تخطر لي فكرة جيدة من وقت لآخر، ولكني أعرف أن ذلك يحدث لي بمعدل أقل بكثير من بعض الأشخاص الذين أعرفهم. على سبيل المثال، فإن صديقي توم له طريقته الخاصّة في إبداع أسماء واضحة وقصيرة مثل Skinnyo، SlideReach أو Quotespire. وبسبب قلّة حيلتي في إيجاد تسميات مثل التّسميات السّابق فإني أتخذ أسلوبًا مختلفًا بعض الشيء، حيث أفكر ببساطة في كلمة تصف الخدمة بشكل حقيقي أو تعبر عن سمة أساسية من سمات الخدمة التي سوف تقدمها الشركة الناشئة. هذه هي الطريقة التي وصلت بها إلى اسم Buffer. أحب أسلوب "الكلمة المعبرة" هذا لسببين آخرين: • أنت بهذا أقرب للوصول لاسم يمكن النّطق به بسهولة ومن دون التباس. يمكنني أن أؤكد لك أنه ليس من الممتع إطلاقًا أن تقضي سنوات في شركتك تحتاج فيها في كل مرّة إلى توضيح كيفية كتابة أو نُطق اسم شركتك النّاشئة. • لأنه من الأسهل أن تتبع أسلوب "الكلمة ذات المقطعين" إذا كنت ستستخدم كلمة معبرة عن مجال عملك بدلاً من الجمع بين الكلمات لإنشاء كلمة جديدة. 3. لا تكترث لاسم النطاق أرى الكثير والكثير من مؤسسي الشركات يقيدون أنفسهم بالتفكير في اسم النطاق. إن لم أتعلّم سوى شيء واحد أثناء اختياري لاسم شركاتي الناشئة وهو أن اسم النطاق لا يهم على الإطلاق، فالاسم نفسه أكثر أهمية بكثير من أن تقيد نفسك بضرورة وجود اسم نطاق مطابق تمامًا لاسم الشركة. اختر اسمًا جيدًا، واختر له اسم نطاق مُعدّلا فيما بعد. فاسم شركتي الناشئة حاليًا هو Buffer، لكن اسم النطاق هو bufferapp.com. واسم شركتي السابقة كان OnePage، لكن كان اسم النطاق الخاص بها myonepage.com. ما يلفت الانتباه هنا هو أن وجود اسم نطاق مطابق لاسم شركتك ليس له أي تأثير على الإطلاق على نجاح شركتك الناشئة، وهو ما أشار إليه "كريس ديكسون" في هذه التّغريدة: ألقِ نظرة هنا على كل هذه الشركات الناشئة الناجحة التي كان لديها اسم نطاق مؤقت، أو التي لا تزال لديها اسم نطاق مختلف عن أسمائها: Square كان موقعها squareup.com. DropBox كان موقعها getdropbox.com. Facebook كان موقعها thefacebook.com. Instagram كان موقعها instagr.am. Twitter كان موقعها twttr.com. Foursquare كان موقعها playfoursquare.com. Basecamp كان موقعها basecamphq.com. Pocket كان موقعها getpocket.com. Bitly كان موقعها bit.ly. Delicious كان موقعها del.icio.us. Freckle له موقعها letsfreckle.com اختر اسمًا ممتازًا، ثم أضف له شيئًا للحصول على اسم نطاق جيد. فالأمر ليس مُهمّا لهذه الدرجة - سواء حصلت على النطاق المُطابق لاسم الشركة لاحقًا أم لم تحصل عليه. ما يهم هو أن تشرع في بناء المُنتج. ترجمة -وبتصرّف- للمقال How to Name Your Startup لصاحبه Joel Gascoigne (جويل غاسكوين هو مؤسس والرئيس التنفيذي في شركة Buffer)1 نقطة
-
في بدايات التسعينات، قام Guido van Rossum بإنشاء لغة البايثون. تُعتبر البايثون من أشهر لغات البرمجة حاليا، ولها حضور واسع في العديد من المجالات التطبيقية والعلمية، وتتميز بسهولة شفرتها البرمجية وسرعة تعلمها مع متانة وقوة تضاهي اللغات الأخرى. سوف نتناول في هذا المقال المواضيع التالية: التعليقات. أنواع البيانات. المتغيرات والتراكيب. جمل التحكم. الدوال Functions. الوحدات. الفئات. ملاحظة: إصدار البايثون 3 هو المعتمد في شرح هذا المقال، وناتج العمليات والأوامر في هذا المقال سيتم كتابتها بعد الرمز # =>. التعليقات تبدأ التعليقات ذات السطر الواحد برمز #، أما التعليقات التي تحتوي أكثر من سطر فتجب إحاطتها بثلاث علامات تنصيص (منفردة أو مزدوجة) في البداية والنهاية. أنظر المثال التالي: # Single line comments start with a number symbol. """ Multiline strings can be written using three "s, and are often used as documentation. """ دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن أنواع البيانات والعمليات الأرقام: 3 # => 3 العمليات الرياضية: 1 + 1 # => 2 8 - 1 # => 7 10 * 2 # => 20 35 / 5 # => 7.0 يوجد نوعان من القسمة في بايثون 3، الأولى تُسمى القسمة بعدد فاصل عائم “floating point division” ونَستخدم رمز القسمة المعروف / ، وناتج العملية هو دائما عدد حقيقي من النوع float: 10.0 / 3 # => 3.3333333333333335 أما النوع الثاني من القسمة فيُسمى القسمة الصحيحة “integer division” ونَستخدم الرمز // لهذا النوع، ويكون ناتج العملية دون الفاصلة والأرقام التي بعدها: 5 // 3 # => 1 5.0 // 3.0 # => 1.0 # يعمل هذا النوع من القسمة على الأعداد الحقيقية أيضا -5 // 3 # => -2 -5.0 // 3.0 # => -2.0 عملية باقي القسمة: 7 % 3 # => 1 عملية الأس: 2**3 # => 8 قاعدة أولوية العمليات حسب الأقواس: (1 + 3) * 2 # => 8 القيم المنطقية (لاحظ الحرف الكبير في البداية): True False عكس القيمة المنطقية باستخدام not: not True # => False not False # => True العمليات المنطقية (العمليات المنطقية حساسة لحالة الأحرف): True and False # => False False or True # => True القيمة المنطقية False تساوي الرقم 0، والقيمة المنطقية True تساوي الرقم 1: 0 and 2 # => 0 -5 or 0 # => -5 0 == False # => True 2 == True # => False 1 == True # => True -5 != False != True #=> True عملية فحص المساواة باستخدام ==: 1 == 1 # => True 2 == 1 # => False فحص عدم المساواة: 1 != 1 # => False 2 != 1 # => True المقارنات: 1 < 10 # => True 1 > 10 # => False 2 <= 2 # => True 2 >= 2 # => True 1 < 2 < 3 # => True 2 < 3 < 2 # => False تفحص عملية is إذا كان متغيران يشيران لنفس الكائن أم لا، ولكن العملية == تفحص إذا كانا بنفس القيمة أم لا: a = [1, 2, 3, 4] b = a b is a # => True b == a # => True b = [1, 2, 3, 4] b is a # => False b == a # => True تُنشَأ النصوص باستخدام علامات التنصيص المزدوجة أو الفردية: "This is a string." 'This is also a string.' تستطيع جمع النصوص ببعضها، ولكن حاول تجنب هذه الطريقة: "Hello " + "world!" # => "Hello world!" تستطيع دمج النصوص ببعضها دون استخدام + : "Hello " "world!" # => "Hello world!" من الممكن التعامل مع النص وكأنه مصفوفة من الحروف: "This is a string"[0] # => 'T' للحصول على طول نص نستخدم الدالة المضمنة len : len("This is a string") # => 16 تستطيع استخدام الدالة format لإجراء عملية التنسيق على النص: "{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated" تستطيع عند استخدام الدالة format ترقيم المدخلات حسب ترتيبها واستخدامها في تنسيق النص أكثر من مرة: "{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") # => "Jack be nimble, Jack be quick, Jack jump over the candle stick" أو باستخدام طريقة تسمية المدخلات: "{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna" تستطيع في البايثون 3 استخدام الطريقة القديمة في بايثون 2 لعمل تنسيق للنصوص: "%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way" None عبارة عن كائن: None # => None لا تستخدم فحص المساواة باستخدام رمز == للمقارنة مع None واستخدم عملية الفحص is بدلا منها: "etc" is None # => False None is None # => True None والرقم 0 والمتغيرات الفارغة من الأنواع strings، lists، dict، وtuples جميعها تُرادف القيمة المنطقية False، أما باقي القيم فهي True: # All other values are True bool(0) # => False bool("") # => False bool([]) # => False bool({}) # => False bool(()) # => False المتغيرات والتراكيب: تتوفّردالة خاصة للطباعة (الإخراج على الطرفية) وتسمى print: print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! يُطبَع سطر جديد تلقائيا عند استخدام الدالة print. تستطيع استخدام المعطى end لتغيير هذا الأمر وتحديد النص الذي تريده بدلا من السطر الجديد: print("Hello, World", end="!") # => Hello, World! للحصول على مدخلات من الطرفية نستخدم الدالة input: input_string_var = input("Enter some data: ") # Returns the data as a string ملاحظة/ في النسخ القديمة من البايثون، كانت الدالة input باسم raw_input. لا يوجد في البايثون تعريفات، ولكن يوجد إعطاء قيم مباشرة. الطريقة المتعارف عليها في تسمية المتغيرات هي الأحرف الصغيرة مع التسطير السفلي: some_var = 5 some_var # => 5 محاولة استخدام متغير لم يأخذ قيمة مسبقاً ينتج عنه خطأ، راجع كيفية معالجة الأخطاء تحت عنوان جمل التحكم. some_unknown_var # ينتُج خطأ من الصنف NameError تشبه القوائم المصفوفات في اللغات الأخرى: li = [] other_li = [4, 5, 6] نستخدم append لإضافة عناصر في نهاية القائمة: li.append(1) # li is now [1] li.append(2) # li is now [1, 2] li.append(4) # li is now [1, 2, 4] li.append(3) # li is now [1, 2, 4, 3] نستخدم الدالةpop لحذف العناصر من آخر القائمة. ترجع التعليمة أدناه القيمة 3 وتصبح مكونات القائمة [1, 2, 4]: li.pop() # => 3 and li is now [1, 2, 4] تعود القائمة إلى حالتها السابقة لتنفيذ الدالة pop بعد تنفيذ الدالة append على النحو التالي: li.append(3) # li is now [1, 2, 4, 3] again. تستطيع التعامل مع القائمة مثل المصفوفة من حيث الوصول لعناصرها: li[0] # => 1 li[-1] # => 3 في حال استخدام فهرس خارج حدود القائمة سينتج خطأ من نوع IndexError: li[4] # Raises an IndexError تستطيع استخدام مجال للحصول على جزء أكبر من القائمة بحيث نحدد فهرس البداية وفهرس النهاية. li[1:3] # => [2, 4] ملاحظة: فهرس النهاية غير مشمول في القيمة المرجعة، حيث يعدّ النمط المستخدم هو نمط نطاق مغلق-مفتوح. في حال عدم استخدام فهرس النهاية: li[2:] # => [4, 3] في حال عدم استخدام فهرس البداية: li[:3] # => [1, 2, 4] اختيار عنصر كل خطوتين ابتداء من العنصر الأول في القائمة: li[::2] # =>[1, 4] إرجاع كامل المصفوفة بطريقة عكسية: li[::-1] # => [3, 4, 2, 1] القاعدة العامة للاستعلامات السابقة في القوائم هي كالتالي(البداية start، النهاية end والخطوة step): # li[start:end:step] نسخ عميق (Deep Copy): li2 = li[:] # => li2 = [1, 2, 4, 3] عندما نفحص المساواة باستخدام عملية is كالتالي: (li2 is li) ستكون النتيجة False. لحذف عنصر من القائمة: del li[2] # li is now [1, 2, 3] لحذف أول عنصر في القائمة يساوي القيمة المدخلة في الدالة remove: li.remove(2) # li is now [1, 3] li.remove(2) # ValueError لأن القيمة غير موجودة إضافة عنصر في مكان معين في القائمة: li.insert(1, 2) # li is now [1, 2, 3] again الحصول على فهرس أول عنصر في القائمة يساوي القيمة المعطاة: li.index(2) # => 1 li.index(4) # ValueError لأن القيمة غير موجودة لإضافة قائمة لقائمة وإرجاع النتيجة كقائمة جديدة: li + other_li # => [1, 2, 3, 4, 5, 6] لتمديد قائمة وإضافة قائمة إليها: li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] لفحص وجود قيمة في القائمة: 1 in li # => True للحصول على حجم القائمة (عدد العناصر التي بها): len(li) # => 6 نوع البيانات Tuple تشبه القائمة ولكنها غير قابلة للتعديل (ثابتة-immutable): tup = (1, 2, 3) tup[0] # => 1 tup[0] = 3 # Raises a TypeError لاحظ أنه في حالة وجود عنصر واحد في tuple لابد من وضع فاصلة عادية بعد العنصر، أما في حالة وجود أكثر من عنصر فتصبح الفاصلة إضافية: type((1)) # => <class 'int'> type((1,)) # => <class 'tuple'> type(()) # => <class 'tuple'> تستطيع تنفيذ أغلب عمليات القوائم على النوع Tuple: len(tup) # => 3 tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) tup[:2] # => (1, 2) 2 in tup # => True تستطيع تفريغ (unpacking) محتويات Tuples وكذلك القوائم في متغيرات كما في الأمثلة التالية: a, b, c = (1, 2, 3) # a = 1, b = 2, c = 3 a, *b, c = (1, 2, 3, 4) # a = 1, b = [2, 3], c = 4 عند عدم استخدام الأقواس فإن نوع البيانات التلقائي الذي سيتم استخدامه هو Tuple: d, e, f = 4, 5, 6 تبديل قيم المتغيرات بطريقة سهلة: e, d = d, e # d = 5, e = 4 القواميس عبارة عن مؤشرات (مُخططات) من المفاتيح للقيم (كل مفتاح يؤشر على قيمة خاصة به). تعريف قاموس فارغ: empty_dict = {} تعريف قاموس بقيم مسبقة: filled_dict = {"one": 1, "two": 2, "three": 3} لاحظ أن المفاتيح في القواميس لابد أن يكون نوع بياناتها ثابتا (immutable) وذلك لضمان الحصول على مفتاح ثابت (لا تتغير قيمته). أنواع البيانات الثابتة والتي من الممكن استخدامها هي int , float, string, tuple. invalid_dict = {[1,2,3]: "123"} # => Raises a TypeError: unhashable type: 'list' valid_dict = {(1,2,3):[1,2,3]} # Values can be of any type, however. يمكن للقيم – عكس المفاتيح – أن تكون من أي نوع. للبحث عن قيم نستخدم الأقواس المعكوفة: filled_dict["one"] # => 1 للحصول على مفاتيح قاموس على شكل قائمة (الترتيب في القواميس غير ثابت): list(filled_dict.keys()) # => ["three", "two", "one"] للحصول على قيم قاموس على شكل قائمة: list(filled_dict.values()) # => [3, 2, 1] للتأكد من وجود مفتاح قاموس معين: "one" in filled_dict # => True 1 in filled_dict # => False في حالة استخدام مفتاح غير موجود للبحث في قاموس، فإن ذلك ينتج خطأ: filled_dict["four"] # KeyError استخدم الدالة get لتجنب الخطأ السابق: filled_dict.get("one") # => 1 filled_dict.get("four") # => None تدعم الدالة get إعادة قيمة تلقائية في حالة عدم وجود المفتاح: filled_dict.get("one", 4) # => 1 filled_dict.get("four", 4) # => 4 تضيف الدالة setdefault المفتاح المُمرر إلى القاموس في حالة عدم وجوده. تضيف التعليمة التالية مفتاحا باسم five وتعطيه قيمة 5، أما التعليمة الثانية فلا تحدت تغييرا على القاموس. filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 للإضافة إلى القاموس: filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} filled_dict["four"] = 4 # طريقة أخرى حذف المفتاح من القاموس: del filled_dict["one"] # Removes the key "one" from filled dict بعض طرق التفريغ في القواميس: {'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} {'a': 1, **{'a': 2}} # => {'a': 2} المجموعات: empty_set = set() some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} نوع البيانات الخاص بعناصر المجموعات لابد أن يكون ثابتا: invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' valid_set = {(1,), 1} للإضافة إلى المجموعة: filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} إجراء عملية التقاطع بين مجموعتين: other_set = {3, 4, 5, 6} filled_set & other_set # => {3, 4, 5} إجراء عملية الاتحاد بين مجموعتين: filled_set | other_set # => {1, 2, 3, 4, 5, 6} إجراء عملية الطرح بين مجموعتين: {1, 2, 3, 4} - {2, 3, 5} # => {1, 4} لإجراء عملية فرق التماثل بين مجموعتين: {1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} لفحص إذا كانت المجموعة على الشمال هي مجموعة تحتوي المجموعة على اليمين أم لا: {1, 2} >= {1, 2, 3} # => False عكس المثال السابق: {1, 2} <= {1, 2, 3} # => True فحص وجود قيمة في مجموعة: 2 in filled_set # => True 10 in filled_set # => False جمل التحكم some_var = 5 جملة if: if some_var > 10: print("قيمة المتغيّر أكبر تماما من 10") elif some_var < 10: # هذه الجملة اختيارية print("قيمة المتغيّر أصغر من 10") else: # هذه الجملة اختيارية print("قيمة المتغيّر تساوي 10") جملة for: for animal in ["dog", "cat", "mouse"]: print("{} is a mammal".format(animal)) لاحظ استخدام الدالة format في جملة for السابقة. يمكن أيضا تطبيق الجملة على مجال عددي range: for i in range(4): print(i) for i in range(4, 8): print(i) for i in range(4, 8, 2): print(i) جملة while: x = 0 while x < 4: print(x) x += 1 # اختصارا ل x = x + 1 معالجة الأخطاء باستخدام try/except (استخدم raise لتوليد الخطأ): try: raise IndexError("This is an index error") except IndexError as e: pass except (TypeError, NameError): pass else: print("All good!") finally: print("We can clean up resources here") ملاحظات حول معالجة الأخطاء: Pass تعني عدم وجود عملية للتنفيذ. تستطيع سرد أكثر من نوع خطأ في جملة except. تستطيع استخدام جملة else مع try/except اختياريا (تنفذ في حالة كانت الشفرة البرمجية في try لم تُصدر أي خطأ). نستخدم جملة finally لتنفيذ شفرة برمجية بعد try/except بغض النظر عن وجود أخطاء أم لا، وعادةً يُعاد تحرير المصادر المستخدمة. بدلا من استخدام جملة finally لإعادة تحرير المصادر المستخدمة، تستطيع استخدام جملة with: with open("myfile.txt") as f: for line in f: print(line) تُقدم البايثون كائنًا متُعددًا (Iterable) وهو كائن مجرد (عام) يُتعامل معه مثل sequence. فمثلا الكائن المُرجع من الدالة range هو كائن مُتعدد: filled_dict = {"one": 1, "two": 2, "three": 3} our_iterable = filled_dict.keys() print(our_iterable) # => dict_keys(['one', 'two', 'three']). تستطيع المرور على عناصر الكائن المتعدد والتعامل معها: for i in our_iterable: print(i) # Prints one, two, three على الرغم من خاصية الكائن المتعدد، إلا أنه لا تستطيع استخدام الفهرس معه: our_iterable[1] # Raises a TypeError تستطيع الحصول من خلال الكائن المُتعدد على كائن iterator منه بحيث تستطيع المرور على عناصره: our_iterator = iter(our_iterable) يحتفظ الكائن iterator بحالته كلما تم استخدامه، فمثلا، باستخدام وظيفة next تستطيع الحصول على العنصر التالي في هذا الكائن: next(our_iterator) # => "one" next(our_iterator) # => "two" next(our_iterator) # => "three" بعد الحصول على كافة عناصر iterator فإن استخدام الدالة next سيعيد خطأ: next(our_iterator) # Raises StopIteration تستطيع الحصول على كافة عناصر iterator دفعة واحدة على شكل قائمة وذلك باستخدام الدالة list : list(filled_dict.keys()) # => Returns ["one", "two", "three"] الدوال نستخدم الكلمة def في تعريف الدالة، ونستخدم كلمة return في إرجاع النتيجة: def add(x, y): print("x is {} and y is {}".format(x, y)) return x + y تطبع الدالة السابقة قيمتيْ المعامليْن المُمرّرين لها وتعيد ناتج جمعهما: add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 يمكن أيضا استدعاء الدالة بذكر أسماء المعاملات (شرط الترتيب غير مطلوب هنا للمعاملات): add(y=6, x=5) تستطيع تعريف دالة باستقبال عددًا غير محدد من المعاملات: def varargs(*args): return args varargs(1, 2, 3) # => (1, 2, 3) من الممكن استخدام المعاملات المُسماة لاستقبال عدد غير محدد من المعاملات أيضا: def keyword_args(**kwargs): return kwargs keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} كما نستطيع دمج الطريقتين في نفس الدالة: def all_the_args(*args, **kwargs): print(args) print(kwargs) all_the_args(1, 2, a=3, b=4) # => (1, 2) {"a": 3, "b": 4} توجد طريقة أخرى لاستدعاء الدوال باستخدام args/kwargs وذلك عندما تكون المعطيات من النوع tuple أو قاموس: args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} all_the_args(*args) # equivalent to foo(1, 2, 3, 4) all_the_args(**kwargs) # equivalent to foo(a=3, b=4) all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) يمكن أيضا إرجاع نتيجة من قيم متعددة على شكل tuple: def swap(x, y): return y, x x = 1 y = 2 x, y = swap(x, y) # => x = 2, y = 1 يختلف المتغيّر في نطاق scope الدالة عن المتغيّرات العامة Global: x = 5 def set_x(num): x = num # => 43 print(x) # => 43 تُستخدَم الكلمة المفتاحية global لتعريف متغيّر عام من داخل الدالة: def set_global_x(num): global x print(x) # => 5 x = num # هذا المتغير يمثل المتغير على النطاق العام وقيمته الان 6 print(x) # => 6 set_x(43) set_global_x(6) تعدّ الدوال في بايثون كائنات من الفئة الأولى: def create_adder(x): def adder(y): return x + y return adder add_10 = create_adder(10) add_10(3) # => 13 كما يمكنك تعريف دوال غير مسمّاة Anonymous functions: (lambda x: x > 2)(3) # => True (lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 ويمكنك تمرير الدالة معاملا لدالة أخرى: list(map(add_10, [1, 2, 3])) # => [11, 12, 13] list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] تستطيع استخدام مبدأ “تفهيم القائمة” للحصول على نفس نتيجة الدوال map و filter: [add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] تستطيع استخدام مبدأ “تفيهم القاموس” و “تفهيم المجموعة” كذلك: {x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} {x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} الوحدات Modules الوحدات في بايثون عبارة عن ملفات بايثون عادية. تستطيع أن تكتب الوحدة الخاصة بك وتستوردها في الشفرة البرمجة الخاصة بمشروعك. اسم الوحدة سيكون نفس اسم الملف الذي أنشأته لهذا الغرض. تُستورَد الوحدات بالطريقة التالية: import math print(math.sqrt(16)) # => 4.0 تستطيع الحصول على دوال محددة من الوحدات: from math import ceil, floor print(ceil(3.7)) # => 4.0 print(floor(3.7)) # => 3.0 تستطيع استيراد جميع الدوالّ من الوحدة دفعة واحدة ولكن هذا الأمر غير منصوح به: from math import * تستطيع اختصار أسماء الوحدات عند استيرادها: import math as m math.sqrt(16) == m.sqrt(16) # => True تُستخدَم الدالة المضمنة dir لمعرفة مكان ملف الوحدة. import math dir(math) إذا كان لديك ملف بايثون باسم math في نفس المجلد الذي يوجد به ملف العمل الخاص بك، فإن الملف math هو الذي سيُحمَّل ويُستورد بدلا من الوحدة التلقائية المضمنة في البايثون باسم math ذلك لأن الأولوية في حال تشابه الأسماء هي للملفات في مجلد العمل المحلي أو الحالي. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن الأصناف Classes نستخدم كلمة class لتعريف صنف: class Human: لتعريف خاصية للصنف (هذه الخاصية تكون مُشاركة بين كل العناصر المتولدة من هذا الصنف): species = "H. sapiens" init هو المشيّدات Constructor الأساسي ويُستدعى عند توليد عنصر من الصنف. التسطير السفلي المكرر مرتين قبل كلمة init وبعدها يدل على أن هذا الكائن أو الخاصية يستخدمه بايثون ولا يجب علينا استخدامها مباشرة. def __init__(self, name): # إعطاء قيمة المعطى للخاصية الموجودة في الصنف self.name = name # قيمة مبدئية self._age = 0 الدالة say هي تابع عيّنة Instance method، أي أن لكل كائن نسخة خاصة به منها. تأخذ هذه التوابع أن self في أول معامل يُمرّر لها: def say(self, msg): print ("{name}: {message}".format(name=self.name, message=msg)) def sing(self): return 'yo... yo... microphone check... one two... one two...' يمكن أيضا تعريف تابع متشارك بين كل كائنات الصنف: @classmethod def get_species(cls): return cls.species نستطيع كذلك تعريف تابع ساكن يُستدعى دون الحاجة لإنشاء كائن من الصنف: @staticmethod def grunt(): return "*grunt*" يحوّل التعليمة property@ دالة إلى خاصيّة للقراءة فقط لها نفس اسم الدالة، لتؤدّي بالتالي وظيفة المسترجعات Getters. @property def age(self): return self._age يمكننا جعل الخاصية قابلة للتعيين لتصبح الدالة تعمل معدّلا Setter: @age.setter def age(self, age): self._age = age كما يمكننا السماح بحذفها: @age.deleter def age(self): del self._age يقوم مُفسر البايثون بتنفيذ كافة اشيفرة البرمجية في ملف الوحدة الذي يقرأه، ومن خلال الخاصية name نتأكد من أن كتلة الشفرة البرمجية التي في جملة الشرط ستُنفَّذ في حال كانت الوحدة هي البرنامج الرئيسي المُنفذ: if __name__ == '__main__': i = Human(name="Ian") i.say("hi") # "Ian: hi" j = Human("Joel") j.say("hello") # "Joel: hello" # استدعاء دالة الفئة i.say(i.get_species()) # "Ian: H. sapiens" # تغيير الخاصية المشتركة Human.species = "H. neanderthalensis" i.say(i.get_species()) # => "Ian: H. neanderthalensis" j.say(j.get_species()) # => "Joel: H. neanderthalensis" # استدعاء الدالة الساكنة print(Human.grunt()) # => "*grunt*" لا تستطيع استدعاء الدالة الساكنة من خلال العنصر المتولد i لأن استدعاءها بهذه الطريقة سيضيف self كمعامل لها مما سينتج عنه خطأ: print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given i.age = 42 i.say(i.age) # => "Ian: 42" j.say(j.age) # => "Joel: 0" del i.age # i.age # => this would raise an AttributeError ترجمة -وبتصرف- للمقال Learn X in Y minutes Where X=Python3 اقرأ أيضا: تعلم لغة بايثون1 نقطة
-
نعم .. عن طريق لغه برمجه cross platform مثل بايثون تقدر تعمل ابلكيشن تشتغل ويندوز ولينكس وتقدر تشتغل كويب وتقدر تشتغل كاندرويد ليها فريمات كتير جدا ابحث عنها1 نقطة
-
اولا يجب ان نفهم اهمية جملة return بعدها سنوضح متى يمكن ان نستخدمها ضمن الدالة main بشكل عام جملة return تعني بأن الدالة (دالة main او اي دالة اخرى) ستقوم بإرجاع متغير من نوع int (يمكن طبعا إرجاع اي نوع اخر من البيانات مثل bool, double وغيره) - كمثال، لو كان لدينا دالة تقوم بجمع عددين، بالتالي فإن السلوك المتوقع من هذه الدالة هو ان تقوم بحساب ناتج عملية الجمع. هذا الناتج يمكن طباعته للمستخدم مباشرة void add(int x, int b) { int sum = x + b; count<<sum; } كما يمكن ايضا استخدام ناتج العملية في اقسام اخرى من الكود، إذا كيف سنتمكن من الوصل للمتغير sum المعرف ضمن دالة الجمع؟ في الحقيقة لا يمكن الوصول له مباشرة، لكن وبما ان كل ما يهمني من دالة الجمع هو ناتج الجمع فقط، اذا يجب ان تقوم هذه الدالة بالعملية الحسابية ثم توصل الناتج لي (ولا يهمني الكود او التعقيد الموجود داخلها، كل ما يهمني هو الناتج). لذلك سنعيد كتابتها مرة اخرى int add(int x, int b) { int sum = x + b; return sum; } الآن اصبح لدي كود متكامل استطيع استخدامه في اي برنامج اقوم بتطبيقه، كل ما علي هو ان استدعي الدالة واعطيها المتغيريين x ، y. ثم ستقوم هي بالعمليات الحسابية نيابية عني. void main() { int number1; int number2; cout<<"Enter first number:"; cin>>number1; cout<<"Enter second number:"; cin>>number2; int sum = add(number1, number2); cout<<"Sum = "<<sum; } الأن اصبح مفهوم return واضحا، اي بمعنى نقوم بإرجاع قيمة (int, double float, bool) عندما نحتاج فعليا لهذه القيمة. السؤال الآن: متى نستخدم return مع الدالة main؟ الجواب: عندما نحتاج فعليا لهذه القيمة. السؤال الآخر: متى نحتاج لهذه القيمة؟ الجواب: عندما نريد توصيف اكثر عن سلوك هذه الدالة، بمعنى عند حدوث شرط معين يمكن لهذه الدالة ان ترجع القيمة 0، وعند حدوث شرط اخر يمكن ان ترجع القيمة 1 وهكذا. // This program will divide two number // if the first number or second number is less than 0, then do not complete the method. // if the second number is 0, do not complete the method int main() { int number1; int number2; cout<<"Enter first number:"; cin>>number1; cout<<"Enter second number:"; cin>>number2; if ( number1 < 0 ) return -1; // do not complete the method and return -1 to the user, so he know number1 < 0 if ( number2 < 0) return -2; // do not complete the method and return -2 to the user, so he know number2 < 0 if ( number2 == 0) return -3; // do not complete the method and return -3 to the user, so he know number2 == 0 return number1/number2; // data is correct, we can return the result } لنتخيل ان البرنامج الذي قمنا بتصميمه هو برنامج قابل لاعادة الاستخدام من قبل المبرمجين الاخرين، اذا كيف يمكن لبرنامجنا ان يكون سليماً وأن يقوم بالعمليات الحسابية فقط عندما تكون البيانات صحيحة، الجواب: هو بالطريقة الموضحة بالمثال. عندما يقوم شخص اخر باستخدام هذا الكود لاحقا، سوف يعرف بأنه اذا تم ارجاع القيمة -1 بالتالي فان العدد الاول سالب وهكذا. عند استخدامنا للغة سي او سي بلس بلس، سنقوم غالبا في التحقق من قيمة عملية معينة (مثل فتح ملف) اذا كانت تساوي 0، فإن العملية ناجحة بدون اخطاء، لكن اذا كانت -1 مثلا فتعني ان الملف مفتوح مسبقا او غير موجود الى ما هنالك من الاحتمالات. مما يمكننا من كتابة البرامج بالشكل السليم، ضمن تحقق جميع الشروط اللازمة لذلك. اخيراً: ستتضح جميع هذه المفاهيم مع كثرة الممارسة، لانه ضمن الامثلة البسيطة غالبا ستكون هذه المفاهيم عبىء علينا، لكن مع تقدمنا واستخدمنا لمفاهيم اعمق في البرمجة سنجد الحل في هذه المفاهيم التي كانت مزعجة يوماً ما. بالتوفيق،،،1 نقطة
-
عندما نكتب int main() فيجب كتابة return 0; في البرنامج للدلالة على أن كل شيء تم على مايرام. كتابة اي قيمة غير 0 تدل على أن هناك خطأ ما. بينما عند كتابة void main() فلا يجب كتابة return 0; وعموما، ليس هناك فرق (كبير جدا). يفضل غالبا استخدام int main() { /* أكواد البرنامج*/ return 0; }1 نقطة
-
شكرا جدا لمجهودك الرائع.. لو سمحت كان عندي سؤال انا عملت مدونة اجنبيه وضفت ليها دومين مجاني ga. لمدة سنه ..وفيها 19 موضوع .. كم من الوقت علشان تتقبل في ادسنس؟ او لو عندك طريقه اعمل موقع ناجح ويقبله ادسنس؟1 نقطة