2017-05-11 12 views
-1
dir/ 
    | 
    |___ __init__.py 
    | 
    |___ Base_class.py 
    | 
    |___ Subclass.py 

__init__.pyhere述べたように)空であるPythonの基本クラスを継承する方法は?


/* 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 

質問:

> python Subclass.py 

なぜ、この下の出力:では、ちょうどEmployeeクラスを継承しますか?どのように基本クラスを継承するのですか?

$ python Subclass.py 
1.04 
1.04 
1.04 
1.05 
1.05 
1.05 
[email protected] 
70000 
False 
+3

'Employee'をインポートすると、Pythonは' 'それを実行します。したがって、ファイルの最後にある 'print'文はすべて実行されます。 –

+0

@StephenRauchすべてのprintステートメントは 'Employee'の一部ではありません。あなたはEmployeeをインポートするだけではありません。 – overexchange

+2

あなたはEmployeeをインポートするだけではありません。ファイル全体が評価されています....あなたが何をしているのかは 'Employee'をあなたのネームスペースに入れています –

答えて

2

importモジュールでは、モジュールの内容の一部をインポートするためにfrom module import nameという構文を使用していても、すべてのコードが実行されるという問題があります。このため、Base_class.pyを実行した場合と同じように、Subclass.pyファイルを実行しても同じ出力が得られます。

Base_classモジュールをインポートするときにテストコードが実行されないようにするには、if __name__ == "__main__":ブロック内に配置する必要があります。グローバル変数__name__は、通常、モジュールの名前です("Base_class"など)。モジュールをスクリプトとして実行すると、"__main__"になります。したがって、その文字列をテストすると、モジュールがメインスクリプトである場合にのみコードを実行し、他のモジュールによってインポートされている場合には実行しません。

サブクラスが親クラスの属性をどのように見ているのか混同されることもあります。これはPythonではやや魔法です。インスタンスの属性を検索すると、まずインスタンスの独自の辞書がチェックされ、次にクラスの辞書、次にMRO内の各基本クラスの辞書(メソッド解決順序、通常は親クラスのチェーンが順番に複雑な多重継承をしている)。したがって、継承された属性Employeeは、Developerクラスに明示的に新しい値を設定しない限り、Developer.__dict__に表示されません。

私が見る限り、Developerのインスタンスを作成して継承するメソッドを呼び出すと、コードはうまく動作するはずです。表示されている唯一のエラーは、Employeeの装飾されたメソッドは他のメソッドと同じインデントされていないことですが、スタックオーバーフローにコードをコピーすることによる問題であると思われます。本当のバグよりも。インデントのためにスペースとタブを混ぜていないことを再確認したい場合があります。これは見えにくい微妙なエラーにつながります(混在させることはPython 3では許可されていません)。

1

あなたはそれはあなたがクラスまたはインスタンスを経由して、それを呼び出すかどうかクラス変数raiseAmountを更新することを意味し、クラスメソッドであるとsetRaiseAmtを宣言しました。このクラスメソッドは必要ありません。デフォルトの昇給額を変更したい場合は、単にそれを直接実行します。

Employee.raiseAmount = ... 

あなたは、個々の従業員の値を設定したい場合は、直接それを行うが、インスタンス経由:

emp1.raiseAmount = ... 

この常には、インスタンスの属性辞書に変数を作成(または更新)します。 の値がraiseAmountの場合、存在する場合はinstance属性の値が取得されます。存在しない場合は、class属性の値が取得されます。あなたは従業員の基本クラスをインポートすると

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

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

はBase_class.pyファイルは次のとおりです。

あなたがセッターを提供しなければならない場合は、別のクラスとインスタンスメソッドを提供する(例えば、クラス割り当てのための要件です)メモリに読み込まれ、最初に処理し、Employeeクラスは、あなたがコンストラクタを作成する必要がありますけれども、あなたがSubclass.pyで、Employeeクラスをインスタンス化しようとすることができます成功したサブクラス化しましたかどうかをテストするにはSubclass.py

の名前空間にインポートされます。

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() 
0

EmployeeをBase_class.pyからインポートすると、Base_class.pyデータ全体がメモリに読み込まれます。したがって、そのファイル内にオブジェクトを作成し、Base_class.pyの中にそれらを出力するので、継承を設定するときにそれらを実行します。

これらのEmployeeオブジェクトは、main.pyなどの別のファイルを使用して作成することをお勧めします。これにより、Employeeクラスをインポートするときに印刷およびオブジェクトの作成要求を処理できなくなります。

+0

はい、私は 'main.py'などがインスタンス化されることを知っています。 – overexchange

関連する問題