آموزش پایتون - تاپل نام‌گذاری‌شده

در پایتون، تاپل‌ها (tuples) ساختارهای داده‌ای تغییرناپذیری هستند که می‌توانند مجموعه‌ای از آیتم‌ها را در خود نگهداری کنند. ما پیش‌تر در فصل‌های قبلی درباره تاپل‌ها، ویژگی‌ها و کاربرد آن‌ها صحبت کرده‌ایم. در این فصل، namedtuple() و کاربرد آن در پایتون را توضیح خواهیم داد.

NamedTuple چیست؟

در پایتون، یک namedtuple() زیرکلاسی از tuple است که به شما امکان می‌دهد تاپل‌هایی با فیلدهای نام‌گذاری‌شده ایجاد کنید. به این معنی که می‌توانید به‌جای اندیس‌های عددی، با استفاده از نام فیلدها به عناصر تاپل دسترسی داشته باشید. این ابزار بخشی از ماژول collections در پایتون است.

سنتکس (نحو)

from collections import namedtuple
 
# Define a namedtuple
Point = namedtuple('typename', fieldnames )
  • نام نوع (Type Name): مقدار typename نام کلاس namedtuple است. این مقدار یک رشته است که نام نوع تاپل را نشان می‌دهد.
  • نام فیلدها (Field Names): نام فیلدها همان نام عناصر موجود در تاپل هستند. این نام‌ها به‌صورت لیستی از رشته‌ها تعریف می‌شوند.

ایجاد یک NamedTuple در پایتون

برای ایجاد یک namedtuple، باید تابع namedtuple را از ماژول collections وارد (import) کنید. سپس می‌توانید با مشخص کردن نام آن و نام فیلدها، یک namedtuple تعریف کنید.

مثال زیر نحوه ایجاد یک namedtuple به نام Point با فیلدهای x و y را نشان می‌دهد −

from collections import namedtuple

# Define a namedtuple
Vertex = namedtuple('Vertex', ['x', 'y'])

# Create an instance
v = Vertex(10, 20)

# Access fields
print("Vertex-1:", v.x)
print("Vertex-2:", v.y)

خروجی کد بالا به صورت زیر خواهد بود −

Vertex-1: 10
Vertex-2: 20

دسترسی به فیلدهای NamedTuple

پیش از این دیدیم که چگونه می‌توان با استفاده از نشانه نقطه‌ای (dot notation) یعنی با استفاده از نام کلید به فیلدهای یک namedtuple دسترسی پیدا کرد. روش‌های دیگری نیز برای دسترسی به فیلدها وجود دارد −

  • دسترسی از طریق اندیس‌گذاری − می‌توانید دقیقاً مانند یک تاپل معمولی، با استفاده از اندیس به فیلدها دسترسی داشته باشید.
  • دسترسی از طریق نام کلید − همچنین می‌توانید مشابه یک دیکشنری، با استفاده از نام کلیدها به فیلدها دسترسی یابید.
  • دسترسی با استفاده از getattr() − می‌توانید از تابع getattr() برای دسترسی به فیلدها بر اساس نام آن‌ها استفاده کنید.

مثال: دسترسی از طریق اندیس‌گذاری

در این مثال، با استفاده از اندیس به فیلدهای namedtuple دسترسی پیدا خواهیم کرد.

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Access fields by indexing
print("Point-1", p[0])
print("Point-2", p[1])

خروجی کد بالا به صورت زیر خواهد بود −

Point-1 10
Point-2 20

مثال: دسترسی از طریق نام کلید

در این مثال، با استفاده از نام کلیدهای آن‌ها به فیلدهای namedtuple دسترسی پیدا خواهیم کرد.

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Access fields by keyname
print("Point-1:", p.x)
print("Point-2:", p.y)

خروجی کد بالا به صورت زیر خواهد بود −

Point-1: 10
Point-2: 20

مثال: دسترسی با استفاده از getattr()

در این مثال، با استفاده از تابع getattr() به فیلدهای namedtuple دسترسی پیدا خواهیم کرد.

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)
 
# Access fields using getattr()
print("getattr(p, 'x'):", getattr(p, 'x'))
print("getattr(p, 'y'):", getattr(p, 'y'))

خروجی کد بالا به صورت زیر خواهد بود −

getattr(p, 'x'): 10
getattr(p, 'y'): 20

متدهای NamedTuple

Namedtupleها همراه با متدهای توکار اضافی ارائه می‌شوند تا عملیات رایج را مدیریت کنند. بخش زیر برخی از این متدها را همراه با مثال بررسی می‌کند.

متد _fields()

متد _fields() برای دسترسی به نام فیلدهای namedtuple استفاده می‌شود. این متد به هیچ آرگومانی نیاز ندارد و تاپلی از نام فیلدها را برمی‌گرداند.

