接下里该进入第六章的学习了
一、多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)
例如:
序列有多种形态:字符串,列表,元祖
动物有多种形态:人,猪,狗
多态和多态性的区别:
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
多态性:一种调用方式,不同的执行效果(多态性)
面向对象的三大特征:封装,继承,多态
封装:又称为信息的隐藏,类的实现和使用时分开的,类提供了外部访问的方法,调用者不需要关注类里面的具体实现,会调用即可
继承:一个类继承另外一个类,被继承的类称为父类或者基类,继承的类称为子类或者派生类,子类可以共享父类里面受保护,公有属性和方法,子类不能共享父类私有属性和方法,继承可以减少代码的书写,提高代码的可维护性
多态:同一种事物有多种形态;多态性:同一种调用方式,返回不同的结果;多态的前提:继承和重写
下面我们通过具体例子来理解一下什么是多态,什么是多态性
1.多态:一种事物有多种表现形式
#定义一个父类
class Animal(object):
#定义一个普通方法
def sayHello(self):
pass
#定义一个子类Person,继承父类Animal
class Person(Animal):
#重写父类同名的方法
def sayHello(self):
print('hello,i am Person')
#定义一个子类Pig,继承父类Animal
class Pig(Animal):
#重写父类同名的方法
def sayHello(self):
print('aoao,i am Pig')
#定义一个子类Dog,继承父类Animal
class Dog(Animal):
#重写父类同名的方法
def sayHello(self):
print('wangwang,i am Dog')
#实例化不同子类创建对象
Per = Person()
Pi = Pig()
Do = Dog()
Per.sayHello()
Pi.sayHello()
Do.sayHello()
这就是多态,一种事物(sayhello)在不同形势下有不同的表现形势
2.多态性:同一种调用方式,返回不同的结果
def func(o): #python是动态语言,o是多态性的体现,这里不需要指定类型,参数的类型由调用者传的值决定
o.sayHello()
func(Per)
func(Pi)
func(Do)
# 二、属性
1.类属性
在类中定义的属性(公有和私有)
定义一个人类,设置姓名和年龄属性
class Person(object):
name = 'xiaoming' #公有类属性
__age = 12 #私有类属性
#创建Person类的对象p
p = Person()
print(p.name) #实例对象访问类的公有属性
print(Person.name) #类对象访问类的公有属性
print(p.__age) #实例对象访问类的私有属性 not ok
print(Person.__age) ##类对象访问类的私有属性 not ok
实例属性
就是通过__init__定义的那些啦
class Person(object):
address = '上海市' #类属性
#定义初始化方法
def __init__(self,name,age):
self.name = name #实例属性
self.age = age
#创建Person类的对象pe
pe = Person('张三',30)
print(pe.address) #通过实例对象访问类属性
print(pe.name) #通过实例对象访问实例属性
print(pe.age)
print(Person.address)#类在定义的时候已经产生了,类属性直接属于类
print(Person.name) #当实例化类创建对象,对属性赋值 实例属性才会产生内存里面 类访问不到实例属性
print(Person.age)
注意一点,类里面定义同名的实例属性和类属性,实例对象修改类属性,实例属性会屏蔽同名类属性,实例属性优先级高于类属性。简而言之就是说他要有一个类属性address,但你实例属性中又跟他重复了,会取实例属性
三、静态方法和类方法
1.类方法
###类对象所拥有的方法,需要使用到修饰器 @classmethod---->类方法。对于类方法,第一个参数必须是类对象,一般以cls表示作为第一个参数(当然可以用其他的名字,但是不建议修改)
#定义一个人类
class Person(object):
country = 'china' #类属性
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
#创建Person对象
p = Person()
print(p.getCountry()) #通过实例对象访问类方法
print(Person.getCountry()) #通过类对象访问类方法
p.setCountry('chinese') #这样就直接把整个类的属性给改啦
print(p.getCountry()) #chinese
print(Person.getCountry()) #chinese
总结:类方法可以修改类属性
2.静态方法
需要通过修饰器@staticmethod来进行修饰,不需要传参数
#定义一个人类
class Person(object):
country = ‘china’ #类属性
@staticmethod
def getCountry():
return Person.country
#创建Person类的对象
p = Person()
print(p.getCountry()) #通过实例对象访问静态方法
就是说是直接通过类去访问属性的
四、slots
如果我们想要限制实例属性怎么办呢
就是说这个类中只能有name和age两种属性,其他的我们都不要
python允许定义class的时候,定义一个特殊的变量---->slots,限制class能够添加的属性
语法格式:__slots__ = ('属性1','属性2')
#定义一个人类,只允许添加姓名和年龄属性
class Student(object):
__slots__ = ('name','sex') #限制当前类添加的属性
#通过Student类创建对象stu
stu = Student()
#往对象里面添加属性
stu.name = '张三'
stu.sex = '男'
print(stu.name)
print(stu.sex)
#增加一个新的属性
# stu.weight = '80kg' #报错,类中限制添加属性没有weight
# print(stu.weight)
Student.weight = '50kg' #这样直接往类里面添加属性是可以的,但就是对象自己不能添加
print(stu.weight)
#定义一个子类demo,继承Student
class Demo(Student):
pass
d = Demo()
d.height = '180'
print(d.height)
注意:__slots__属性限制添加属性只对当前类的实例对象起作用,对类属性,继承的子类实例对象不起作用的
来讲几个好玩的例子
1.发邮件
import smtplib
#导入邮箱文本
from email.mime.text import MIMEText
#设置邮箱服务器 qq/126/163/gmail/yahoo/阿里云
SMTPServer = 'smtp.163.com'
#设置发送邮箱的地址
sender = 'yaodaolian1@163.com'
#设置发送邮箱的密码
password = 'y123456'
#设置发送的内容
message = '你是一个好人...'
#转换成人能够看懂的格式
msg = MIMEText(message)
#设置发送邮件的主题
msg['subject'] = '来自一位帅哥的表白'
#发送者
msg['from'] = sender
#设置邮箱服务器
emailServer = smtplib.SMTP(SMTPServer,25)
#登录邮箱
emailServer.login(sender,password)
#发送邮件的内容
emailServer.sendmail(sender,['yaodaolian1@163.com'],msg.as_string()) #前面是发送者,后面是收件者
#关闭邮箱
emailServer.quit()
五、递归
定义:
在函数中不调用其他函数,而是调用自己------》递归函数
凡是循环能做的事,递归都能做
例如:计算n的阶乘
#1.使用循环求n的阶乘
def calNum(num):
result = 1
for i in range(1,num+1):
result *= i
return result
print(calNum(5))
#2.使用递归实现
def calNum(num):
if num > 1:
result = num * calNum(num-1) #自己调用自己
else:
result = 1
return result
print(calNum(5))
递归的作用:提高我们代码运行效率,简化代码
递归的使用场景:商品的分类,遍历文件目录下所有的文件
2.递归遍历目录
import os
def getAllFileDir(path,): #path文件路径
#获取当前目录下所有的文件
filelist = os.listdir(path) #filelist是一个列表
#处理每个文件,在文件之间加分隔符
sp = '-' #这个分隔符自己随便定义把
#遍历获取所有的文件,如果是目录使用递归继续遍历,如果是文本文件直接打印
for fileName in filelist: #fileName 就是遍历当前目录下的所有文件
#判断是否是路径(用绝对路径)
fileAbsPath = os.path.join(path,fileName) #文件的绝对路径
#判断是否是目录
if os.path.isdir(fileAbsPath):
print(sp+'目录:',fileName)
#使用递归函数
getAllFileDir(fileAbsPath) #是目录就递归接着找目录中的文件
else:
print(sp+'文本文件:',fileName)
#调用函数
getAllFileDir('F:\hellopython')
栈模拟递归遍历目录
原理:先进后出
装子弹
“”"
#使用模拟堆栈
#入栈
# stack = []
# stack.append(‘A’)
# stack.append(‘B’)
# stack.append(‘C’)
# print(stack)
#
# #出栈
# stack.pop()
# print(stack)
import os
def getAllFileDir(path):
stack = []
#入栈
stack.append(path)
#处理栈,当栈为空的时候结束操作
while len(stack) != 0:
#出栈
outDir = stack.pop()
#获取当前目录所有文件
filelist = os.listdir(outDir)
#判断哪些是目录,继续入栈,如果是文件直接打印
for fileName in filelist:
#判断文件是否是路径(用绝对路径)
fileAbsPath = os.path.join(outDir,fileName)
if os.path.isdir(fileAbsPath):
print(‘目录:’,fileName)
#入栈
stack.append(fileAbsPath)
else:
print(‘文本文件:’,fileName)
#调用函数
getAllFileDir(‘F:\hellopython’)
队列模拟遍历目录
队列原理:先进先出
collections
deque() 创建一个队列
append() 队列添加元素
popLeft() 从队列里面删除元素
len() 获取长度
listdir()获取当前目录下所有的文件
isdir()判断是否是目录
import collections
import os
def getAllFileDir(path):
#创建一个队列
queue = collections.deque()
#入队
queue.append(path)
#处理队列,如果队列为空结束操作
while len(queue) != 0:
#出队
outDir = queue.popleft()
#获取当前目录下所有的文件
filelist = os.listdir(outDir)
#判断哪些是目录,入队,如果是文件直接打印
for fileName in filelist:
#判断是否是路径(用绝对路径)
fileAbsPath = os.path.join(outDir,fileName)
if os.path.isdir(fileAbsPath):
print('目录:',fileName)
#入队
queue.append(fileAbsPath)
else:
print('文本文件:',fileName)
#调用函数
getAllFileDir('F:\hellopython')
六、高阶函数
1.map
map(function,iterable)
function—》函数,两个参数—》返回值是一个新的列表
iterable—》一个或者多个序列
python2:返回列表,python3:返回的是迭代器
案例1:计算列表各个元素的平方
li = [1,2,3,4]
#定义一个求平方的函数
def square(n):
return n ** 2
res = map(square,li) #将li列表里面每个元素先作为square函数参数,获取每个元素平方,再执行map函数
print(res) #迭代器
print(list(res)) 一个列表
print(tuple(res)) #()
案例2:将整数元素的序列,转换为字符串类型
res3 = map(str,[1,2,3,4])
print(tuple(res3))
2.reduce
函数将一个数据集合(列表,元组)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
格式:
reduce(function,iterable,[initializer])
function:函数,有两个参数
iterable:可迭代的对象
initializer:可选,初始化参数
案例1:两个数的求和
from functools import reduce
def add(a,b):
return a + b
res = reduce(add,range(1,5))
res = reduce(add,[1,2,3,4])
res = reduce(add,(1,2,3,4))
print(res) #10
总结:一个函数作用于一个序列,需要传递两个参数,reduce返回结果再和下个数进行运算
3.filter
用于过滤序列,过滤掉不符合条件的元素,返回由符合条件的元素组成的新列表
格式:
filter(function,iterable)
function:函数 判断函数
iterable:序列,序列的每一个元素作为参数传递到函数进行判断,返回True,False,最后将返回True的元素存放到一个新的列表中
#案例1:筛选指定的元素
list01 = [1,2,3,4,5,6,7,8,9,10]
#定义一个函数
def even(num):
if num % 2 == 0:
return True
return False
res = filter(even,list01)
print(list(res))
4.sorted
正常的排序我们就不一一赘述了
他可以通过key接受一个内置函数进行排序
lst = [2,0,-99,-20,100,111]
res2 = sorted(lst2,key=abs)
print(res2)