مب

مبانی در Python

113 تمرین

درباره‌ی مبانی

Python یک زبان برنامه‌نویسی پویا و به‌شدت نوع‌دار است. این زبان هم از تایپ اردکی و هم از تایپ تدریجی بهره می‌برد، آن هم از طریق نشانه‌های نوع. سبک‌های برنامه‌نویسی دستوری، اعلانی (مثلاً تابعی) و شیءگرا همگی پشتیبانی می‌شوند، اما در باطن در Python همه‌چیز یک شیء است.

Python تأکید زیادی بر خوانایی کد دارد و (مشابه Haskell) از تورفتگی معنادار برای مشخص کردن تعریف تابع، متد و کلاس استفاده می‌کند.

Python توسط Guido van Rossum ساخته شد و نخستین بار در ۱۹۹۱ منتشر شد. بنیاد نرم‌افزار Python منابع توسعه‌ی Python و CPython را مدیریت و هدایت می‌کند و پیشنهادهای تغییر زبان را از اعضا جامعه، از طریق پیشنهادهای بهبود Python یا PEPها دریافت می‌کند.

مستندات کامل نسخه‌ی فعلی را می‌توانید در docs.python.org پیدا کنید.


این نخستین مفهوم، ۴ ویژگی اصلی زبان Python را معرفی می‌کند:

  1. انتساب نام (متغیرها و ثابت‌ها)،
  2. توابع (کلیدواژه‌ی def و کلیدواژه‌ی return)،
  3. توضیحات، و
  4. داک‌استرینگ‌ها.
Note

به‌طور کلی، محتوا، آزمون‌ها و ابزارهای تحلیلگرِ مسیر Python از قراردادهای سبکی که در PEP ۸ و PEP ۲۵۷ برای سبک کد Python آمده است پیروی می‌کنند، با این پیشنهاد (قوی) که هیچ اسم متغیر تک‌حرفی به کار نرود.

ذن Python (PEP ۲۰) و Pythonic یعنی چه؟ فلسفه‌های دیگری را هم بیان می‌کنند.

در مسیر Python، متغیرها همیشه با snake_case و ثابت‌ها با SCREAMING_SNAKE_CASE نوشته می‌شوند.

انتساب نام (متغیرها و ثابت‌ها)

در Python هیچ کلیدواژه‌ای برای ساختن متغیرها یا ثابت‌ها به کار نمی‌رود. در عوض، برنامه‌نویسان می‌توانند اسم‌ها (که به آن‌ها متغیر هم می‌گویند) را با عملگر انتساب = به هر نوع شیئی متصل کنند: <name> = <value>. یک اسم می‌تواند در طول عمرش بارها دوباره به مقادیر مختلف (انواع شیء متفاوت) انتساب داده شود.

برای مثال، my_first_variable را می‌توان با = بارها دوباره انتساب داد و با هر بازانتساب می‌تواند به انواع شیء متفاوتی اشاره کند:

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

>>> import collections
>>> my_first_variable = collections.Counter([1,1,2,3,3,3,4,5,6,7]) # <--Now my_first_variable has been re-bound to a Counter object.
>>> print(type(my_first_variable))
<class 'collections.Counter'>

>>> print(my_first_variable)
Counter({3: 3, 1: 2, 2: 1, 4: 1, 5: 1, 6: 1, 7: 1})

ثابت‌ها

ثابت‌ها اسم‌هایی هستند که قرار است در یک برنامه فقط یک بار انتساب داده شوند. بهتر است در سطح ماژول (فایل) تعریف شوند و معمولاً برای همه‌ی توابع و کلاس‌های برنامه قابل مشاهده‌اند. استفاده از SCREAMING_SNAKE_CASE نشان می‌دهد که نباید به اسم دوباره انتساب داده شود یا مقدارش تغییر کند.

# All caps signal that this is intended as a constant.
MY_FIRST_CONSTANT = 16

# Re-assignment will be allowed by the compiler & interpreter,
# but this is VERY strongly discouraged.
# Please don't do this, it could create problems in your program!
MY_FIRST_CONSTANT = "Some other value"

توابع

در Python، واحدهای کارکرد در توابع کپسوله می‌شوند، که خودشان شیء هستند (این لاک‌پشت‌ها تا بینهایت است).

توابع می‌توانند به‌تنهایی اجرا شوند، به‌عنوان آرگومان به توابع دیگر داده شوند، تودرتو شوند یا به یک کلاس متصل گردند. وقتی توابع به اسم یک کلاس متصل می‌شوند، به آن‌ها متد می‌گویند. توابع و کلاس‌های مرتبط (همراه با متدهایشان) می‌توانند در یک فایل یا ماژول یکسان گروه‌بندی شوند و به‌صورت بخشی یا کامل برای استفاده در برنامه‌های دیگر وارد شوند.

کلیدواژه‌ی 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 
# the variable 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 mis-match 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.'

# Because a string is an instance of the str class, methods can also be called on them "directly".
>>> start_text = "my silly sentence for examples."
>>> start_text.upper()  # <--Calling the upper() method on start_text directly.
'MY SILLY SENTENCE FOR EXAMPLES.'

# Alternatively, we can skip the variable assignment (although this gets messy quick).
>>> "my silly sentence for examples.".upper()
'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 از نشانه‌های توضیح چندخطی پشتیبانی نمی‌کند. هر خط از یک بلوک توضیح باید با نویسه‌ی # شروع شود.

مفسر توضیحات را نادیده می‌گیرد:

# This is a single line comment.

x = "foo"  # This is an in-line comment.

# This is a multi-line
# comment block over multiple lines --
# these should be used sparingly.

داک‌استرینگ‌ها

نخستین دستور در بدنه‌ی یک تابع می‌تواند به‌صورت اختیاری یک داک‌استرینگ باشد که هدف تابع یا شیء را به‌طور مختصر خلاصه می‌کند. داک‌استرینگ‌ها با سه علامت نقل‌قول دوگانه (""") و در همان سطحی که بلوک کد تورفته است، تورفته، اعلام می‌شوند:

# 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

داک‌استرینگ‌ها را ابزارهای خودکار مستندسازی می‌خوانند و با فراخوانی ویژگی ویژه‌ی .__doc__ روی اسم تابع، متد یا کلاس بازگردانده می‌شوند. برای برنامه‌ها در هر اندازه‌ای که به مستندسازی نیاز دارند توصیه می‌شوند و قراردادهایشان در PEP۲۵۷ آمده است.

داک‌استرینگ‌ها می‌توانند به‌عنوان آزمون‌های واحد سبک هم عمل کنند که PyTest یا واردکردن ماژول doctest می‌تواند آن‌ها را بخواند و اجرا کند. آزمون‌نویسی و doctest در مفهوم بعدی بررسی می‌شوند.

# 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.

...

# Printing the __doc__ attribute of the built-in type: str.
>>> print(str.__doc__)
str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or
errors is specified, then the object must expose a data buffer
that will be decoded using the given encoding and error handler.
Otherwise, returns the result of object.__str__() (if defined)
or repr(object).
encoding defaults to 'utf-8'.
errors defaults to 'strict'.
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

مبانی را یاد بگیرید