قواعد زبان پایتون
مجموعهٔ قوانین زبان برنامهنویسی پایتون مجموعهٔ قوانین هستند که میتوان برنامههایی قابل فهم برای ماشین به این زبان نوشت. در طراحی این زبان به شدت سعی شدهاست که به سادگی قابل فهم باشد؛ این به این مفهوم است که سعی شدهاست که مجموعهٔ دستورها آن به نگارش دستورها در زبان انسان نزدیک باشد.
فلسفه طراحی
پایتون زبانی قابل فهم و بسیار خواندنی است. این یک طرح بصری نسبتاً نامشخص است و از کلمات کلیدی انگلیسی استفاده میکند که اغلب در سایر زبانها از حروف نگارشی استفاده میکنند. پایتون قصد دارد ساده و سازگار با طراحی نحو آن باشد، به گونهای که در مانترا محصور شده و «برای انجام آن باید یک روش — و ترجیحاً فقط یک راه — وجود داشته باشد» از طریق ذن پایتون.
این مانترا عمداً مخالف مانترا پرل و روبی است، «در این زبانها، بیش از یک راه برای انجام آن وجود دارد».
واژههای کلیدی
واژههای کلیدی واژههایی هستند که ساختار قواعد این زبان را مشخص میکنند؛ لذا نمیتوان از آنها به عنوان نام متغیرها استفاده کرد.
and
as
assert
async
await
break
class
continue
def
del
elif
else
except
False
finally
for
from
global
if
import
in
is
lambda
None
nonlocal
not
or
pass
raise
return
True
try
while
with
yield
- یادداشتها
- ↑
async
وawait
از پایتون ۳٫۵، اضافه شدهاست. - ↑
True
,False
وnonlocal
از پایتون ۳ اضافه شدهاست.
دندانه دار نوشتن
برای مشخص کردن بلوکهای برنامه، پایتون از فضاهای خالی و دندانه دار نوشتن (به انگلیسی: Indentation) استفاده میکند. بهطور معمول در بسیاری از زبانهای مشهور مانند C و Java از ساختار آکولاد برای مشخص کردن بلوکهای برنامه استفاده میشود:
void foo(int x)
{
if (x == 0) {
bar();
baz();
} else {
qux(x);
foo(x - 1);
}
}
در صورتی که برنامهٔ معادل فوق در پایتون به صورت زیر است:
def foo(x):
if x == 0:
bar()
baz()
else:
qux(x)
foo(x - 1)
مشاهده میکنید که چگونه فاصلهٔ اضافی (معمولا یک tab) مشخصکنندهٔ بلوکهای برنامه است. اگرچه استفاده از هردو فاصله و tab در نسخههای کنونی پایتون معمول است، استفاده همزمان از هردو آنها موجب سردرگمی و ایجاد اشتباهات ناآگاهانه میشود؛ لذا معمولاً تنها از tab یا تنها از فاصله استفاده میشود.
نوع دادهها
در پایتون، نوع دادهها به صورت دینامیک از روی مقداری که به متغیرها نسبت داده میشود تعیین میشود. در واقع هیج نوعی برای مغیری که مقداردهی نشدهاست، تعریف نمیشود. بلکه نوع متغیر مورد نظر توسط مقدار نسبت داده شده تعیین میشود. نوع دادهها در پایتون دارای اطلاعات ارجاع به نوع شیئی هستند که از آن ساخته شدهاند. این ویژگیها در جایگاههای مختلف در رفتار پایتون تأثیر میگذارد. به خاطر ویژگی دینامیک بود نوع دادهها در پایتون، تبدیل نوع متغیرها احتیاج به در قالب ریختن متغیرها (به انگلیسی: Casting) ندارد. به عنوان یک عدد موهومی در یک عدد صحیح بلند را ضرب کنید و پایتون به صورت خودکار نوع حاصل را تعیین میکند. اگرچه همیشه این امکانپذیر نیست! به عنوان مثال ضرب یک رشته در یک عدد معنی ندارد!
نوعهای پایه
پایتون انواع پایه مختلفی را پشتیبانی میکند. به عنوان مثال اعداد صحیح، حقیقی (به انگلیسی: float) محاسبات با دقت دلخواه و اعداد موهومی. بهطور کلی نوع دادهها در پایتون به دو دستهٔ تغییرناپذیر (به انگلیسی: Immutable) و تغییرپذیر (به انگلیسی: Mutable) تقسیم میشوند. به عنوان مثال رشتهها در پایتون تغییرناپذیر هستند. تغییرناپذیر متغیرها در پایتون به این معنی است که نمیتوان متغیر را بعد از ایجاد دستکاری کرد؛ لذا برای بر خلاف بسیاری از زبانهای دیگر، تغییر رشته در باعث ایجاد رشتهای دیگر میشود.
نوعهای مجموعهای
نوع دادههای مجموعهای دارای دو دستهٔ دارای ترتیب (به انگلیسی: sequences) و بدون ترتیب (نگاشت یا (به انگلیسی: mapping)) هستند. نوع دادههای دارای ترتیب در بردارندهٔ مقادیر هستند که به صورتی مرتب پشت سر هم قرار گرفتهاند. نمونهٔ این نوع دادهها لیستها (آرایههای دینامیک)، توپلها (به انگلیسی: tuples) و رشتهها هستند. اندیس گذاری در پایتون از ۰ شروع میشود. این نوع دادهها میتوانند (بجز رشتهها) میتوانند نوع دادههای مختلف غیر یکسان را دربر گیرند. رشتهها و توپلها تغییرناپذیر هستند. در صورتی که لیستها و دیکشنریها تغییرپذیر هستند. یعنی میتوان آنها را «در جا» ویرایش (حذف عنصر، اضافه کردن عنصر، عوض کردن مقدار، مرتبسازی …) کرد. نوع دادههای بدون ترتیب معمولاً به صورتی دیکشنری هستند. یعنی مجموعهای تغییرناپذیر را به مجموعهٔ از اشیا مینگارند؛ لذا در کل ترتیبی برای دادهها در نظر گرفته نمیشود. اشیایی که نگاشته میشوند (کلیدها یا (به انگلیسی: keys)) باید از نوع تغییرناپذیر باشند، مانند اعداد صحیح یا یک رشته. این مسئله به خاطر آن است که در پشت صحنه، نگارش توسط یک تابع درهم سازی انجام میشود. تغییرناپذیر باعث میشود عملیات در بازدهی زمانی/حافظهای بهتری انجام شوند؛ اگرچه لازم است که مقادیر آنها ثابت بمانند؛ لذا چنین ساختاری «دیکشنری» نام دارد. نوع دادهٔ مشابه دیگر «مجموعه» (به انگلیسی: set) نام دارد که شامل تعداد شی بدون ترتیب است که بدون تکرار هستند، درست مانند تعریف ریاضی مجموعهها؛ لذا به راحتی میتوان از آنها برای انجام عملیات مجموعهای ماند اجتماع، اشتراک، تفاضل، تفاضل متقارن، زیر مجموعهگیری و غیره استفاده کرد.
ساختار شیء گرایی
در پایتون همه چیز حتی شیء در کلاسها تعریف شدهاند. خود کلاسها نیز، به عنوان یک شیء، دارای کلاسهایی به نام فرا کلاس هستند.
قواعد اولیه نگارش
رشتهها
رشتهها گاه با "
و گاه با '
نوشته میشود و اگر شما در میان رشته نیز از '
استفاده کردید بهتر است رشته را با "
آغاز و پایان دهیم
اشارهکردن در رشته
میتوان با استفاده از درصد در درون رشته یا استفاده از متد format
چیزهایی را که به راحتی نمیتوان درون رشته قرار داد یا پرینت کرد را درون رشته قرار دهیم:
print(f"I just printed {num} pages to the printer {printer}")
print("I just printed {} pages to the printer {}".format(num, printer))
print("I just printed {0} pages to the printer {1}".format(num, printer))
print("I just printed {num} pages to the printer {printer}".format(num=num, printer=printer))
print("I just printed %s pages to the printer %s" % (num, printer))
print("I just printed %(num)s pages to the printer %(printer)s" % {"num": num, "printer": printer})
چاپ رشتهای چند سطر
برای این کار بهتر است از ۳تا '
یا ۳تا"
نمونهٔ زیر چگونگی این کار را نشان میدهد:
print("""Dear %(recipient)s,
I wish you to leave Sunnydale and never return.
Not Quite Love,
%(sender)s
""" % {'sender': 'Buffy the Vampire Slayer', 'recipient': 'Spike'})
رشتههای خام
سرانجام، تمام رشتههای قبلاً ذکر شده در گونههای «خام» قرار میگیرند (که با قرار دادن r به معنای واقعی کلمه قبل از نقل قول نشان داده میشوند)، که هیچ گونه تلاقی در درون نمیانجامد و از این رو برای عبارات منظم بسیار مفید هستند. "@ -quoting" را در C# مقایسه کنید. رشتههای خام در ابتدا بهطور خاص برای عبارات منظم درج شده بودند. با توجه به محدودیتهای نشانهگذاری، رشتههای خام ممکن است دارای خستگی برگشتناپذیر نباشند. ایجاد یک رشته خام با نگه داشتن یک مسیر پنجرههایی که به صورت برگشتی به انتهای خود منتهی میشود، به انواع مختلفی از کار نیاز دارد (معمولاً استفاده از اسلشهای جلو به جای بک لایت، زیرا پنجره هر دو را میپذیرد).
>>> # A Windows path, even raw strings cannot end in a backslash
>>> r"C:\Foo\Bar\Baz\"
File "<stdin>", line 1
r"C:\Foo\Bar\Baz\"
^
SyntaxError: EOL while scanning string literal
>>> dos_path = r"C:\Foo\Bar\Baz\ " # avoids the error by adding
>>> dos_path.rstrip() # and removing trailing space
'C:\\Foo\\Bar\\Baz\\'
>>> quoted_dos_path = r'"{}"'.format(dos_path)
>>> quoted_dos_path
'"C:\\Foo\\Bar\\Baz\\ "'
>>> # A regular expression matching a quoted string with possible backslash quoting
>>> re.match(r'"(([^"\\]|\\.)*)"', quoted_dos_path).group(1).rstrip()
'C:\\Foo\\Bar\\Baz\\'
>>> code = 'foo(2, bar)'
>>> # Reverse the arguments in a two-arg function call
>>> re.sub(r'\(([^,]*?),([^ ,]*?)\)', r'(\2, \1)', code)
'foo(2, bar)'
>>> # Note that this won't work if either argument has parens or commas in it.
ادغام دو رشته
میتوان دو رشته را به صورت زیر ادغام کرد:
title = "One Good Turn: " \
'A Natural History of the Screwdriver and the Screw'
که معادل است با عبارت زیر:
title = "One Good Turn: A Natural History of the Screwdriver and the Screw"
اعداد
در پایتون اعداد به فرم عادی مشابه سایز زبانها تعریف میشوند، همچون 0
, -1
, 3.4
, 3.5e-8
.
عدد صحیح در پایتون طول دلخواه دارد و در صورت نیاز بهطور خودکار فضای حافظه را زیاد میکند. پایتون دارای نوع داده صحیح با محدودهٔ یکسان هستند. تا قبل از نسخهٔ ۳ پایتون، دو نوع عدد صحیح موجود بود، یکی اعداد صحیح عادی با طول ثابت، و دیگری اعداد صحیح با طول بلند یا "long" با طول دلخواه. اینکه از کدام نوع عدد صحیح استفاده شود، به صورتی خودکار توسط پایتون انجام میشد. در نسخههای جدید، نوع اول بهطور کامل حذف شد. اعداد حقیقی (به انگلیسی: float) به صورت عادی تعریف میشوند. استفاده از این نوع زمانی انجام میشود که از علامت نقطه به عنوان ممیز اعشار استفاده شود، مانند ۱٫۱.
لیستها، تاپلها، مجموعهها، دیکشنریها
همانطور که گفته شد، لیستها دارای ساختار تغییرپذیر هستند. لیستها در کلاس list
تعریف میشوند. نمونهای از تعریف یک لیست به صورت زیر است:
a_list = [1, 2, 3, "a dog"]
میتوان لیستها را همچون ایجاد یک شیء از یک کلاس تعریف کرد:
a_second_list = list()
a_second_list.append(4)
a_second_list.append(5)
همانطور که گفته شد توپلها tuple
اعضایی تغییرناپذیر از پایتون هستند که در کلاس tuple
تعریف میشوند.
a_tuple = 1, 2, 3, "four"
اگرچه در تعریف فوق توپل توسط کاما بین اعضای آن تعریف میشود، میتوان با قرار دادن پرانتز بین اعضای آن تعریف آن را قابل فهم تر میکند. یک توپل تهی به صورت () معرفی میشود.
مجموعههای نوع دادههایی قابل تغییر هستند که در کلاس set
تعریف میشوند.
some_set = {0, (), False}
دیکشنریها نوع دادههایی تغییرپذیر هستند که در کلاس dict
تعریف میشوند. در پایتون اعضای یک دیکشنری به صورت زوج {key: value}
تعریف میشود.
a_dictionary = {"key 1":"value 1", 2:3, 4:[]}
عملگرها
عملگرهای محاسباتی
عملگرهای محاسباتی شامل +
، -
، *
، /
، %
(باقیمانده) و **
(توان) است. در استفاده از /
برای تقسیم باید دقت کرد. به مثال زیر دقت کنید:
def mean(seq):
return sum(seq) / len(seq)
فراخوانی mean([3.0, 4.0])
برمیگرداند. ممکن است mean([3, 4])
را فراخوانی کنید و خروجی ۳ بگیرید که نتیجهای عجیب است. دلیل این مسئله این است که تقسیم اعداد به صورت صحیح انجام شده و لذا نتیجه عددی صحیح است. راه چاره این است که تیکه برنامهٔ فوق را به صورات زیر تغییر دهیم:
def mean(seq):
return float(sum(seq)) / len(seq)
البته این مشکل در پایتون ۳ حل شد.
در نسخههای بعدی پایتون عملگری به صورت //
تعریف شدهاست که تنها تقسیم صحیح است.
عملگرهای مقایسهای
==
برای تشخیص آنکه ورودی با مقدار مقدار دادهشده برابر است:g == 2
<>
(پایتون ۲) و=!
(پایتون ۳) برای تشخیص مساوینبودن ورودی و مقدار دادهشده:g != 2
-
<
برای تشخیص بزرگتر بودن ورودی از مقدار و =<
برای تشخیص بزرگتر یا مساوی بودن ورودی از مقدار. -
>
برای تشخیص کوچکتر بودن ورودی از مقدار و =>
برای تشخیص کوچکتر یا مساوی بودن ورودی از مقدار. is
برای تشخیص هماهنگی ورودی و مقدار وis not
برای تشخیص هماهنگی نبودنin
برای تشخیص قرارداشتن مقدار در ورودی وnot in
برای تشخیص برعکس
در صورت درست بودن، بهما True
و در غیر این صورت، False
میدهد
برنامهنویسی تابعی
سبک برنامهنویسی تابعی به سبکی از برنامهنویسی گفته میشود که در آن به صورتی به صورتهایی مؤثر تر از قابلیتهای لیستها و نوع دادههای آن برای انجام عملیات نسبتاً پیچیدهتر استفاده میشود.
مرکبها
لیست مرکب لیستی است که مقادیری به آن داده شده و همراه حلقه for
درون لیست میتوان آن مقادیر را تا جای ممکن تکرار کرد.
L = [mapping_expression for element in source_list if filter_expression]
به عنوان مثال برنامهٔ زیر ۵ توان اول ۲ را توسط یک سطر کد محاسبه میکند:
powers_of_two = [2**n for n in range(1, 6)]
به عنوان مثالی دیگر، برنامهٔ زیر (کوییکسورت) را به کوتاه (اگرچه غیر بهینه) انجام میدهد:
def qsort(L):
if L == []:
return []
pivot = L[0]
return (qsort([x for x in L[1:] if x < pivot]) +
[pivot] +
qsort([x for x in L[1:] if x >= pivot]))
پایتون ۲٬۷+ همچنین مجموعه را به درستی تنظیم و پشتیبانی میکند و دیکشنری را تنظیم میکند.
توابع کلاساول
در پایتون، توابع کلاس اول هستند که میتوانند بهصورت دینامیکی ایجاد شده و به اطراف منتقل شوند.
پشتیبانی محدود پایتون از کارکردهای ناشناس، ساختار lambda
است. برنامه زیر با کاراکتر ۵ اجرا میشود:
f = lambda x: x**2
f(5)
لامبداها یک عمل را بهجای چندین عمل انجام میدهد، اگرچه جریان کنترل هنوز هم با استفاده از اتصال کوتاه میتواند کمتر با ظرافت در لامبدا اجرا شود، و اصطلاحات بیشتری با عبارات شرطی دارند.
بستارها
پایتون از نسخه ۲٬۲ از بستار پشتیبانی کردهاست. در اینجا مثالی را میبینید:
def derivative(f, dx):
"""Return a function that approximates the derivative of f
using an interval of dx, which should be appropriately small.
"""
def function(x):
return (f(x + dx) - f(x)) / dx
return function
اگرچه نحو پایتون، گاهی اوقات، برنامهنویسان زبانهای دیگر را به این فکر میاندازد که بستار در این زبان پشتیبانی نمیشود. متغیرها در توابع پایتون تنها در خود تابع اجرا میشود و نمیتوان آن را در خارج از تابع اجرا کرد، مگر آنکه آن را با کدهای global
یا nonlocal
را در پیش از ایجاد متغیر بنویسیم.
توجه داشته باشید که بستارهای الزامآور از یک نام تاحدی قابل تغییر از درون تابع نیست. برای مثال:
>>> def foo(a, b):
... print('a: %r' % a)
... print('b: %r' % b)
... def bar(c):
... b = c
... print('b*: %r' % b)
... bar(a)
... print('b: %r' % b)
>>> foo(1,2)
a: 1
b: 2
b*: 1
b: 2
و شما میتوانید آن را ببینید که b
، همانند قابل مشاهده از بستارهای محدود، ارزش خود را حفظ میکند. ما میتوانیم از b
در داخل تابع استفاده کنیم اما بیرون از تابع نه. مگر آنکه از عبارت nonlocal b
در تابع استفاده کرد. در پایتون ۲ (فاقد nonlocal
در نسخه) راه حل معمول این است که از مقدارهای تغییرپذیر استفاده نمود و آن مقدار را تغییر داد، این کار الزامآور نیست. برای مثال، لیستی با یک عنصر را اشاره میکنیم.
مولدها
در پایتون ۲٫۲ به عنوان یک ویژگی اختیاری معرفی و در نسخه ۲٫۳ نهایی شدهاست، مولد است که سازوکاری برای ارزیابی کندرو از یک تابع میباشد و در غیر این صورت یک فضای منعکننده یا لیست محاسباتی فشرده را برگشت میدهد.
این یک نمونه برای تولید کندرو نخستین عدد است:
from itertools import count
def generate_primes(stop_at=0):
primes = []
for n in count(2):
if 0 < stop_at < n:
return # raises the StopIteration exception
composite = False
for p in primes:
if not n % p:
composite = True
break
elif p ** 2 > n:
break
if not composite:
primes.append(n)
yield n
برای استفاده از این تابع به سادگی تماس بگیرید، بهعنوان مثال:
for i in generate_primes(): # iterate over ALL primes
if i > 100:
break
print(i)
تعریف از یک مولد با یک عملکرد همسان ظاهر میشود، بهجز واژه کلیدی yield
از return
نیز در محل استفاده شدهاست. با این حال، یک مولد یک شیء با حالت مداوم است، که میتوان بارها و بارها وارد و خارج از محدوده یکسان شد. سپس بایک تماس مولد میتوان در محل از یک لیست استفاده کرد، یا دیگر ساختارهایی که عناصر در آن تکرار خواهد شد. هر زمان که حلقه for
در مثال نیاز دارد به مورد بعدی برود، این مولد نامیده میشود، و محصول مورد بعدی را باز میدهد.
دکوراتورها
دکوراتور شیء قابل فراخوانیای است که به منظور پیرایش تعریف تابع کلاس یا متد استفاده میشود. کلیدواژهٔ @
برای دکوراتور استفاده میشود.
@viking_chorus
def menu_item():
print("spam")
که با کد زیر هم ارز است.
def menu_item():
print("spam")
menu_item = viking_chorus(menu_item)
استفاده از دکوراتورها نوعی فرا برنامهنویسی است. دکوراتورها به منظور بهبود تابع یا متدی که روی آن اعمال میشوند استفاده میشوند. مثلاً در مثال پایین viking_chorus
موجب میشود تابع menu_item
هشت بار اجرا شود.
def viking_chorus(myfunc):
def inner_func(*args, **kwargs):
for i in range(8):
myfunc(*args, **kwargs)
return inner_func
منابع
- ↑ "Readability counts." - PEP 20 - The Zen of Python بایگانیشده در ۲۰۱۴-۱۲-۰۵ توسط Wayback Machine
- ↑ "PEP 20 - The Zen of Python". Python Software Foundation. 2004-08-23. Archived from the original on 2008-12-03. Retrieved 2008-11-24.
- ↑ http://docs.python.org/dev/reference/lexical_analysis.html#keywords
- ↑ http://docs.python.org/reference/lexical_analysis.html#keywords
- ↑ "New Keywords". Python v3.5 documentation. Docs.python.org. Archived from the original on 2016-06-18. Retrieved 2016-06-01.
- ↑ "2. Lexical analysis". Python v2.7.5 documentation. Docs.python.org. Archived from the original on 2012-10-23. Retrieved 2013-08-16.
- ↑ "Archived copy". Archived from the original on 2016-01-27. Retrieved 2016-01-19.
- ↑ "Archived copy". Archived from the original on 2016-01-26. Retrieved 2016-01-19.
- ↑ "Archived copy". Archived from the original on 2016-01-26. Retrieved 2016-01-19.
- ↑ David Mertz. "Functional Programming in Python". IBM developerWorks. Archived from the original on 2007-02-20. Retrieved 2007-08-27.
- ↑ "PEP 308 -- Conditional Expressions". Archived from the original on 2016-03-13. Retrieved 2016-04-14.