面向对象函数高阶

接下里该进入第六章的学习了

一、多态

多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)

例如:

序列有多种形态:字符串,列表,元祖
动物有多种形态:人,猪,狗

多态和多态性的区别:
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
多态性:一种调用方式,不同的执行效果(多态性)

面向对象的三大特征:封装,继承,多态

封装:又称为信息的隐藏,类的实现和使用时分开的,类提供了外部访问的方法,调用者不需要关注类里面的具体实现,会调用即可
继承:一个类继承另外一个类,被继承的类称为父类或者基类,继承的类称为子类或者派生类,子类可以共享父类里面受保护,公有属性和方法,子类不能共享父类私有属性和方法,继承可以减少代码的书写,提高代码的可维护性
多态:同一种事物有多种形态;多态性:同一种调用方式,返回不同的结果;多态的前提:继承和重写

下面我们通过具体例子来理解一下什么是多态,什么是多态性

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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值