مقدمه

در درس قبل دیدیم که برای تعریف متغیرهای پایتون، نیاز به اعلان نوع نیست و یک متغیر پایتون به ساده‌ترین شکل ممکن و با گزاره‌ای مثل x = value ایجاد می‌شود. اما هر مقدار مثل value متعلق به یک نوع (type) یا به بیان دقیق‌تر یک نوع داده (datatype) است و از طرفی، ماهیت دینامیک سیستم نوع (type system) در پایتون باعث می‌شود که متغیرها بتوانند در طول برنامه، مقادیری از نوع‌های مختلف دریافت کنند. بنابراین، هر متغیر پایتون، در هر لحظه، می‌تواند از یک نوع باشد و این نوع معمولاً از آخرین مقدار تخصیص داده شده به آن متغیر، مشخص می‌شود. در پایتون، چند نوع درونی (built-in) وجود دارد که برای کار با مقادیر رایجی مثل اعداد، رشته‌های متنی و کالکشن‌ها تدارک دیده شده‌اند. در این درس، این نوع‌های built-in را به طور گذرا معرفی می‌کنیم و در درس‌های بعدی این فصل و سه فصل بعد، این نوع‌ها را با جزئیات بیشتر مورد بررسی قرار می‌دهیم.

نوع‌های Built-in

نوع‌های built-in در پایتون را می‌توانیم در دو گروه قرار دهیم: نوع‌های ساده‌ای که مقادیر آنها فقط شامل یک چیز (یک عدد، یک رشته و ...) هستند و نوع‌های پیچیده‌تری که مقادیر آنها می‌توانند شامل یک کالکشن یا دنباله از مقادیرِ نوع‌های مختلف باشند.

نوع مقادیر مثال
int اعداد صحیح a = 8
b = 1_000_000
float اعداد اعشاری x = 1.0
y = 1.25
complex اعداد مختلط z = 3 + 5j
w = 2 - 4j
str رشته‌های کاراکتری s1 = "Hi"
s2 = 'Hello'
bool مقادیر بولین b = False
list یک کالکشن تغییرپذیر از مقادیر ترتیبی l1 = [1, 2, 3, 4]
l2 = [1, "one", 1.0]
tuple یک کالکشن تغییرناپذیر از مقادیر ترتیبی t1 = (1, 2, 3, 4)
t2 = (1, "one", 1.0)
range یک کالکشن تغییرناپذیر به صورت یک بازه از مقادیر r1 = range(2, 6)
r2 = range(1, 10, 2)
dict یک کالکشن تغییرپذیر از جفت‌های key و value d = {'name': 'lale', age: 4}
set یک کالکشن تغییرپذیر از مقادیر غیرترتیبی s = {2, 4, 6, 8}
frozenset یک کالکشن تغییرناپذیر از مقادیر غیرترتیبی f1 = frozenset([1, 2, 3])
f2 = frozenset({1, 2, 3})
NoneType مقدار None x = None

در جدول بالا ۵ نوع اول، نوع‌های ساده هستند. یعنی مقادیر این نوع‌ها فقط می‌توانند شامل یک چیز باشند؛ مثلاً یک عدد صحیح، یک رشته‌ی متنی و غیره. اما شش نوع بعدی، نوع‌هایی هستند که مقادیر آنها می‌توانند یک کالکشن از مقادیر را نگه دارند. همانطور که می‌بینید، چیزی که بین این کالکشن‌ها تفاوت ایجاد می‌کند، دو مفهوم تغییرپذیری و ترتیب است. در ادامه، این مفاهیم را در عمل خواهیم دید. نوع آخر یعنی NoneType هم یک نوع خاص است که فقط شامل یک مقدار None است که مفهومی معادل تهی (empty) دارد.

در اینجا یک معرفی مختصر از هر یک از این نوع‌ها خواهیم داشت و در آینده با جزئیات مربوط به آنها آشنا می‌شویم. البته بحث ما در مورد نوع‌های عددی int و float کمی مفصل‌تر خواهد بود اما جزئیات بیشتری از این نوع‌ها هم در درس کار با اعداد ارائه خواهد شد.

نوع int در پایتون

