目录
八、面向对象
7、继承
7.1、继承的简介
继承是面向对象三大特性之一
继承指的是一个类继承另一类的特性(属性、方法)
一个类可以是一个或多个类的子类,也可以指定多个超类
7.2、继承
在定义一个类时,class 语句中类名后面圆括号中加上父类名字
语法:
calss 类名(父类):
pass
A 是 B 的 父类
B 是 A 的 子类
子类 可以获取父类的方法
示例1:
class A():
def afn(self):
print('这是A类')
class B(A):
def bfn(self):
print('这是B类')
c = B()
c.afn()
c.bfn()
>> 这是A类
>> 这是B类
7.3、issubclass( ) 方法
issubclass 用于检测一个类和另一类的子类
返回 True 是子类
返回 False 不是子类
内置方法:
issubclass(A,B)
示例1:
class A():
pass
calss B(A):
pass
calss C(A):
pass
print(issubclass(C,B))
>> False
print(issubclass(B,A))
>> True
print(issubclass(C,A))
>> True
7.4、调用的先后顺序
在实例中调用方式或属性时,
实例对象会先在自己代码块中寻找,父类中(父类的父类,等等) 查找,直到找到指定的方法或报错
查找属性,父类中(父类的父类,等等) 查找,直到找到指定的属性 或 报错
7.5、方法的重写/覆盖
在实例调用方法时,
如果子类中有和父类的相同的方法,子类的方法则会覆盖父类中的方法
示例1:
class A():
def afn(self):
print('这是A类')
class B(A):
def afn(self):
print('这是B类')
a = A()
b = B()
a.afn()
b.afn()
>> 这是A类
>> 这是B类
7.6、super( ) 方法
super可以动态的获取父类中的属性
super可以将在所有的父类(以及父类的父类,等等)中查找,直到找到指定的属性或引发异常。
语法:
super().__init__(A,B,C)
实例1:
class A():
def __init__(self,name):
self._name = name
class B(A):
def __init__(self,age,name):
self._age = age
super().__init__(name)
b = B(18,'张三')
print(b._name,b._age)
>> 18 张三
7.7、多重继承
在Python中,一个子类可以继承多个父类的特性
多重继承在父类中查找属性和方法是按照顺位查找,先左1父类开始找,再往右,直到找到指定的属性或者引发错误
示例1:
class A():
def fa():
print('这是A类的方法')
class B():
def fa():
print('这是B类的方法')
def fb():
print('这是B类的方法')
class C(A, B):
def fc(self):
C.fa()
C.fb()
c = C()
c.fc()
>> 这是A类的方法
>> 这是B类的方法
8、多态
8.1、多态
多态是面向对象的三大特性之一
多态指的是可以同样的处理不同类型的对象,每当无需指定对象是什么样的就能对其执行操作时,就是多态在起作用
示例1:# 可以传递任意对象,函数并不会检测你传递对象是否会报错,这种特性就是多态
class A():
def __init__(self,name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
def fn(b):
print('a = %s'%b.name)
L = [1,2,3,4,5]
a = A(L)
fn(a)
>> a = [1, 2, 3, 4, 5]
8.2、鸭子类型
多态 有时又称为 鸭子类型
如果走起来像鸭子,叫起来像鸭子,那么它就是鸭子。
8.2.1、转自百度百科:鸭子类型
在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。
这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试(见下面的“历史”章节),“鸭子> > 测试”可以这样表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭> > 子。”
在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。例如,在不使> 用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它> 的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调> 用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥> 有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型> 的方式因此得名。
鸭子类型通常得益于"不"测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正> 确使用。
静态语言中的鸭子类型一些通常的静态语言如Boo和C#第四版,有一些额外的类型注解,它们指示编译器将类的类型检查安排在运行时而不是编译时,并在编译器的输出中包含用于运行时类型检查的代码。这些附加的内容允许这些语言享受鸭子类型的大多数益处,仅有的缺点是需要在编译时识别和指定这些动态类。
与其他类型系统的比较
结构类型系统
鸭子类型和结构类型相似但与之不同。结构类型由类型的结构决定类型的兼容性和等价性,而鸭子类型只由结构中在运行时所访问的部分决定类型的兼容性。Objective Caml语言使用结构类型系统。
接口
接口可以提供鸭子类型的一些益处,但鸭子类型与之不同的是没有显式定义任何接口。例如,如果一个第三方Java库实现了一个用户不允许修改的类,用户就无法把这个类的实例用作一个自己定义的接口的实现,而鸭子类型允许这样做。模板或泛型
模板函数或方法在一个静态类型上下文中应用鸭子测试;这同时带来了静态和动态类型检查的一般优点和缺点。同时,由于在鸭子类型中,只有“在运行时被实际调用的”方法需要被实现,而模板要求实现“在编译时不能证明不可到达的”所有方法,因此鸭子类型更具有可伸缩性。
实例包括带有模板的C++语言和Java语言的泛型。 [2]
9、类和实例的属性和方法
9.1、 类属性
在类中定义的属性就是类属性
类和实例都可以访问,只能由类修改
9.2、类方法
被 @classmethod 装饰的方法就是类方法,类方法传递的是cls
cls 表示当前类对象,和self一样会自动传递
9.3、实例属性
在实例对象中定义的属性就是实例属性
实例属性只能由实例属性访问和修改
9.4、实例方法
定义方法中带有 self 的形参都是实例方法
self 表示当前调用实例对象,和cls一样会自动传递
9.5、静态方法
被 @staticmethod 装饰的方法就是静态方法
静态方法不需要传递 self
静态方法可以直接调用
示例1:
class A():
a = 10 # 这是一个类属性
@classmethod
def fn1(cls): # 这是一个类方法
print(cls.a)
def fn2(self): # 这是一个实例方法
print(self.a)
@staticmethod
def fn3(): # 这是一个静态方法
print('这是静态方法')
b = A()
b.a = 20 # 这是一个实例属性
A.fn1()
b.fn2()
A.fn3()
b.fn3()
>> 10
>> 20
>> 这是静态方法
>> 这是静态方法