آموزش پایتون - بازتاب
در برنامهنویسی شیءگرا، بازتاب (Reflection) به توانایی استخراج اطلاعات درباره هر شیء در حال استفاده اشاره دارد. شما میتوانید نوع شیء، اینکه آیا زیرکلاسی از کلاس دیگر است یا خیر، ویژگیها (Attributes) آن چیست و موارد بسیار دیگری را متوجه شوید. کتابخانه استاندارد پایتون شامل چند تابع است که ویژگیهای مختلف یک شیء را منعکس و بررسی میکنند. بازتاب گاهی اوقات خودبازرسی (Introspect) نیز نامیده میشود.
در ادامه فهرست توابع بازتاب در پایتون آمده است −
- تابع ()type
- تابع ()isinstance
- تابع ()issubclass
- تابع ()callable
- تابع ()getattr
- تابع ()setattr
- تابع ()hasattr
- تابع ()dir
تابع ()type
ما بارها از این تابع استفاده کردهایم. این تابع به شما میگوید که یک شیء متعلق به کدام کلاس است.
مثال
دستورات زیر کلاس مربوط به اشیاء مختلف از نوع دادههای توکار را چاپ میکنند
print (type(10))
print (type(2.56))
print (type(2+3j))
print (type("Hello World"))
print (type([1,2,3]))
print (type({1:'one', 2:'two'}))
در اینجا، خروجی زیر را دریافت خواهید کرد −
<class 'int'>
<class 'float'>
<class 'complex'>
<class 'str'>
<class 'list'>
<class 'dict'>
بیاین نوع یک شیء از یک کلاس تعریفشده توسط کاربر را بررسی کنیم −
class test:
pass
obj = test()
print (type(obj))
این کد خروجی زیر را تولید خواهد کرد −
<class '__main__.test'>
تابع ()isinstance
این یکی دیگر از توابع توکار در پایتون است که مشخص میکند آیا یک شیء، نمونهای از کلاس دادهشده هست یا خیر.
سنتکس
isinstance(obj, class)
این تابع همیشه یک مقدار بولین برمیگرداند؛ اگر شیء واقعاً متعلق به کلاس دادهشده باشد True و در غیر این صورت False.
مثال
دستورات زیر مقدار True را برمیگردانند −
print (isinstance(10, int))
print (isinstance(2.56, float))
print (isinstance(2+3j, complex))
print (isinstance("Hello World", str))
این کد خروجی زیر را تولید خواهد کرد −
True
True
True
True
در مقابل، این دستورات مقدار False را چاپ میکنند.
print (isinstance([1,2,3], tuple))
print (isinstance({1:'one', 2:'two'}, set))
این کد خروجی زیر را تولید خواهد کرد −
False
False
همچنین میتوانید این بررسی را با یک کلاس تعریفشده توسط کاربر انجام دهید
class test:
pass
obj = test()
print (isinstance(obj, test))
این کد خروجی زیر را تولید خواهد کرد −
True
در پایتون، حتی خود کلاسها نیز شیء هستند. همه کلاسها شیئی از کلاس object محسوب میشوند. این موضوع را میتوان با کد زیر بررسی کرد −
class test:
pass
print (isinstance(int, object))
print (isinstance(str, object))
print (isinstance(test, object))
تمام دستورات print بالا مقدار True را چاپ میکنند.
تابع ()issubclass
این تابع بررسی میکند که آیا یک کلاس، زیرکلاسی از کلاس دیگر هست یا خیر. این تابع مربوط به کلاسهاست، نه نمونههای آنها.
همانطور که قبلاً اشاره شد، تمام کلاسهای پایتون زیرکلاسی از کلاس object هستند. بنابراین، خروجی دستورات print زیر برای همه آنها True است.
class test:
pass
print (issubclass(int, object))
print (issubclass(str, object))
print (issubclass(test, object))
این کد خروجی زیر را تولید خواهد کرد −
True
True
True
تابع ()callable
یک شیء زمانی فراخوانیپذیر (callable) است که فرایند خاصی را اجرا کند. یک تابع پایتون که فرایند مشخصی را انجام میدهد، یک شیء فراخوانیپذیر است. بنابراین (callable(function مقدار True را برمیگرداند. هر تابعی، اعم از توکار، تعریفشده توسط کاربر یا متد، فراخوانیپذیر است. اشیاء مربوط به انواع دادهای توکار مانند int ،str و غیره، فراخوانیپذیر نیستند.
مثال
def test():
pass
print (callable("Hello"))
print (callable(abs))
print (callable(list.clear([1,2])))
print (callable(test))
یک شیء رشتهای فراخوانیپذیر نیست. اما abs تابعی است که فراخوانیپذیر محسوب میشود. متد pop در لیستها فراخوانیپذیر است، اما ()clear در واقع یک فراخوانی تابع است و نه خود شیء تابع، بنابراین فراخوانیپذیر نیست.
این کد خروجی زیر را تولید خواهد کرد −
False
True
True
False
True
یک نمونه از کلاس در صورتی فراخوانیپذیر است که دارای متد ()__call__ باشد. در مثال زیر، کلاس test شامل متد ()__call__ است. بنابراین، از شیء آن میتوان به گونهای استفاده کرد که گویی یک تابع را فراخوانی میکنیم. به همین دلیل، شیءِ کلاسی که دارای تابع ()__call__ باشد، یک شیء فراخوانیپذیر است.
class test:
def __init__(self):
pass
def __call__(self):
print ("Hello")
obj = test()
obj()
print ("obj is callable?", callable(obj))
این کد خروجی زیر را تولید خواهد کرد −
Hello
obj is callable? True
تابع ()getattr
تابع توکار ()getattr مقدار ویژگی نامگذاریشده یک شیء را بازیابی میکند.
مثال
class test:
def __init__(self):
self.name = "Manav"
obj = test()
print (getattr(obj, "name"))
این کد خروجی زیر را تولید خواهد کرد −
Manav
تابع ()setattr
تابع توکار ()setattr یک ویژگی جدید به شیء اضافه کرده و مقداری به آن اختصاص میدهد. همچنین میتواند مقدار یک ویژگی موجود را تغییر دهد.
در مثال زیر، شیء کلاس test دارای یک ویژگی تک به نام name است. ما از ()setattr برای اضافه کردن ویژگی age و تغییر مقدار ویژگی name استفاده میکنیم.
class test:
def __init__(self):
self.name = "Manav"
obj = test()
setattr(obj, "age", 20)
setattr(obj, "name", "Madhav")
print (obj.name, obj.age)
این کد خروجی زیر را تولید خواهد کرد −
Madhav 20
تابع ()hasattr
این تابع توکار اگر ویژگی دادهشده برای آرگومان شیء موجود باشد مقدار True و در غیر این صورت مقدار False را برمیگرداند. ما از همان کلاس test استفاده میکنیم و بررسی میکنیم که آیا ویژگی خاصی دارد یا خیر.
class test:
def __init__(self):
self.name = "Manav"
obj = test()
print (hasattr(obj, "age"))
print (hasattr(obj, "name"))
این کد خروجی زیر را تولید خواهد کرد −
False
True
تابع ()dir
اگر این تابع توکار بدون آرگومان فراخوانی شود، نامهای موجود در اسکوپ (محدوده) فعلی را برمیگرداند. برای هر شیء که به عنوان آرگومان داده شود، لیستی از ویژگیهای آن شیء و ویژگیهای قابل دسترس از طریق آن را برمیگرداند.
-
برای یک شیء ماژول − این تابع ویژگیهای ماژول را برمیگرداند.
-
برای یک شیء کلاس − این تابع ویژگیهای آن کلاس و به صورت بازگشتی ویژگیهای کلاسهای پایه آن را برمیگرداند.
-
برای هر شیء دیگر − ویژگیهای خود شیء، ویژگیهای کلاس آن و به صورت بازگشتی ویژگیهای کلاسهای پایه کلاس مربوطهاش را برمیگرداند.
مثال
print ("dir(int):", dir(int))
این کد خروجی زیر را تولید خواهد کرد −
dir(int): ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
مثال
print ("dir(dict):", dir(dict))
این کد خروجی زیر را تولید خواهد کرد −
dir(dict): ['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
مثال
class test:
def __init__(self):
self.name = "Manav"
obj = test()
print ("dir(obj):", dir(obj))
این کد خروجی زیر را تولید خواهد کرد −
dir(obj): ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
پیشرفت مطالعه: وضعیت خواندهشدن این درس فقط در همین مرورگر ذخیره میشود؛ بدون نیاز به حساب کاربری.