معرفی نوع‌های built-in پایتون را با نوع int شروع می‌کنیم که همانطور که در جدول بالا هم اشاره شده، شامل مقادیر عددی صحیح است. یعنی در پایتون، هر عدد صحیح از نوع int در نظر گرفته می‌شود. بازه‌ی مقادیر برای نوع int بازه‌ی (-inf, inf) است. یعنی هر عدد صحیح، هرچقدر هم که بزرگ باشد، حتی اگر هزاران رقم داشته باشد، به نوع int متعلق است. بنابراین، اعمال محاسباتی روی اعداد صحیح خیلی بزرگ هم به صورت دقیق و بدون مسائلی مثل خطای دقت و سرریز (overflow) انجام می‌شود.

مفسر پایتون را در ترمینال فراخوانی کنید و کد زیر را در آن آزمایش کنید. تأکید می‌کنم که هر خطی که با کاراکترهای >>> شروع شده، توسط ما وارد می‌شود و سایر خطوط، نتیجه‌ی اجرای کدها هستند.

>>> a = 8
>>> a + 1 
9
>>> b = 10 ** 80 
>>> b + 1 
100000000000000000000000000000000000000000000000000000000000000000000000000000001 
          

در پایتون نماد ** متعلق به عمل محاسباتی توان است و عبارتی مثل a ** b به معنای ab است. در مورد عملگرهای حسابی در درس‌های بغد، مطالب لازم بیان خواهد شد.

انعطاف‌پذیری نوع int

در طراحی و توسعه‌ی زبان پایتون، اصل بر سادگی، انعطاف‌پذیری و ارگونومی بالا بوده و هست. بنابراین، در تعارضات اجتناب‌ناپذیری که در طراحی زبان وجود دارد، اولویت به ارگونومی و سادگی داده شده است. در اکثر زبان‌های برنامه‌نویسی، نوع یا نوع‌هایی که برای کار با اعداد صحیح در نظر گرفته شده‌اند، شامل یک بازه‌ی مشحص و محدود از اعداد صحیح هستند. بنابراین، برنامه‌نویس باید مراقب رخ دادن خطاهای دقت و سرریز از بازه‌ی مقادیر مجاز (overflow) برای هر نوع باشد و بداند که رفتار آن زبان در هنگام رخ دادن سرریز چیست. اما در پایتون، ما با چنین مسائلی مواجه نخواهیم شد؛ چون فقط یک نوع int برای اعداد صحیح وجود دارد که هیچ محدودیتی از نظر بازه‌ی مقادیر ندارد. در پایتون، سایز نوع int متغیر است. به این ترتیب، اعداد صحیح کوچک‌تر فضای کمتری می‌گیرند و اعداد بزرگ‌تر به صورت دینامیک فضای بیشتری دریافت می‌کنند. این پیاده‌سازی، هزینه‌های مربوط به کارایی (performance) را که قاعدتاً باید به خاطر نامحدود بودن بازه‌ی مقادیر int تحمیل شود، به حداقل می‌رساند.

نمایش اعداد صحیح در سایر مبناها

امکان نمایش اعداد صحیح در مبناهای به جز 10 هم وجود دارد. اعداد باینری، یعنی اعداد در مبنای 2 که فقط از دو رقم صفر و 1 تشکیل می‌شوند، با پیشوند 0b، اعداد اکتال، یعنی اعداد در مبنای 8 که از هشت رقم 0 تا 7 تشکیل می‌شوند، با پیشوند 0o و اعداد هگزادسیمال، یعنی اعداد در مبنای 16 که از شانزده رقم شامل ارقام صفر تا 9 و کاراکترهای a تا f (به جای 10 تا 15) تشکیل می‌شوند، با پیشوند 0x قابل ایجاد هستند.

>>> 0b11111111
255
>>> 0xff
255
          

نوع float در پایتون

در پایتون، نوع float برای نمایش اعداد اعشاری در نظر گرفته شده است. این نوع در زبان‌های دیگر با نام‌هایی مثل double یا f64 شناخته می‌شود و از روی استانداردی به نام IEEE-754 پیاده‌سازی شده است. بر خلاف نوع int، نوع float سایز ثابتی معادل 64 بیت دارد و امکان تغییر سایز آن به صورت دینامیک، وجود ندارد. بنابراین، نوع float بازه‌ی مشخصی از مقادیر را شامل است. تعیین دقیق بازه‌ی مقادیر ممکن برای نوع float به پلتفرم بستگی دارد اما در اکثر سیستم‌ها:

  • مقدار ماکزیمم یا بزرگترین عدد مثبتی که به نوع float متعلق است، تقریباً برابر با 1.79×10308 است. هر عدد اعشاری بزرگتر از این عدد، برابر با بی‌نهایت (inf) در نظر گرفته می‌شود.
  • مقدار مینیمم یا کوچکترین عدد مثبتی که به نوع float متعلق است، تقریباً برابر با 2.2×10-308 است. هر عدد مثبت کوچک‌تر از این عدد، برابر با 0.0 در نظر گرفته می‌شود.

اعداد اعشاری را می‌توان با استفاده از نماد علمی هم نمایش داد. در این روش، از کاراکتر e یا E برای توان‌رسانی استفاده می‌شود؛ به این شکل که عدد aeb یا aEb برابر با a×10b محسوب می‌شود. حالا مثال زیر را ببینید.

>>> 1e308
1e308
>>> 1e309 
inf
>>> -1e309 
-inf
          

پس، نوع float در پایتون شامل بازه‌ای از اعداد اعشاری به همراه دو مقدار inf و -inf و البته یک مقدار خاص دیگر به نام nan است. اجازه دهید ببینیم این مقادیر عددی خاص در پایتون چه رفتاری دارند.

مقادیر inf و nan

دیدیم که اعدادی که از مقدار ماکزیمم بازه‌ی مقادیر float بزرگ‌تر باشند، برابر با مقدار خاص inf در نظر گرفته می‌شوند که همان مفهومی است که آن را با نام بی‌نهایت می‌شناسیم. مقدار nan نیز به‌نوعی، نشانگر مفهوم مبهم در حسابان (calculus) است. اما این مفاهیم در برنامه‌نویسی به همان شکلی که در ریاضیات دیده‌ایم، کار نمی‌کنند و با وجود شباهت‌ها، تفاوت‌هایی وجود دارد که باید از آن مطلع باشیم. گذشته از این، حتی زبان‌های برنامه‌نویسی هم این مفاهیم را به شکل یکسان پیاده‌سازی نکرده‌اند و بنابراین، اگر با زبان‌های دیگر آشنا هستید، نباید فکر کنید که رفتار این مقادیر در پایتون مشابه زبان‌های دیگر است. بعد از این روشنگری، اجازه دهید بپردازیم به مقادیر inf و nan در دنیای پایتون.

اما راستش را بخواهید، روشنگری ما هنوز به پایان نرسیده و یک نکته‌ی دیگر از آن باقی مانده. حتی در دنیای پایتون هم همه چیز یکسان و یکنواخت نیست. در پایتون استاندارد، عبارت 1.0 / 0.0 و به طور کلی حاصل تقسیم هر مقدار عددی بر صفر منجر به خطا می‌شود اما در کتابخانه‌ای مثل NumPy حاصل این تقسیم برابر با inf است. به هر حال، فعلاً موضوع بحث ما، پایتون استاندارد است.

مقدار nan از عبارت not a number گرفته شده و در اثر یک عمل محاسیاتی نامعتبر تولید می‌شود. در مورد رفتار مقادیر عددی inf و nan در پایتون، باید به نکات زیر توجه داشته باشید.

  • تقسیم هر مقدار عددی (از جمله inf و nan) بر صفر باعث تولید خطا می‌شود.
  • حاصل عبارات inf - inf و inf / inf برابر با nan خواهد بود.
  • حاصل هر مقدار عددی به توان صفر برابر با 1 خواهد بود.

حالا به مثال زیر توجه کنید.

>>> x = 1e500
>>> y = 1e400
>>> x
inf
>>> y
inf
>>> x - y 
nan
>>> x / y 
nan
>>> x + y
inf
>>> x * y 
inf 
>>> x ** y 
inf
>>> x ** 0 
1.0 
>>> 0 ** 0 
1.0
          

خطاهای مربوط به اعداد اعشاری

