继承和多态
继承的概念:
在现实生活中,继承一般指的是子女继承父辈的财产。那么在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中可以描述为猫和狗都继承自动物。同理,波斯猫和家猫都继承自猫。而斑点狗,泰迪都继承之狗。程序中当我们定义一个class的时候,可以从某个现有的class继承,新的class称之为子类(Subclass),而被继承的class称之为基类、父类或超类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
多继承:
Python中多继承的语法格式如下:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
需要注意圆括号中父类的顺序,如果继承的父类中有相同的方法名,而在子类中使用时未指定,python 将从左至右查找父类中是否包含方法。
重写:
class Animal():
def __init__(self,name,food):
self.name = name
self.food = food
def eat(self):
print('%s喜欢吃%s'%(self.name,self.food))
def shout(self):
print(self.name,"喵喵")
#编写一个Dog类继承Animal
class Dog(Animal):
def __init__(self,name,food):
super().__init__(self,name,food)
def shout(self):#重写父类的shout方法,喵喵叫不是Dog的叫声
print(self.name,"汪汪叫")
#编写一个Cat类继承Animal
class Cat(Animal):
def __init__(self,name,food):
super().__init__(name,food)
#对于Dog和Cat来说,Animal是它们的父类,而Dog和Cat是Animal的子类
#子类获得了父类全部的功能,自动拥有了父类的eat()方法
dog1 = Dog('小狗','骨头')
dog1.shout()
类属性和实例属性:
属性:尽量把需要用户传入的属性作为实例属性,而把同类都一样的属性作为类属性。实例属性在每创造一个类是都会初始化一遍,不同的实例的实例属性可能不同,不同实例的类属性都相同。
1:实例属性:
在__init__(self,…)中初始化
内部调用时都需要加上self.
外部调用时用“对象名.属性名”调用
2:类属性:
在__init__()里初始化
在内部用classname.类属性名调用
外部既可以用classname.类属性名又可以用instancename.类属性名来调用
3:私有属性:
1:双下划线__开头:外部不可通过“对象名.属性名”来访问或者更改实际将其转化为了“_类名__属性名”
单下划线、双下划线、头尾双下划线说明:
__foo__: 定义的是特殊方法,类似 __init__() 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问(创建的实例可以访问),不能用于 from module import *
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
访问权限
访问限制—私有属性:
私有类属性
私有对象属性
为了保护属性不被随意修改和访问,可以将属性定义为私有属性。
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问.
访问限制注意事项:
1.设置为私有属性不能直接通过对象访问属性,但是可以通过“实例化对象名._类名__属性名”直接进行访问。但是不建议这样操作.不同版本的Python解释器可能会把“__属性名”改成不同的变量名。总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
2.通过“对象名.__属性名”直接修改私有属性。
表面上看好像修改了其实并没有,因为Python解释器已经将对象内部的属性名解释成“_类名__属性名”。如果在外部修改相当于另外声明一个属性。
能直接修改吗?类属性可以直接修改通过类名._类名__属性名=(可通过类方法定义后面说明)
类方法与静态方法:
1:普通方法:
def fun_name(self,…):
pass
外部用实例调用
2:静态方法:通过装饰器 @staticmethod 装饰
不能访问实例属性
参数不能传入self
与类相关但是不依赖类与实例的方法
3:类方法:@classmethod
不能访问实例属性
参数必须传入cls
必须传入cls参数(即代表了此类对象-----区别------self代表实例对象),并且用此来调用类属性:cls.类属性名
静态方法与类方法都可以通过类或者实例来调用。其两个的特点都是不能够调用实例属性
静态方法不需要接收参数,使用类名.类属性