تعلم معنا .. الدليل السريع إلى لغة البرمجة بايثون Python 3

في بدايات التسعينات، قام Guido van Rossum بإنشاء لغة البايثون. تُعتبر البايثون من أشهر لغات البرمجة حاليا، ولها حضور واسع في العديد من المجالات التطبيقية والعلمية، وتتميز بسهولة شفرتها البرمجية وسرعة تعلمها مع متانة وقوة تضاهي اللغات الأخرى.

سوف نتناول في هذا المقال المواضيع التالية:

  1. التعليقات.
  2. أنواع البيانات.
  3. المتغيرات والتراكيب.
  4. جمل التحكم.
  5. الدوال Functions.
  6. الوحدات.
  7.  الفئات.

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

التعليقات

تبدأ التعليقات ذات السطر الواحد برمز #، أما التعليقات التي تحتوي أكثر من سطر فتجب إحاطتها بثلاث علامات تنصيص (منفردة أو مزدوجة) في البداية والنهاية. أنظر المثال التالي:

# Single line comments start with a number symbol.

""" Multiline strings can be written
    using three "s, and are often used
    as documentation.
"""

أنواع البيانات والعمليات

الأرقام:

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")

ملاحظات حول معالجة الأخطاء:

  1. Pass تعني عدم وجود عملية للتنفيذ.
  2. تستطيع سرد أكثر من نوع خطأ في جملة except.
  3. تستطيع استخدام جملة else مع try/except اختياريا (تنفذ في حالة كانت الشفرة البرمجية في try لم تُصدر أي خطأ).
  4. نستخدم جملة 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 ذلك لأن الأولوية في حال تشابه الأسماء هي للملفات في مجلد العمل المحلي أو الحالي.

الأصناف 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

اترك تعليقاً

لن ينشر بريدك الإلكتروني.