دیدیم که پایتون با اعداد خارج از بازه‌ی مقادیر float چه رفتاری دارد. اما نمایش اعداد درون بازه‌ی مقادیر float هم می‌تواند با خطاهایی مثل خطای تقریب همراه باشد و این موضوعی است که باید از کم و کیف آن باخبر باشیم تا با نتایح غیر قابل انتظار مواجه نشویم.

اعداد اعشاری در کامپیوتر به فرمت باینری نمایش داده می‌شوند و در این فرمت، امکان نمایش دقیق خیلی از اعداد اعشاری (حتی اعدای به سادگی 0.1 و 0.2) وجود ندارد و در عمل، تقریبی از این اعداد ذخیره می‌شود. وقتی پای تقریب در میان باشد، مقداری خطا هم وجود خواهد داشت که ناشی از اختلاف مقدار تقریبی و مقدار واقعی است.

>>> 0.1 + 0.2 
0.30000000000000004
>>> 8.6 - 2.4 
6.199999999999999
          

علاوه بر این، دقت نوع float بین 15 تا 17 رقم است و اعدادی که تعداد ارقام بیشتری دارند، به صورت تقریبی ذخیره می‌شوند.

>>> 2.01234567890123456789
2.0123456789012346 
          

در درس کار با اعداد، روش مواجهه با این خطاها را یاد خواهیم گرفت اما فعلاً فقط بدانید که چنین خطاهایی وجود دارند.

نوع complex در پایتون

در پایتون از اعداد مختلط هم به طور درونی پشتیبانی می‌شود و یک نوع built-in با نام complex برای کار با این اعداد در نظر گرفته شده است. یک عدد مختلط دارای فرم کلی a + bj است که در آن، a بخش حقیقی (real) و b بخش موهومی (imaginary) نامیده می‌شود. j هم عددی است که مجذور آن برابر با -1 است و در ریاضیات با i نمایش داده می‌شود. مجموعه‌ی اعداد مختلط در واقع، یک اَبَرمجموعه برای مجموعه‌ی اعداد حقیقی است و می‌توان یک عدد مختلط مثل a + bj را معادل یک نقطه‌ی (a, b) در فضای دوبعدی دانست.

نوع str در پایتون

نوع str در پایتون برای کار با مقادیر متنی در نظر گرفته شده است. از کوتیشن‌ها برای ایجاد مقادیر یا رشته‌های متنی استفاده می‌شود.

>>> s1 = "Hello"
>>> s2 = 'Hi' 
>>> s3 = "My friend's car"
          

همانطور که در این مثال می‌بینید، از هر دو نوع کوتیشن تکی و جفتی می‌توانیم برای ایجاد رشته‌ها استفاده کنیم. این امر باعث می‌شود بتوانیم از کاراکترهای کوتیشن درون رشته‌ها استفاده کنیم.

اگر بخواهیم یک رشته‌ی چندخطی ایجاد کنیم، می‌توانیم از ''' ''' یا """ """ استفاده کنیم. یک فایل پایتون با نام builin_types.py ایجاد کنید و کد زیر را در آن وارد کنید.

Copy Icon builtin_types.py
s = '''This is
a multiline
string'''
            
print(s)

اگر برنامه را اجرا کنید، خواهید دید که رشته به همان شکلی که در برنامه وارد شده، در سه خط چاپ می‌شود. جزئیات مربوط به رشته‌ها و نوع str را در درس کار با رشته‌های متنی خواهیم دید.

نوع bool در پایتون

نوع bool در پایتون برای کار با مقادیر بولین در نظر گرفته شده است. مقادیر بولین مقادیری هستند که می‌توانند برابر با True یا False باشند و بنابراین، نوع bool فقط شامل همین دو مقدار است. کاربرد واقعی مقادیر بولین و نوع bool را بعد از آشنایی با عملگرهای مقایسه‌ای و منطقی و به‌ویژه هنگام کار با عبارات و گزاره‌های شرطی خواهیم دید.

کالکشن‌ها در پایتون

کالکشن‌ها در پایتون، نوع‌هایی هستند که می‌توانند بیش از یک مقدار را در خود ذخیره کنند. در اینجا به یک معرفی مختصر از هر یک از کالکشن‌های پایتون بسنده می‌کنیم و در آینده آنها را مورد بررسی قرار می‌دهیم.

نوع list

لیست‌ها رایج‌ترین نوع کالکشن در پایتون هستند که تقریباً مشابه نوع آرایه در زبان‌های دیگر هستند. یک لیست، کالکشن یا دنباله‌ای از مقادیر است که ترتیب قرارگیری آنها مهم است و با استفاده از اندیس می‌توان به آنها دسترسی داشت. به علاوه، لیست‌ها کالکشن‌های تغییرپذیر هستند؛ یعنی می‌توان آنها را به صورت درجا ویرایش کرد. برای تعریف لیست‌ها از براکت استفاده می‌شود.

>>> prime_numbers = [2, 3, 5, 7]
>>> prime_numbers[0]
2 
>>> prime_numbers[3] = 11
>>> prime_numbers[3]
11
          

نوع tuple

تاپل‌ها را می‌توانیم ورژن تغییرناپذیر لیست‌ها بدانیم. یعنی مثل لیست‌ها، تاپل‌ها هم ترتیبی هستند و با اندیس می‌توانیم به آیتم‌های تاپل دسترسی داشته باشیم اما یک تاپل را نمی‌توان به صورت درجا ویرایش کرد. تاپل‌ها با استفاده از پرانتز تعریف می‌شوند.

>>> prime_numbers = (2, 3, 5, 7)
>>> prime_numbers[0]
2
          

نوع range

از نوع range برای ایجاد بازه‌های عددی استفاده می‌شود. از این نوع بیش از هر جایی در حلقه‌های for استفاده می‌شود. سینتکس کلی برای ایجاد یک بازه‌ی عددی به صورت range(start, stop, end) است که باعث می‌شود اعداد صحیح بازه‌ی [start, stop) با طول گام step ایجاد شوند. کاربرد نوع range را در آینده خواهیم دید.

>>> r = range(1, 7)
>>> r[0]
1
>>> r[5]
6
          

نوع dict

نوع dict برای ایجاد یک کالکشن از مقادیر key و value کاربرد دارد. این کالکشن‌ها که دیکشنری نامیده می‌شوند، در پایتون تغییرپذیرند و با استفاده از آکلادها ساخته می‌شوند. دسترسی به آیتم‌های یک دیکشنری از طریق مقدار key امکان‌پذیر است.

>>> d = {'name': 'lale', age: 4}
>>> d['name']
'lale'
>>> d['age'] 
4
          

نوع‌های set و frozenset

نوع set برای ایجاد یک کالکشن از مقادیر غیرترتیبی و غیرتکراری کاربرد دارد. این کالکشن همان چیزی است که در ریاضیات مجموعه (Set) نامیده می‌شود. یک مجموعه در پایتون با استفاده از آکلادها ایجاد می‌شود و امکان ویرایش درجای آن وجود دارد.

>>> s = {1, 2, 3} 
>>> s
{1, 2, 3}
>>> s.remove(3)
>>> s
{1, 2}
          

نوع frozenset هم ورژن تغییرناپذیر set است؛ یعنی امکان ویرایش درجای آن وجود ندارد.

تبدیل نوع در پایتون

متناظرر با هر یک از نوع‌های built-in در پایتون، تابعی همنام با آن نوع وجود دارد که برای تبدیل مقادیر سایر نوع‌ها به آن نوع کاربرد دارد. برای مثال، برای نوع int یک تابع با نام int() داریم که آرگومانش را (در صورت امکان) به int تبدیل می‌کند. مثال زیر را ببینید.

>>> int(1.2)
1
>>> int("12")
12
>>> int(True)
1
>>> int(False)
0
>>> float(1)
1.0
>>> float("1.2")
1.2
>>> float(True)
1.0
>>> float('inf')
inf
>>> float('nan')
nan
>>> bool(0)
False 
>>>> bool(-8)
True
>>> bool(float('inf'))
True
>>> bool(float('nan'))
True
>>> bool("")
False 
>>> bool("Hi")
True
          

برای نوع‌های کالکشن هم توابع تبدیل مشابهی وجود دارد که امکان تبدیل کالکشن‌ها به همدیگر را فراهم می‌کنند. این توابع را هنگام بررسی کالکشن‌های پایتون خواهیم دید.