Inheritance
العلم كله مبنى على الوراثة والإكمال من حيث انتهى الآخرون
تخيل ان عندنا كلاس Human كالتالى
class Human(object):
def __init__(self, name, sex):
self._name=name
self._sex=sex
def _set_name(self, name):
self._name=name
def _set_sex(self, sex):
self._sex=sex
name=property(fget=lambda self:self._name, fset=_set_name)
sex=property(fget=lambda self:self._sex, fset=_set_sex)
وعندنا كلاس Employer كالتالى
class Employer(object):
def __init__(self, name, sex, salary):
self._name=name
self._sex=sex
self._salary=salary
def _set_name(self, name):
self._name=name
def _set_sex(self, sex):
self._sex=sex
def _set_salary(self, salary):
self._salary=salary
name=property(fget=lambda self:self._name, fset=_set_name)
sex=property(fget=lambda self:self._sex, fset=_set_sex)
salary=property(fget=lambda self: self._salary, fset=_set_salary)
اكيد لاحظت ان ال Employer هو Human ولكن مش فيه زيادة عن ال Human غير ال salary attribute و ال salary setter وال salary property
يعنى نقدر نقول ال
Employer is-a human
فكل اللى عليك انك تحسن الكود بحيث ان ال Employer يورث كل الصفات + الميثودز الموجودة بال Human ويضيف عليه المميزات الخاصة بيه زى ال salary كالتالى مثلا
class Employer(Human):
def __init__(self, name, sex, salary):
Human.__init__(name, sex)
self._salary=salary
def _set_salary(self, salary):
self._salary=salary
salary=property(fget=lambda self: self._salary, fset=_set_salary)
تعالى نتكلم بمثال اوضح وقريب من العالم الحقيقى بعض الشئ وعلى المثال السابق
إنسان وموظف ومدير
الموظف ماهو إلا إنسان والمدير ماهو إلا انسان مش كدا ؟ تعالى الأول نعرف ال Human class بتاعنا
class Human(object):
def __init__(self, name, color, sex):
#Data members..
self.__name=name
assert sex in Gender.Options #Male or Female only.
self.__sex=sex
self.__color=color
#getters/setters...
def getName(self):
return self.__name
def setName(self, value):
self.__name = value
def getSex(self):
return self.__sex
def setSex(self, value):
self.__sex = value
def getColor(self):
return self.__color
def setColor(self, value):
self.__color = value
#properties...
name = property(getName, setName, None, "Gets/Sets name.")
sex = property(getSex, setSex, None, "Gets/Sets sex.")
color = property(getColor, setColor, None, "Gets/Sets color.")
__str__=lambda self: "<Human object: %s >"%self.__name
__unicode__=__str__
#methods..
def eat(self):
#Eating
pass
def drink(self):
#Drinking
pass
def sleep(self):
#Sleeping
pass
هنا عرفنا صنف جديد بيعبر عن الإنسان وليه متغيرات داخلية زى الإسم واللون والنوع وبعض الميثودز لمعالجتهم وميثودز اخرى مثل eat, drink, sleep
لاحظ ان النوع لازم يكون موجود فى Gender.Options المعرفة كالتالى
class Gender(object):
Male, Female="Male", "Female" #0, 1 whatever!
Options=(Male,Female)
الإسلوب دا يقدر يفيدك لما تيجى عايز تعمل type لنوع صامت او جامد مثلا النوع او الألوان وهكذا
لاحظ ال __str__ دى magic method بيتم استدعائها عند استدعاء print او حتى ال casting بإستخدام str()
لاحظ اننا خلينا __unicode___ نفس المعنى من str (ويفضل انك تستخدم ال unicode على طول الأبلكيشن بتاعك)
تقدر تعرفهم اكيد كالتالى
def __str__(self):
....
def __unicode__(self):
return self.__str__()
نيجى للموظف
class Employer(Human):
def __init__(self, name, color, sex, salary, firm):
#Construct the human with (name, color, sex)
Human.__init__(self, name, color, sex)
#Superize it :)
#super(Employer, self).__init__(name, color, sex)
self.__salary=salary
self.__firm=firm
def getFirm(self):
return self.__firm
def setFirm(self, value):
self.__firm = value
firm = property(getFirm, setFirm, None, "Gets/Sets the firm.")
def getSalary(self):
return self.__salary
def setSalary(self, value):
self.__salary = value
salary = property(getSalary, setSalary, None, "Gets/Sets salary.")
__str__=lambda self: "<Employer object:(%s, %d) >"%(self.getName(), self.salary) #super(Employer, self)
def eat(self):
print "This is my break (eat or having fun hummm?"
def sleep(self):
print "Hi, it's me sleeping!"
هنا بننشئ كلاس جديد مشتق من ال Human وبنجهزه بالبيانات الخاصة بال Human (اسم ولون ونوع) والبيانات الخاصة بالموظف (المرتب والشركة) ومتغيرات تعالج الحالة
اعدنا تعريف بعض الميثودز(الطرق) الخاصة بال Human بمعنى انهم اصبحت overriden
نيجى للمدير ومالمدير الا موظف ولكن له صلاحيات اعلى زى مثلا اعطاء علاوة او فصل موظف وهكذا
class Manager(Employer):
def __init__(self, name, color, sex, salary, firm):
#Employer.__init__(self, name, color, sex, salary, firm)
super(Manager, self).__init__(name, color, sex, salary, firm)
#print self.__dict__
#{'_Human__color': 'white', '_Employer__salary': 200000, '_Human__name': 'Wael', '_Employer__firm': 'Sun', '_Human__sex': 'Male'}
def raiseSalaryOf(self, emp, theraise):
assert (isinstance(emp,Employer) and emp.firm==self.firm)
emp.salary += theraise
لاحظ انك لو طلبت .__dict__ لأى كلاس هيعرضلك قاموس dictionary فيه القيم اللى وراثها من المتغيرات الداخلية والمقطع الأول منها بيعبر عن منين موروثة
تعالى ننفذ عالمنا الصغير دا كتطبيق سريع
if __name__=="__main__":
ahmed=Employer("ahmed", "white", Gender.Male, 50000, "Google")
omar =Employer("omar", "black", Gender.Male, 40000, "Sun")
tina =Employer("christina", "white", Gender.Female, 50000, "Google")
emps=(ahmed, omar, tina)
wael=Manager("Wael", "white", Gender.Male, 200000, "Sun")
wael.raiseSalaryOf(omar, 9000)
print issubclass(Employer, Human)
print isinstance(ahmed, Human) #Ahmed is a Human..
print Human.__bases__ #inherits object.
print Manager.__bases__ #Inherits Employer..
لاحظ ان issubclass(C, B) بتسأل هل الصف C مشتق من B او لأ
لاحظ isinstance(object, Type) بتسأل هل ال object دا تم انشاءه من الصف Type او لأ
لاحظ ان __bases__ بتعبر عن الأب (او الأباء لو ورثت من اكتر من صف)
احنا استخدمنا assert فى كذا جزئية لكن ايه هى assert ?
Assert بتفيد فى عمل تصحيح سريع بحيث انك تضمن عدم التنفيذ فى حال وجود خطأ
امتة استخدم ASSERT ? استخدامها مقترن بحالة التطوير والمحل مثلا مش هتعمل كود فيه assert statement للمستخدم النهائى ، لكن ممكن تحطها فى مكتبة هيستخدمها مطور (هيراعى المتطلبات مظبوط) غير كدا استخدم ال Exceptions, Errors
الوراثة المتعددة
class Wolf(object):
def __init__(self):
self.__bite=True
can_bite=lambda self:self.__bite
def fullmoon(self):
print "Wooooooooooooooooooooooooo"
def bite(self, h):
print "I'm cursed"
class Werewolf(Human, Wolf):
def __init__(self, name, color, sex):
Human.__init__(self, name, color, sex)
Wolf.__init__(self)
تابع مثالنا السابق هنا عندنا صف بإسم wolf وصف بإسم مستذئب بيورث الإنسان والذئب
yasser=Werewolf("yasser", "black", Gender.Male)
print yasser.__dict__
print "Can bite? ", yasser.can_bite()
yasser.bite(ahmed)
print Werewolf.__bases__
الناتج
{'_Human__color': 'black', '_Wolf__bite': True, '_Human__name': 'yasser', '_Human__sex': 'Male'}
Can bite? True
I'm cursed
(<class '__main__.Human'>, <class '__main__.Wolf'>)
الأباء للمستذئب زى ماشفت فى ناتج __bases__
(<class '__main__.Human'>, <class '__main__.Wolf'>)