簡體   English   中英

如何繼承python基類?

[英]How to inherit a python base class?

dir/
  |
  |___ __init__.py
  |
  |___ Base_class.py
  |
  |___ Subclass.py

__init__.py是空的(如提到這里


/* Base_class.py


class Employee:

    numOfEmployees = 0 # Pure class member, no need to override
    raiseAmount = 1.04 # Could not be pure class member, so, can it be overidden by object?
                           # Yes. make sense
                           # This is why we use self.raiseAmount in methods
    def __init__(self, firstName, lastName, pay):
        self.firstName = firstName
        self.lastName = lastName
        self.pay = pay
        self.email = firstName + '.' + lastName + '@email.com'

        Employee.numOfEmployees += 1

    def fullName(self):
        return '{} {}'.format(self.firstName, self.lastName)

    def appyRaise(self):
        self.pay = int(self.pay * self.raiseAmount)

        @classmethod
        def setRaiseAmt(cls, amount):
            cls.raiseAmount = amount

        @classmethod
        def createEmployee(cls, employeeStr):
            firstName, lastName, pay = employeeStr.split('-')
            return cls(firstName, lastName, pay)

        @staticmethod
        def isWorkDay(day):
            if day.weekday() == 5 or day.weekday() == 6:
                return False
            return True


emp1 = Employee('AAA', 'BBB', 50000)
emp2 = Employee('CCC', 'DDD', 40000)


print Employee.raiseAmount # 1.04
print emp1.raiseAmount     # 1.04
print emp2.raiseAmount     # 1.04

# Regular methods
emp1.fullName()          # Executing fullName(<__main__.Employee object at 0xb7dbef0c>) 
Employee.fullName(emp1)  # same as above 


# With classmethods, the class of the object instance is implicitly passed as the first argument instead of self.

Employee.setRaiseAmt(1.05) # class variable's cls member raiseAmount will get updated

print Employee.raiseAmount # 1.05
print emp1.raiseAmount     # 1.05
print emp2.raiseAmount     # 1.05

emp1.setRaiseAmt(1.05) # Invokes as, setRaise(<class '__main__.Employee'>,1.05)

# Application of class methods as constructors
employeeStr = 'John-Doe-70000'
newEmployee = Employee.createEmployee(employeeStr);

print newEmployee.email
print newEmployee.pay


# With static methods, neither self (the object instance) nor  cls (the class) is implicitly passed as the first argument. They behave like plain functions except that you can call them from an instance or the class:

emp1 = Employee('AAA', 'BBB', 50000)
emp2 = Employee('CCC', 'DDD', 40000)

import datetime
myDate = datetime.date(2016, 7, 10)

print emp1.isWorkDay(myDate) # Executing isWorkDay(myDate)

/* Subclass.py */

from  Base_class import Employee

class Developer(Employee):
    pass

題:

在僅繼承Employee類上:

> python Subclass.py

為什么這下面的輸出? 如何繼承基類?

$ python Subclass.py
1.04
1.04
1.04
1.05
1.05
1.05
John.Doe@email.com
70000
False

你似乎遇到的問題是,當你import一個模塊,它的所有代碼的運行,即使您正在使用from module import name語法剛剛導入的模塊的內容的一部分。 這就是為什么從運行Subclass.py文件中獲得與運行Base_class.py相同的輸出的Base_class.py

如果您不希望在導入Base_class模塊時運行測試代碼,則應將其放在if __name__ == "__main__":塊中。 全局變量__name__通常是模塊的名稱(例如"Base_class" )。 當您將模塊作為腳本運行時,它是"__main__" 因此,測試該字符串可以使您僅在模塊是主腳本時才運行某些代碼,而不是在其他模塊導入該腳本時才運行。

您可能還對子類如何看其父類的屬性感到困惑。 這在Python中有點神奇。 在實例上查找屬性時,首先會檢查實例自己的字典,然后是類的字典,然后是其MRO(方法解析順序,通常是父類鏈)中每個基類的字典,除非您正在執行復雜的多重繼承)。 因此,除非您在Developer類上為其顯式設置新值,否則Employee的繼承屬性將不會顯示在Developer.__dict__

據我所知,如果您創建一些Developer實例並調用它們將繼承的某些方法,則您的代碼應該可以正常工作。 看到的唯一錯誤是Employee中的修飾方法與其他方法的縮進方式不同,但是我懷疑(基於您說的輸出結果)這是將代碼復制到Stack Overflow的問題,而不是真正的錯誤。 您可能要仔細檢查一下,是否沒有混合使用縮進的空格和制表符,這可能導致難以發現的細微錯誤(並且Python 3中不允許混合使用)。

您已將setRaiseAmt聲明為類方法,這意味着無論您是通過類還是通過實例調用raiseAmount ,它都會更新變量raiseAmount 不需要這種方法。 如果要更改默認的加注金額,請直接執行以下操作:

Employee.raiseAmount = ...

如果要設置單個員工的價值,也可以直接通過實例進行設置:

emp1.raiseAmount = ...

總是在實例的屬性字典中創建(或更新)變量。 讀取 raiseAmount的值時,將獲得實例屬性的值(如果存在),否則將獲得類屬性的值。

如果必須提供設置器(例如,這是類分配的要求),請提供單獨的類和實例方法:

@classmethod
def set_default_raise_amount(cls, amount):
    cls.raise_amount = amount

def set_raise_amount(self, amount):
    self.raise_amount = amount

當您導入Employee基類時,首先將Base_class.py文件讀入內存並進行處理,然后將Employee類導入到Subclass.py的名稱空間中。

要測試您是否成功繼承了子類,可以在Subclass.py嘗試實例化Employee類,盡管您需要創建一個構造函數。

將它們添加到您的Developer類。

from Base_class import Employee

class Developer(Employee):
     def __init__(self):
          Super(Employee, self).__init__()

test_dev = Developer('Bob', 'Marley', 1000)

test_dev.fullName()

從Base_class.py導入Employee時,它將整個Base_class.py數據讀取到內存中。 因此,因為您在該文件內創建對象並在Base_class.py中打印它們,所以在設置繼承時將執行它們。

您可能要通過main.py之類的其他文件來創建那些Employee對象。 當您導入Employee類時,這將阻止您處理打印和對象創建請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM