PythonGuide/OOP Inheritance
من PFWiki
الوراثة
العلم كله مبنى على الوراثة والإكمال من حيث انتهى الآخرون
تخيل ان عندنا كلاس 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'>)
