در این قسمت نوع خاصی از متودها در پایتون به نام classmethod ها را تعریف میکنم. منبع اصلی این قسمت با کلیک کردن روی عنوان پست قابل دسترس است و من اینجا تقریبا مطالب آن را ترجمه میکنم. (با کمی تصرف!)
ابتدا مفهوم وسیله ی نقلیه را تعریف میکنیم. با ارث بردن از آن مفاهیم موتور، اتومبیل و کامیون را تعریف میکنیم. خوب، حالا که چی؟! :دی
میخواهیم تعداد موتورها، اتومبیل ها، کامیونها و همچنین تعداد کل وسایل نقلیه را به راحتی و تنها با یک متغیر total در اختیار داشته باشیم.
تعداد هر نوع وسیله را با استفاده از متود set_total تعیین میکنیم و برای نمایش آن از متود print_total استفاده میکنیم.
#an example of an old-style class
class Vehicle:
'''
represents a vehicle.
total is the number
of all vehicles
'''
total=0
@classmethod
def print_total(cls):
'''
prints total of cls kind vehicles!
e.g:
>>> Bike.set_total(3)
>>> Bike.print_total()
3
'''
print cls.total
@classmethod
def set_total(cls, value):
'''
sets total of cls kind vehicles!
e.g:
>>> Bike.set_total(3)
'''
cls.total = value
#updating the total
#number of all vehicles
Vehicle.total+=value
@staticmethod
def vehicle_total():
'''prints the total
number of all vehicles'''
print Vehicle.total
'''
represents a vehicle.
total is the number
of all vehicles
'''
total=0
@classmethod
def print_total(cls):
'''
prints total of cls kind vehicles!
e.g:
>>> Bike.set_total(3)
>>> Bike.print_total()
3
'''
print cls.total
@classmethod
def set_total(cls, value):
'''
sets total of cls kind vehicles!
e.g:
>>> Bike.set_total(3)
'''
cls.total = value
#updating the total
#number of all vehicles
Vehicle.total+=value
@staticmethod
def vehicle_total():
'''prints the total
number of all vehicles'''
print Vehicle.total
#using 'pass' keyword, leaving
#the class with no more definition
class Bike(Vehicle): pass
class Car(Vehicle): pass
class Truck(Vehicle): pass
class Bike(Vehicle): pass
class Car(Vehicle): pass
class Truck(Vehicle): pass
خوب، همانطور که دیدید برای تعریف یک classmethod مثل تعریف staticmethod از دکوراتورها استفاده کردیم.
دقت کنید که اولین ورودی هر classmethod را cls نامگذاری کردیم (مانند self این هم لزومی ندارد cls نامگذاری شود ولی معمولا این اسم را برمیگزینند! :دی)
این ورودی همانند self هنگام صدازدن متود مقدار دهی نمیشود اما فرقش با self این است که self نمونه ای از کلاس است که تابع را صدا میزند اما cls خود کلاسی (و نه نمونه ی آن) است که تابع را فرامیخواند، حال چه از طریق یک نمونه ی آن صدازده شود چه مستقیم از خود کلاس (شبیه staticmethod)
>>> Bike.set_total(3) # Bike.total = 3
>>> Car.set_total(5) # Car.total = 5
>>> Truck.set_total(2) # Truck.total = 2
>>>
>>> b = Bike()
>>> c = Car()
>>> t = Truck()
>>>
>>> b.print_total(); c.print_total(); t.print_total()
3
5
2
>>> #following results are just the same as above
...
... Bike.print_total(); Car.print_total(); Truck.print_total()
3
5
2
>>>
>>> Car.set_total(5) # Car.total = 5
>>> Truck.set_total(2) # Truck.total = 2
>>>
>>> b = Bike()
>>> c = Car()
>>> t = Truck()
>>>
>>> b.print_total(); c.print_total(); t.print_total()
3
5
2
>>> #following results are just the same as above
...
... Bike.print_total(); Car.print_total(); Truck.print_total()
3
5
2
>>>
>>> Vehicle.total #total of vehicles
10
>>> b.vehicle_total() #total of vehicles
10
>>> Car.vehicle_total() #total of vehicles
10
>>> Car.total #total of cars
5
>>>
10
>>> b.vehicle_total() #total of vehicles
10
>>> Car.vehicle_total() #total of vehicles
10
>>> Car.total #total of cars
5
>>>
همانطور که دیدید، همانند یک staticmethod فرقی نمیکند که یک classmethod را از نمونه ای از کلاس یا خود آن فرا بخوانیم.
توجه کنید که تفاوت staticmethod با classmethod در این است که اولی به طور کلی مستقل از خود کلاس است و تنها درون آن تعریف شده( به عبارت دیگر تفاوت آن با متودی همنام در بیرون از کلاس در namespace آنها است) اما دومی تنها مستقل از نمونه های یک کلاس است و نه خود آن.
با کمی ور رفتن با این مفاهیم بهتر میفهمیدشون :دی
برای اطلاعات بیشتر درباره ی classmethod به سایت رسمی پایتون اینجا یا اینجا مراجعه کنید. هر سوالی هم داشتید میتوانید به صورت پاسخ به همین پست بپرسید.
موفق باشید ☺