python 面向对象-继承、封装和多态
1、面向对象的三大特性:
继承、封装和多态
2、继承
- 语法:class Student(父类):
- 变量可以被继承
-
#coding=utf-8 import test9 class Student(test9.Person): sum = 0 def __init__(self,name,age): #构造函数 self.name = name self.age = age def do_homework(self):#实例方法 self.do_english_homework() print(self.name +" do homework") def do_english_homework(self): print(self.name+ " do english homework") def __marketing(self,score): if score < 0: return else: self.score = score print (self.name+" score :" + str(score))
- 将一些应该父类拥有的属性,放到父类
-
class Person(): def __init__(self,name,age): #构造函数 self.name = name self.age = age def getName(self,name):#实例方法 self.name = name print(self.name)
这个是子类
-
#coding=utf-8 from test9 import Person class Student(Person): sum = 0 # def __init__(self,name,age): #构造函数 # self.name = name # self.age = age def do_homework(self):#实例方法 self.do_english_homework() print(self.name +" do homework") def do_english_homework(self): print(self.name+ " do english homework") student1 = Student("anson",19) print(student1.__dict__)
输出
-
[Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" {'age': 19, 'name': 'anson'}
这说明,变量是可以被继承的。
- 方法可以被继承
-
#coding=utf-8 from test9 import Person class Student(Person): sum = 0 # def __init__(self,name,age): #构造函数 # self.name = name # self.age = age def do_homework(self):#实例方法 self.do_english_homework() print(self.name +" do homework") def do_english_homework(self): print(self.name+ " do english homework") student1 = Student("anson",19) student1.getName() # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" # anson
- 和Java一样,python也是单继承
- 父类构造函数和子类构造函数
- 子类构造方法中显式调用父类构造方法
#coding=utf-8 from test9 import Person class Student(Person): sum = 0 def __init__(self,school): self.school = school def do_homework(self):#实例方法 self.do_english_homework() print(self.name +" do homework") def do_english_homework(self): print(self.name+ " do english homework") student1 = Student("anson") student1.getName()
输出:报错
[Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" Traceback (most recent call last): File "/Users/anson/Documents/Project/python_ToolCodes/test8.py", line 17, in <module> student1.getName() File "/Users/anson/Documents/Project/python_ToolCodes/test9.py", line 7, in getName print(self.name) AttributeError: Student instance has no attribute 'name'
报错原因是缺少父类的构造函数的属性,即然是学生,那肯定也是人,也是要有姓名和年龄的
所以需要改写成:
#coding=utf-8 from test9 import Person class Student(Person): sum = 0 def __init__(self,school,name,age): self.school = school #Person.__init__(name,age)#显示调用父类构造函数,显然是不行的 Person.__init__(self,name,age)#手动传入self def do_homework(self):#实例方法 self.do_english_homework() print(self.name +" do homework") def do_english_homework(self): print(self.name+ " do english homework") student1 = Student("yangzte","anson",19) student1.getName() # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" # anson
问题1:子类构造方法中,显示调用父类的构造方法就可以了,且用父类名就可以了
问题2:为什么需要必须显示的传入self呢?前面说的self 是python自动给我们传的。
一个类调用一个实例方法,本身不伦不类,但是python就是可以这么干,所以
Person.__init__(self,name,age)#手动传入self
显示调用父类构造方法可以这么干
那为什么必须传self呢?
因为如果我们new 个对象,其实是python 隐式调用了构造方法,但是self 它也是帮我们传入了的,只是我们看不见。
包括我们用对象去调用构造方法,也是不传self的,实质上,对象就是self,python是知道的,所以对象调用构造方法或者是实例方法时,对象.构造方法(),或者对象.实例方法(),python自己就把“对象”当成self 传给构造方法__init__(self, , ,)或者实例方法(self,,,)
但是用个类去调用一个构造方法,python都不知道具体对象到底是谁,那它就认为,跟调用普通方法没什么区别,普通方法要传全部必须参数,那这里也得着么传全了
(能力有限,解释只能解释到这个肤浅的层面了)
- 子类构造方法中隐式调用父类构造方法
- super(Student,self).__init__(name,age)#隐式调用父类构造函数;显然报错了
这是为什么呢?解答在这里
https://blog.csdn.net/andos/article/details/8973368
-
#coding=utf-8 from test9 import Person class Student(Person): sum = 0 def __init__(self,school,name,age): self.school = school #Person.__init__(name,age)#显式调用父类构造函数,显然是不行的 #Person.__init__(self,name,age)#手动传入self是可以的 super(Student,self).__init__(name,age)#隐式调用父类构造函数, def do_homework(self):#实例方法 self.do_english_homework() print(self.name + " do homework") def do_english_homework(self): print(self.name+ " do english homework") student1 = Student("yangzte","anson",19) student1.getName() # [Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" # Traceback (most recent call last): # File "/Users/anson/Documents/Project/python_ToolCodes/test8.py", line 19, in <module> # student1 = Student("yangzte","anson",19) # File "/Users/anson/Documents/Project/python_ToolCodes/test8.py", line 10, in __init__ # super(Student,self).__init__(name,age)#隐式调用父类构造函数, # TypeError: super() argument 1 must be type, not classobj
要怎么解决呢?
- 看看原来的父类
-
#coding=utf-8 class Person(): def __init__(self,name,age): #构造函数 self.name = name self.age = age def getName(self):#实例方法 print(self.name)
- 其实就是父类如果是无源之水,那就会报错,比如student的父类也得是从别的父类继承,即使是继承自万物之源Object 类 ,那也是必须的
class Person(object):在这句,传入了object类
-
#coding=utf-8 class Person(object): def __init__(self,name,age): #构造函数 self.name = name self.age = age def getName(self):#实例方法 print(self.name)
输出:不报错了
-
[Running] python -u "/Users/anson/Documents/Project/python_ToolCodes/test8.py" anson