مثال زیر نحوه استفاده از متد _fields() را نشان می‌دهد −

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Access fields using _fields()
print("Fields of p:", p._fields)

خروجی کد بالا به صورت زیر خواهد بود −

Fields of p: ('x', 'y')

متد _replace()

متد _replace() برای ایجاد یک نمونه جدید از namedtuple استفاده می‌شود که در آن یک یا چند فیلد با مقادیر جدید جایگزین شده‌اند. این متد آرگومان‌های نام‌دار (keyword arguments) می‌گیرد که در آن کلیدها همان نام فیلدها و مقادیر همان مقادیر جدیدی هستند که باید اختصاص داده شوند.

مثال زیر نحوه استفاده از متد _replace() را نشان می‌دهد −

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Replace a field value
p2 = p._replace(x=30)

# Access fields
print("p2.x:", p2.x)
print("p2.y:", p2.y)

خروجی کد بالا به صورت زیر خواهد بود −

p2.x: 30
p2.y: 20

متد _asdict()

متد _asdict() برای تبدیل namedtuple به یک دیکشنری معمولی استفاده می‌شود. این تابع ساختار OrderedDict() حاصل از مقادیر نگاشت‌شده namedtuple() را برمی‌گرداند.

مثال زیر نحوه استفاده از متد _asdict() را نشان می‌دهد −

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Convert to dictionary
d = p._asdict()
print(d)

خروجی کد بالا به صورت زیر خواهد بود −

{'x': 10, 'y': 20}

متد _make()

متد _make() برای ایجاد یک نمونه جدید از namedtuple از روی یک شیء قابل‌پیمایش یا همان iterable (مانند یک لیست یا تاپل) استفاده می‌شود.

مثال زیر نحوه استفاده از متد _make() را نشان می‌دهد −

from collections import namedtuple

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create an instance
p = Point(10, 20)

# Create a new instance using _make()
p2 = Point._make([30, 40])

# Access fields
print("p2.x:", p2.x)
print("p2.y:", p2.y)

خروجی کد بالا به صورت زیر خواهد بود −

p2.x: 30
p2.y: 40

عملگر ** (ستاره دوگانه)

عملگر ** (ستاره دوگانه) برای باز کردن (unpack) فیلدهای namedtuple به آرگومان‌های نام‌دار استفاده می‌شود. این عملگر زمانی مفید است که بخواهید فیلدهای یک namedtuple را به تابعی که آرگومان‌های نام‌دار می‌پذیرد پاس دهید.

مثال زیر نحوه استفاده از عملگر ** را نشان می‌دهد −

import collections

# Declaring namedtuple()
Student = collections.namedtuple('Student',
                                 ['name', 'age', 'DOB'])

# Adding values
S = Student('farhan', '23', '2541997')

# initializing iterable
li = ['nishu', '19', '411997']

# initializing dict
di = {'name': "ravi", 'age': 24, 'DOB': '1391997'}

# using ** operator to return namedtuple from dictionary
print("The namedtuple instance from dict is  : ")
print(Student(**di))

خروجی کد بالا به صورت زیر خواهد بود −

The namedtuple instance from dict is  :
Student(name='ravi', age=24, DOB='1391997')

مقایسه NamedTuple با دیکشنری و کلاس‌ها

تفاوت‌های اصلی بین NamedTuple، دیکشنری و کلاس‌ها به شرح زیر است −

ویژگی NamedTuple دیکشنری کلاس
سنتکس (نحو) ساده، دقیقاً مانند تاپل جفت‌های کلید-مقدار پیچیده‌تر، همراه با متدها و ویژگی‌ها
دسترسی به عناصر با نام یا اندیس با کلید با صفت (attribute)
تغییرپذیری (Mutability) تغییرناپذیر تغییرپذیر تغییرپذیر
کارایی حافظه کارآمدترین کارایی کمتر کمترین کارایی

نتیجه‌گیری

در این فصل درباره namedtupleها در پایتون و تفاوت‌های آن با دیکشنری‌ها و کلاس‌ها آموختیم. یک پرسش رایج این است که چه زمانی باید از NamedTuple، دیکشنری یا یک کلاس استفاده کنیم؟ زمانی می‌توان از NamedTuple استفاده کرد که به یک شیء تغییرناپذیر با فیلدهای ثابت نیاز داشته باشید؛ یعنی اگر ویژگی‌های هر دو ساختار تاپل و دیکشنری را هم‌زمان بخواهید. از دیکشنری زمانی می‌توان استفاده کرد که به یک شیء تغییرپذیر با کلیدهای پویا نیاز دارید. و کلاس زمانی استفاده می‌شود که به یک ساختار داده پیچیده همراه با متدها و رفتارهای خاص نیاز داشته باشید.

پیشرفت مطالعه: وضعیت خوانده‌شدن این درس فقط در همین مرورگر ذخیره می‌شود؛ بدون نیاز به حساب کاربری.