Author Topic: Inheritance الوراثة فى بايثون  (Read 886 times)

Ahmed Youssef

  • Helping Freak
  • Administrator
  • Active Member
  • *****
  • Posts: 242
    • View Profile
    • WWW
    • Email
Inheritance الوراثة فى بايثون
« on: October 26, 2008, 03:39:21 AM »


Inheritance

 العلم كله مبنى على الوراثة والإكمال من حيث انتهى الآخرون

تخيل ان عندنا كلاس Human كالتالى
Code: [Select]
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 كالتالى

Code: [Select]
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 كالتالى مثلا
Code: [Select]
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 بتاعنا
Code: [Select]
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 المعرفة كالتالى
Code: [Select]
class Gender(object):
    Male, Female="Male", "Female" #0, 1 whatever!
    Options=(Male,Female)


الإسلوب دا يقدر يفيدك لما تيجى عايز تعمل type لنوع صامت او جامد مثلا النوع او الألوان وهكذا
لاحظ ال __str__ دى magic method بيتم استدعائها عند استدعاء print او حتى ال casting بإستخدام str()
لاحظ اننا خلينا __unicode___ نفس المعنى من str (ويفضل انك تستخدم ال unicode على طول الأبلكيشن بتاعك)
تقدر تعرفهم اكيد كالتالى
Code: [Select]
def __str__(self):
....

def __unicode__(self):
return self.__str__()


نيجى للموظف
Code: [Select]
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

نيجى للمدير ومالمدير الا موظف ولكن له صلاحيات اعلى زى مثلا اعطاء علاوة او فصل موظف وهكذا
Code: [Select]
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 فيه القيم اللى وراثها من المتغيرات الداخلية والمقطع الأول منها بيعبر عن منين موروثة

تعالى ننفذ عالمنا الصغير دا كتطبيق  سريع
Code: [Select]
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

الوراثة المتعددة
Code: [Select]
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 وصف بإسم مستذئب بيورث الإنسان والذئب
Code: [Select]
    yasser=Werewolf("yasser", "black", Gender.Male)
    print yasser.__dict__
    print "Can bite? ", yasser.can_bite()
    yasser.bite(ahmed)
    print Werewolf.__bases__

الناتج
Code: [Select]
{'_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__
Code: [Select]
(<class '__main__.Human'>, <class '__main__.Wolf'>)




« Last Edit: October 04, 2009, 04:46:10 PM by Ahmed Youssef »
Logged

Life is just a chance to grow a soul. - A. Powell
Weblog: http://ahmedyoussef.wordpress.com/