派生的概念,当子类添加自己的新的属性或者自己这里重新定义这些属性(不会影响父类),需要注意的是,一旦重新定义了自己的属性与父类的重名,那么调用新增的属性时,就以自己的为准了
在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有时候可能需要重用父类的那个函数功能,应该是用调用普通函数的方式,即类名func(),此时就与普通函数相同了
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止,而这个MRO列表的构造是通过一个C3线性化算法来实现的,实际上就是合并了所有的父类的MRO列表并遵循如下三个准则
1.子类会先于父类被检查
2.多个父类会根据它们在列表的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如果继承了多个父类,那么属性的查找方式有两种,分别是深度优先和广度优先
简单就说就是会按照mor列表里的顺序去找方法
那么这个列表到底是什么顺序去找的属性呢?
python的mro列表的产生决定了查找的方式,
【python2中的类分为两种,一种是新式类,一种是经典类】
# # python2中的经典类:没有继承object的类以及它的子类都称为经典类
#
# class Foo:
# pass
#
#
# class Bar(Foo):
# pass
#
# # python2中的新式类:继承object的类以及它的子类都称为新式类
# class Foo(object):
# pass
#
# class Bar(Foo):
# pass
# python3中所有的类都是新式类,因为所有的类都是默认继承object的
# class Foo:
# pass
对于经典类就是深度优先,对于新式类就是广度优先(对象自己这里>>自己的类>>父类)
【15.在子类中重用父类的方法和属性】
在子类中重用父类的方法---指名道姓法(不依赖继承)
class Hero:
def __init__(self, nickname, life_value, aggresivity):
self.nickname = nickname
self.life_value = life_value
self.aggresivity = aggresivity
def attack(self, enemy):
enemy.life_value -= self.aggresivity
class Garen(Hero):
camp = 'Demacia'
def __init__(self, nickname, life_value , aggresivity, weapon):
Hero.__init__(self, nickname, life_value , aggresivity)
self.weapon = weapon
def attack(self, enemy):
Hero.attack(self, enemy) #指名道姓,直接指定调用函数的对象
print('from Garen Class')
g = Garen('草丛', 100, 30,'大保健')
print(g.__dict__)
在子类中重用父类的方法---super()(依赖继承)
主要有子类继承了父类的,python就会根据MRO列表,计算出继承的执行的顺序关系,而super()就是在MRO列表中去找父类的执行方式【有一个坑要注意的,super()方法并不是找父类,而是根据MRO列表去执行顺序!即使看上去没有继承关系的也必须去根据MRO列表执行】
# 方式二 super继承
class Hero:
def __init__(self, nickname, life_value, aggresivity):
self.nickname = nickname
self.life_value = life_value
self.aggresivity = aggresivity
def attack(self, enemy):
enemy.life_value -= self.aggresivity
class Garen(Hero):
camp = 'Demacia'
def __init__(self, nickname, life_value , aggresivity, weapon):
super().__init__(nickname, life_value , aggresivity)
self.weapon = weapon
def attack(self, enemy):
super(Garen,self).attack(enemy) #得到了父类的对象(依赖继承,不用再传self)
print('from Garen Class')
class Riven(Hero):
camp = 'Noxus'
r = Riven('瑞文',100,30)
g = Garen('草丛', 100, 30,'大保健')
g.attack(r)
print(r.life_value)
【16.组合】
什么是组合?
什么是什么(老师是人、学生是人),这种关系用继承
什么有什么(老师有生日,学生有生日),这种关系用组合
# 选课系统
class People:
school = 'Luffycity'
def __init__(self, name, age,sex):
self.name = name
self.age = age
self.sex = sex
class Teather(People):
def __init__(self, name, age,sex, level, salary):
super().__init__(name, age,sex)
self.level = level
self.salary = salary
def teach(self):
print('%s is teaching' % self.name)
class Student(People):
def __init__(self, name, age, sex, class_time):
super().__init__(name, age, sex)
self.class_time = class_time
def learn(self):
print('%s is talking' % self.name)
class Course:
def __init__(self,course_name, course_price, course_period):
self.course_name = course_name
self.course_price = course_price
self.course_period = course_period
def tell_info(self):
print(self.course_name, self.course_period, self.course_price)
teacher1 = Teather('大胖', 99, '男', '低级', 5000)
teacher2 = Teather('小胖', 89, '男', '中级', 3000)
stu1 = Student('小猪',20,"男", "08:30:00")
python = Course('python', 8900, '6mons')
linux = Course('Linux',1200, '3mons')
teacher1.course = python
teacher2.course = python
# teacher1.course.tell_info()
stu1.course1 = python
stu1.course2 = linux
stu1.course1.tell_info()
stu1.course2.tell_info()
【17.抽象类与归一化】
抽象类的引入
相似的类里有相同的功能,但是调用的方法名称不同,对使用者造成困难,最好能统一类的方法
python中没有像JAVA那样提供了interface的接口类去抽象几个类的特征,但是有它独特的方法--使用父类的继承就可以了,
问题:虽然降低的复杂度,但是不能硬性限制类的继承方法,如何限制呢?
使用抽象类啊!使用abc模块,对父类使用metaclass=abc.ABCMeta,并且对函数使用装饰器@abc.abstractmethod
抽象类本质还是类,抽象类只能被继承不能被实例化,它的功能只是为了规范子类,本身就是不能被实例化的,
抽象类会降低后期类的使用的复杂度,尽量在写程序的时候先使用这个方式去规范后面类继承的方法
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def run(self):
pass
@abc.abstractmethod
def eat(self):
pass
class People(Animal):
def run(self):
print('people is walking')
def eat(self):
print('people is eating')
class People:
def walk(self):
print('is walking')
class Pig:
def run(self):
print('is running')
class Dog:
def zou(self):
print('is zouing')
p1 = People()
pig1 =Pig()
dog1 = Dog()
p1.walk()
pig1.run()
dog1.zou()
【18.多态与多态性】
面向对象的第二特性:多态(同一种事物的多种形态),比如动物有人、狗、猪的形态
文件也有多种形态,文本文件、可执行文件等
多态性(多态动态性绑定):
可以不考虑实例类型的情况下,直接使用实例
多态性的好处:1.增加了程序的灵活性,以不变应万变,使用者都是同一种形式去调用(func(animal))
2.增加了程序的可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class People(Animal):#动物的形态之一:人
def talk(self):
print('say hello')
class Dog(Animal):#动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal):#动物的形态之三:猪
def talk(self):
print('say aoao')
class Cat(Animal):
def talk(self):
print('say miaomiao')
# 多态性:指的是在可以不考虑对象的类型的情况下,而直接使用对象
# 多态性就是不用考虑自己的实例类的具体类型直接执行就完事了
# 静态的多态性:使用+方法的时候无需考虑数据类型,只要是列表、数字、字符串,直接都可以相加,加就完事了
p1 = People()
d1 = Dog()
pig1 = Pig()
cat1 = Cat()
p1.talk()
d1.talk()
pig1.talk()
# 使用了同一个接口,就像学车一样,不会学开什么车,只是开车的方法就可以了
def func(animal):
animal.talk()
func(p1)
func(pig1)
func(d1)
func(cat1)
鸭子类型:看上去是一个鸭子,具有鸭子的特征,那就是鸭子
# class File:
# def read(self):
# pass
#
# def write(self):
# pass
#
#
# class Disk:
# def read(self):
# print('disk read')
#
# def write(self):
# print('disk write')
#
# class Text:
# def read(self):
# print('text read')
#
# def write(self):
# print('text writre')
#
# disk = Disk()
# text = Text()
#
# disk.read()
# disk.write()
# text.read()
# text.write()
# 序列类型:列表list、元祖tuple、字符串str
l = list([1,2,3])
t = tuple(('a','b'))
s = str('hello')
# print(l.__len__())
# print(t.__len__())
# print(s.__len__())
# 提供接口
def len(obj):
return obj.__len__()
print(len(l))
【19.封装之如何隐藏属性】
封装:从字面上就是隐藏,实际封装不是单纯的意义的隐藏(属性名前 __name)
在类的定义阶段__name就会执行代码,识别__name的就会改成classname__name形成封装
python通过一种变形的操作来隐藏起来,在定义阶段就隐藏
特点:
1.变形完以后,类外部无法直接访问到obj.__AttrName
2.在类的内部obj.__AttrName是可以调用的,是因为在类的定义阶段就已经改成了变形的格式了
3.子类无法覆盖父类__开头的属性
【总结】
1.这种机制也没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:类名__属性名,然后就可以访问了,如a._A__N
2.变形的过程只在类的定义时发生过一次,在定义的后的赋值操作,不会变形,要隐藏就放在类里面!别等人家都生成了你再想隐藏!
3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
# class A:
# __x = 1
#
# def __init__(self, name):
# self.__name = name
#
# def __foo(self):
# print('run foo')
# def bar(self):
# self.__foo()
# print('form bar')
#
# a = A('panda')
# a.bar()
# class Foo:
# def func(self):
# print('from foo')
#
# class Bar(Foo):
# def func(self):
# print('from bar')
#
# b = Bar()
# b.func()
# class Foo:
# def __func(self):
# print('from foo')
#
#
# class Bar(Foo):
# def __func(self):
# print('from bar')
#
#
# b = Bar()
# b._Bar__func()
【20.封装的意义】
封装的意义:封装数据属性或函数属性
1. 将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。
2. 封装方法:目的是隔离复杂度
# 封装数据属性:明确的区分内外,只能在内部开一个接口让外部去间接的访问,可以控制用户的使用行为,可以打印为固定的格式
# 把真实的数据隐藏起来,只能访问定制的格式
# class People:
# def __init__(self, name, age):
# self.__name = name
# self.__age = age
#
# def tell_info(self):
# print('Name:<%s> Age:<%s>' %(self.__name, self.__age))
#
# def set_info(self,name, age):
# if not isinstance(name, str):
# print('名字必须是字符串类型')
# return
# if not isinstance(age, int):
# print('年龄必须是数字类型')
# return
# self.__name = name
# self.__age = age
#
#
# p = People('panda', 19)
# p.tell_info()
# p.set_info('zombie', 1)
# p.tell_info()
# 目的二:隔离复杂度
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入取款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
a = ATM()
a.withdraw()
【21.封装与可扩展性】
封装的可扩展性高体现在哪里?
使用者的方法没有变,需求只需要变自己类的方法里的函数属性就可以了
class Room:
def __init__(self, name, owner, height, weight, length):
self.name = name
self.owner = owner
self.__height = height
self.__weight = weight
self.__length = length
def area(self):
return self.__weight*self.__length*self.__height
r = Room('卫生间','panda',10,10,10)
print(r.area())
# 使用者的方法没有变,需求只需要变自己类的方法里的函数属性就可以了
【22.property的使用】
【23.绑定方法与非绑定方法介绍】
【24.绑定方法与非绑定方法】
【25.反射】
【26.内置方法介绍】
【27.元类介绍】
【28.自定义元类控制类的创建】
【29.自定义元类控制类的实例化行为】
【30.自定义元类控制类的实例化行为的应用】
【31.面向对象的软件开发与作业介绍】
【32.什么是异常处理】
【32.try...except...详细方法】
- 路飞学城—Python爬虫实战密训班 第三章
路飞学城—Python爬虫实战密训班 第三章 一.scrapy-redis插件实现简单分布式爬虫 scrapy-redis插件用于将scrapy和redis结合实现简单分布式爬虫: - 定义调度器 - ...
- 路飞学城—Python爬虫实战密训班 第二章
路飞学城—Python爬虫实战密训班 第二章 一.Selenium基础 Selenium是一个第三方模块,可以完全模拟用户在浏览器上操作(相当于在浏览器上点点点). 1.安装 - pip instal ...
- 路飞学城Python爬虫课第一章笔记
前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 之前看阮一峰的博客文章,介绍到路飞学城爬虫课程限免,看了眼内容还不错,就兴冲冲报了名,99块钱满足以下条件会返还并送书送视频. 缴 ...
- 路飞学城-Python开发集训-第3章
学习心得: 通过这一章的作业,使我对正则表达式的使用直接提升了一个level,虽然作业完成的不怎么样,重复代码有点多,但是收获还是非常大的,有点找到写代码的感觉了,遗憾的是,这次作业交过,这次集训就结 ...
- 路飞学城-Python开发集训-第1章
学习体会: 在参加这次集训之前我自己学过一段时间的Python,看过老男孩的免费视频,自我感觉还行,老师写的代码基本上都能看懂,但是实际呢?....今天是集训第一次交作业的时间,突然发现看似简单升级需 ...
- 路飞学城-Python开发集训-第4章
学习心得: 学习笔记: 在python中一个py文件就是一个模块 模块好处: 1.提高可维护性 2.可重用 3.避免函数名和变量名冲突 模块分为三种: 1.内置标准模块(标准库),查看所有自带和第三方 ...
- 路飞学城-Python开发集训-第2章
学习心得: 这章对编码的讲解超级赞,现在对于编码终于有一点认知了,但还没有大彻大悟,还需要更加细心的琢磨一下Alex博客和视频,以前真的是被编码折磨死了,因为编码的问题而浪费的时间很多很多,现在终于感 ...
- 路飞学城-Python开发-第二章
''' 数据结构: menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村':{ '爱奇艺':{}, '汽车之家' ...
- 路飞学城-Python开发-第三章
# 数据结构: # goods = [ # {"name": "电脑", "price": 1999}, # {"name&quo ...
- 路飞学城-Python开发-第一章
# 基础需求: # 让用户输入用户名密码 # 认证成功后显示欢迎信息 # 输错三次后退出程序 username = 'pandaboy' password = ' def Login(username ...
随机推荐
- I'm studying Bootstrap! loading...
最近在学习bootstrap框架. Bootstrap框架是目前前端最受欢迎的框架,出于Twitter公司!搞前端你说你不会Bootstrap都不好意思见人呢. Bootstrap是基于Html Cs ...
- day08 数字,字符串类型内置方法
目录 数字类型内置方法 为什么要有数据类型? 定义方式 方法 储存一个值or多个值? 有序or无序?(有序:有索引, 无序:无索引) 可变or不可变(可变:值变id不变,不可变:值变id也变) 字符串 ...
- node——含有异步函数的函数封装
在写代码时我们会发现有大量的重复代码,为了使代码更加简洁,我们可以将重复的代码封装为一个可以在多个部分时候用的函数. 之前写的新闻代码中,经常出现的操作有对文件的读取,我们可以将它封装为一个函数rea ...
- jq点击按钮打开和关闭弹出层,点击除了当前按钮以外的地方关闭弹出层
1.html <a id="more" onclick="moreFun()">更多</a> <ul id="moreL ...
- Flask-Babel 使用简介(翻译文档)
最近用flask-bable翻译一个项目,在网站上查找到有一个示例文档,地址:http://translations.readthedocs.io/en/latest/flask-babel.html ...
- 挖一挖python中的深浅拷贝问题
前几天在做面试题的时候,遇到一个与Python深浅拷贝的问题,今天总结出来一个方法,能够快速判断在对一个对象复制后,新对象与原来对象是否会互相影响的方法. 先抛出结论,然后我们对结论进行验证~~~ 先 ...
- 2019-02-25 SQL:cast(itemvalue as decimal(19,4))
1.Operand data type nvarchar(max) is invalid for sum operator 要转换格式 2.Conversion failed when convert ...
- js 数组 : 差集、并集、交集、去重
//input:[{name:'liujinyu'},{name:'noah'}] //output:['liujinyu','noah'] Array.prototype.choose = func ...
- android的架构图
1.Applications 该层是Android应用程序层. 每一个应用必须利用android系统设计的应用框架(application framework)开发. 眼下的开发环境是eclipse ...
- XML 解析---dom解析和sax解析
眼下XML解析的方法主要用两种: 1.dom解析:(Document Object Model.即文档对象模型)是W3C组织推荐的解析XML的一种方式. 使用dom解析XML文档,该解析器会先把XML ...