Python هي لغة برمجة ديناميكية وصارمة في أنماطها. وهي تستعين بكلٍّ من التنميط البطّي والتنميط التدريجي عبر تلميحات النوع.
وبينما تدعم Python أساليب برمجية مختلفة متعددة، فإن كل شيء في Python يُعدّ كائنًا داخليًا. ويشمل ذلك الأعداد والسلاسل النصية والمصفوفات، وحتى الدوال.
سنغوص أكثر في معنى كل ذلك بينما نمضي في المسار.
يقدّم لك هذا التمرين الأول أربع ميزات رئيسية في لغة Python:
def والكلمة المفتاحية return)،بشكل عام، يتبع المحتوى والاختبارات وأدوات التحليل الخاصة بمسار Python اصطلاحات الأسلوب الموضحة في PEP 8 وPEP 257 لأسلوب كتابة كود Python، مع اقتراح إضافي (قوي) بعدم وجود أسماء متغيرات من حرف واحد أو متغيرات باسم "_".
وفي مسار Python، تُكتب المتغيرات دائمًا بأسلوب snake_case، وتُكتب الثوابت بأسلوب SCREAMING_SNAKE_CASE.
يستطيع المبرمجون ربط الأسماء (وتُسمّى أيضًا المتغيرات) بأي نوع من الكائنات باستخدام عامل الإسناد =: <name> = <value>.
ويمكن إعادة إسناد الاسم (أو إعادة ربطه) إلى قيم مختلفة (أنواع كائنات مختلفة) على مدار عمره.
>>> my_first_variable = 1 #<-- my_first_variable bound to an integer object of value one.
>>> my_first_variable = 2 #<-- my_first_variable re-assigned to integer value 2.
>>> print(type(my_first_variable))
<class 'int'>
>>> print(my_first_variable)
2
>>> my_first_variable = "Now, I'm a string." #<-- You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
<class 'str'>
>>> my_first_variable = 'You can call me "str".' #<-- Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
You can call me "str".
الثوابت أسماء يُقصد بها أن تُسند مرة واحدة فقط في البرنامج.
ويُفضّل تعريفها على مستوى الوحدة (الملف)، وعادةً ما تكون مرئية لجميع الدوال والأصناف في البرنامج.
واستخدام SCREAMING_SNAKE_CASE يشير إلى أنه لا ينبغي إعادة إسناد الاسم أو تغيير قيمته.
تبدأ الكلمة المفتاحية def تعريف دالة.
ويمكن أن يكون لكل دالة صفر أو أكثر من المعاملات الرسمية بين الأقواس الهلالية ()، متبوعة بنقطتين :.
وتبدأ عبارات جسم الدالة في السطر الذي يلي def، ويجب أن تكون مُزاحة في كتلة.
# The body of a function is indented by 2 spaces, & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
total = number_one + number_two
print(total)
>>> add_two_numbers(3, 4)
7
# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
... result = number_one + number_two + number_three # This was indented by 4 spaces.
... print(result) #this was only indented by 3 spaces
...
...
File "<stdin>", line 3
print(result)
^
IndentationError: unindent does not match any outer indentation level
تُرجع الدوال قيمة أو كائنًا صراحةً عبر الكلمة المفتاحية return:
# Function definition on first line, explicit return used on final line.
>>> def add_two_numbers(number_one, number_two):
return number_one + number_two
# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7
# Assigning the function call to a variable and printing it
# will also return the value.
>>> sum_with_return = add_two_numbers(5, 6)
>>> print(sum_with_return)
11
الدوال التي لا يتبع فيها return تعبير صريح ستُرجع ضمنيًا كائن None.
وسنغطي تفاصيل None في تمرين لاحق.
وبغرض هذا التمرين وهذا الشرح، فإن None عنصر نائب يمثّل لا شيء، أو العدم:
# This function will return `None`
def square_a_number(number):
square = number * number
return # <-- note that this return is not followed by an expression
# Calling the function in the Python shell appears
# to not return anything at all.
>>> square_a_number(2)
>>>
# Using print() with the function call shows that
# the function is actually returning the **None** object.
>>> print(square_a_number(2))
None
والدوال التي تحذف return ستُرجع أيضًا ضمنيًا كائن None.
وهذا يعني أنه إذا لم تستخدم return في دالة، فستُرجع Python كائن None نيابةً عنك.
# This function omits a return keyword altogether.
def add_two_numbers(number_one, number_two):
result = number_one + number_two
>>> add_two_numbers(5, 7)
>>> print(add_two_numbers(5, 7))
None
# Assigning the function call to a variable and printing
# the variable will also show None.
>>> sum_without_return = add_two_numbers(5, 6)
>>> print(sum_without_return)
None
تُستدعى الدوال بالنداء عليها باستخدام اسمها متبوعًا بـ ().
ويُستخدم الترميز النقطي (.) لاستدعاء الدوال المعرّفة داخل صنف أو وحدة.
>>> def raise_to_power(number, power):
... return number ** power
...
>>> raise_to_power(3,3) # <--Invoking the function with the arguments 3 and 3.
27
# A mismatch between the number of parameters and the number of arguments will raise an error.
>>> raise_to_power(4,)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: raise_to_power() missing 1 required positional argument: 'power'
# Calling methods or functions in classes and modules.
>>> start_text = "my silly sentence for examples."
>>> str.upper(start_text) # <--Calling the upper() method from the built-in str class on start_text.
'MY SILLY SENTENCE FOR EXAMPLES.'
# Importing the math module
>>> import math
>>> math.pow(2,4) # <--Calling the pow() function from the math module.
16.0
تبدأ التعليقات في Python بعلامة # ليست جزءًا من سلسلة نصية، وتنتهي عند نهاية السطر.
وعلى خلاف كثير من لغات البرمجة الأخرى، فإن Python لا تدعم علامات التعليق متعدد الأسطر.
ويجب أن يبدأ كل سطر في كتلة التعليق بالمحرف #.
يمكن أن تكون العبارة الأولى في جسم الدالة سلسلة توثيقية، تلخّص بإيجاز غرض الدالة أو الكائن. وتُعرَّف السلاسل التوثيقية باستخدام ثلاث علامات اقتباس مزدوجة (""") مُزاحة عند المستوى نفسه من كتلة الكود:
# An example from PEP257 of a multi-line docstring
# reformatted to use Google style non-type hinted docstrings.
# Some additional details can be found in the Sphinx documentation:
# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword Arguments:
real (float): The real part of the number (default 0.0)
imag (float): The imaginary part of the number (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
تقرأ السلاسل التوثيقية أدوات التوثيق الآلية مثل Sphinx، وتُرجَع عند استدعاء السمة الخاصة .__doc__ على اسم الدالة أو الطريقة أو الصنف.
وتُوضَّح الاصطلاحات العامة للسلاسل التوثيقية في PEP257، لكن الصيغ الدقيقة تختلف من مشروع إلى آخر ومن فريق إلى آخر.
وتحاول تمارين المفاهيم في Exercism اتباع أسلوب Google للكود غير المزوّد بتلميحات النوع.
ويمكن أن تعمل السلاسل التوثيقية أيضًا كاختبارات وحدة خفيفة، وسنغطيها في تمرين لاحق.
# An example on a user-defined function using a Google style docstring.
>>> def raise_to_power(number, power):
"""Raise a number to an arbitrary power.
Parameters:
number (int): The base number.
power (int): The power to raise the base number to.
Returns:
int: The number raised to the specified power.
Takes a number and raises it to the specified power, returning the result.
"""
return number ** power
...
# Calling the .__doc__ attribute of the function and printing the result.
>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.
Parameters:
number (int): The base number.
power (int): The power to raise the base number to.
Returns:
int: The number raised to the specified power.
Takes a number and raises it to the specified power, returning the result.
ستكتب بعض الكود لمساعدتك على طهي لازانيا رائعة من كتاب الطبخ المفضل لديك.
لديك خمس مهام، جميعها مرتبطة بطهي وصفتك.
لقد بدأنا لك تعريف الدالة الأولى في ملف البداية، لكنك ستحتاج إلى كتابة تعريفات الدوال المتبقية بنفسك. كما ستحتاج إلى تعريف أي ثوابت بنفسك. اقرأ أسطر التعليق #TODO في ملف البداية بعناية. بمجرد أن تنتهي من مهمة، احذف تعليق TODO.
عرّف الثابت EXPECTED_BAKE_TIME الذي يمثل عدد الدقائق التي يجب أن تخبز فيها اللازانيا في الفرن.
وفقًا لكتاب الطبخ لديك، يجب أن تبقى اللازانيا في الفرن لمدة 40 دقيقة:
>>> print(EXPECTED_BAKE_TIME)
40
أكمل الدالة bake_time_remaining() التي تأخذ عدد الدقائق الفعلي الذي قضته اللازانيا في الفرن كوسيط، وتُرجع عدد الدقائق التي ما زالت اللازانيا تحتاجها لتخبز بناءً على الثابت EXPECTED_BAKE_TIME.
>>> bake_time_remaining(30)
10
عرّف الدالة preparation_time_in_minutes() التي تأخذ number_of_layers الذي تريد إضافته إلى اللازانيا كوسيط، وتُرجع عدد الدقائق التي ستقضيها في تحضيرها.
افترض أن كل طبقة تستغرق دقيقتين للتحضير.
>>> def preparation_time_in_minutes(number_of_layers):
...
...
>>> preparation_time_in_minutes(2)
4
عرّف الدالة elapsed_time_in_minutes() التي تأخذ معاملين كوسائط:
number_of_layers (عدد الطبقات المضافة إلى اللازانيا)elapsed_bake_time (عدد الدقائق التي قضتها اللازانيا بالفعل في الخَبز في الفرن).يجب أن تُرجع هذه الدالة إجمالي الدقائق التي قضيتها في المطبخ تطبخ، أي زمن التحضير أثناء رصّ الطبقات زائد الزمن الذي قضته اللازانيا في الخَبز في الفرن.
>>> def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
...
...
>>> elapsed_time_in_minutes(3, 20)
26
عُد إلى الوصفة وأضف "ملاحظات" على شكل توثيقات الدوال.
def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time):
"""Calculate the elapsed cooking time.
Parameters:
number_of_layers (int): The number of layers in the lasagna.
elapsed_bake_time (int): Time the lasagna has been baking in the oven.
Returns:
int: The total time elapsed (in minutes) preparing and baking.
This function takes two integers representing the number of lasagna
layers and the time already spent baking the lasagna. It calculates
the total elapsed minutes spent cooking (preparing + baking).
"""
سجّل في Exercism لتتعلّم وتتقن Python عبر 17 مفهومًا146 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.