سلام
خوب ببینید هر کلاس شامل مجموعهای از صفتها و کارهاست.. یکم توضیحات بیشتر رو من اینجا نوشتم شاید به دردت بخورن :
http://python.coderz.ir/lessons/l05.htmlتو پایتون ما دو نوع اتریبیوت (صفت) داریم: اتریبیوتهایی که در سطح کلاس (Class Attribute) و اتریبیوتهایی که در سطح شیهای کلاس (Instance Attribute) تعریف میشن.
اتریبیوتهای کلاس توسط تمام نمونه یا اشیایی که از اون کلاس ساخته میشن، در دسترسه.. یعنی اگر مقدار اونها تغییر داده بشه، برای تمام نمونهها یا اشیای کلاس هم تغییر پیدا میکنه، این نوع اتریبیوت توسط نام کلاس و اشیا کلاس در دسترس قرار میگیره
ولی اتریبیوتهای شی این طور نیستند و فقط در حوزه هر شی تعریف میشن، فقط با استفاده از اشیا در دسترس هستند و تغییر اونها توسط شی هم فقط موجب تغییر مقدار اون اتریبیوت برای همون شی میشه...
یه مثال ساده:
>>> class Test:
... class_variable = 1
... def __init__(self, arg_1, arg_2):
... self.instance_variable_1 = arg_1
... self.instance_variable_2 = arg_2
همونطور که مشخصه الان کلاس Test یه اتریبیوت کلاس و دو اتریبیوت شی داره.
دو نمونه یا شی از کلاس می سازیم:
>>> t1 = Test('a1', 'b1')
>>> t2 = Test('a2', 'b2')
متد __init__ نقش سازنده (constructor) رو در کلاس های پایتون داره و به صورت خودکار بلافاصله بعد از ایجاد شی فراخوانی میشه. آرگومان اول این متد هم همیشه به شی ایجاد شده اشاره داره... که همیشه باید باشه. به این ترتیب با ایجاد هر شی این متد میاد و برای اون شی دو تا اتریبیوت هم ایجاد میکنه که مقدار اونها در لحظه ایجاد نمونه یا شی باید تعیین بشن.
کار با اتریبیوت کلاس:
>>> Test.class_variable
1
>>> t1.class_variable
1
>>> t2.class_variable
1
>>> Test.class_variable = 3
>>> t1.class_variable
3
>>> t2.class_variable
3
نکتهای که هست اینه که هر وقت خواستیم مقدار اتریبیوت کلاس رو تغییر بدیم، باید همیشه از نام خود کلاس استفاده کنیم. در غیر این صورت یعنی تغییر مقدار اتریبیوت کلاس با استفاده از شی، موجب ایجاد یک اتریبیوت شی جدید برای اون شی میشه:
>>> t1.class_variable = 5
>>> Test.class_variable
3
>>> t1.class_variable
5
>>> t2.class_variable
3
کار با اتریبیوت شی هم فکر نکنم نیاز به مثالی داشته باشه... حالا اگه سوالی داشتی.. که خوب هستم در خدمتت...
در مورد کلاس خودت:
قسمت پایین کدت رو اینطور اصلاح میکنم:
print(x.allow)
print(x.hello)
print(Test.fun)
x.damn()
اون None هم به خاطر این هستش که سطر آخر کد شما print تو print شده!.. متد damn خودش یک print داره که خروجی رو به خروجی استاندارد پایتون که اینجا کامند لاین میشه میفرسته .... و نه به شکل پارامتر به تابع print دوم... و در واقع همونطور که یکی از دوستان هم گفت ... تابع print در سطر آخر اصلا چیزی رو دریافت نمیکنه تا چاپ کنه... و None هم حاصل چاپ هیچی هستش.