从大的角度说,开发大的方面肯定是以面向对象思想为指导。但是在局部位置肯定会用到函数式编程。
看了函数式编程以后,很长一阵时间的愣神。。。定义那么多,感觉就是C++函数指针啊,没有区别,就是函数指针,然后在局部体现一些"封装"、“继承”、“多态”。下面通过一小段代码体现:
如给一个列表,假如让用生成器思想筛选一下:
list01 = [1,32,45,8,99,4,7,56]
# 需求:
# 1.找出列表中大于10的数字
# 2.找出列表中的所有偶数
# 3.找出列表中10~50之间的数字
# 4.上面需求中需要用到函数式编程以及面向对象三大特征
def find01(list_taeger):
for item in list_taeger:
#条件:大于10
if(item > 10):
yield item
def find02(list_taeger):
for item in list_taeger:
#条件:偶数
if(item % 2 == 0):
yield item
def find03(list_taeger):
for item in list_taeger:
# 条件:10~50之间
if (item > 10 and item < 50):
yield item
for item in find01(list01):
print(item)
print("******************")
for item in find02(list01):
print(item)
print("******************")
for item in find03(list01):
print(item)
输出结果:
32
45
99
56
******************
32
8
4
56
******************
32
45
上面的代码使用了生成器的思想也实现了筛选的要求,但是没有符合面向对象思想,下面再对代码进行重构,按照面向对象设计的思想进行重构.。首先是封装,那么要找变化点,上面find01、find02、find03之间唯一的区别就是条件,三者判断的条件不同。
那么把条件判断的地方单独写一个方法,当初参数传入find方法,如下:
def find(list_taeger,condition):
for item in list_taeger:
#条件
if condition(item):
yield item
继承和多态,就在上面一个方法中能体现了。因为上面的条件方法是按照指针传入的,那么真正调用的时候传入的是自己写的那个方法,而且是和find中调用的方法一样的参数(list的元素)、一样的返回值(返回布尔值),从思想上是一种变相的"继承"。而又恰恰因为这个实际传入的方法,数量不知道、真正的判断逻辑也不知道,多种多样千变万化,但是find调用始终不变,从思想上来说又是一种变相的"多态"。
完整的代码如下:
"""
函数式编程
"""
list01 = [1,32,45,8,99,4,7,56]
# 需求:
# 1.找出列表中大于10的数字
# 2.找出列表中的所有偶数
# 3.找出列表中10~50之间的数字
# 4.上面需求中需要用到函数式编程以及面向对象三大特征
def find(list_taeger,condition):
for item in list_taeger:
#条件
if condition(item):
yield item
def condition01(item):
if item >10:
return True
def condition02(item):
if item % 2 == 0:
return True
def condition03(item):
if item >10 and item < 50:
return True
for item in find(list01,condition01):
print(item)
print("**************************")
for item in find(list01,condition02):
print(item)
print("**************************")
for item in find(list01,condition03):
print(item)
输出结果:
32
45
99
56
**************************
32
8
4
56
**************************
32
45
上面举了一个简单的例子,下面把我前面写着玩的乘风破浪的姐姐类进行这种写法的筛选:
"""
类:乘风破浪的姐姐
属性:姓名、年龄、身高、胸围
行为:唱歌、跳舞
"""
class SuperBigSister:
"""
实例化成员:具体的姐姐、必须有名字、年龄、身高、胸围属性
"""
#类变量复活卡
resurgenceCard = 2
def __init__(self,name,age,height,bustline):
self.name = name
self.__age = age
self.__height = height
self.__bustline = bustline
def setAge(self,age):
if(age == 18):
self.__age = age
else:
print("要改我年龄只能改18,不然不许改,哼!")
def getAge(self):
return self.__age
age = property(getAge,setAge)
def setscore(self,value):
if (value < 100 and value > 0):
self.__score = value
else:
raise ValueError("分数应在0-100")
def getscore(self):
return self.__score
score = property(getscore,setscore)
@property
def height(self):
return self.__height
@height.setter
def height(self,value):
self.__height =value
@property
def bustline(self):
return "这么想知道的话也可以告诉你是%s杯"%self.__bustline
def __str__(self):
return "%s的年龄是%d,身高是%d,分数是%d"%(self.name,self.age,self.height,self.score)
class SuperBigSisterManage:
def __init__(self):
self.__sisters = []
def addSister(self,sister):
self.__sisters.append(sister)
def findsister(self,condition):
for sister in self.__sisters:
if condition(sister):
yield sister
def condition_age(sister):
if(sister.age >30):
return True
def condition_score(sister):
if(sister.score >80):
return True
def condition_height(sister):
if(sister.height >160):
return True
sister_huangshengyi = SuperBigSister("黄圣依",38,159,"C")
sister_huangshengyi.score = 81
sister_ningjing = SuperBigSister("宁静",48,165,"B")
sister_ningjing.score = 92
sister_zhangyuqi = SuperBigSister("张雨绮",34,160,"B")
sister_zhangyuqi.score = 75
manage = SuperBigSisterManage()
manage.addSister(sister_huangshengyi)
manage.addSister(sister_ningjing)
manage.addSister(sister_zhangyuqi)
print("*****找出大于30的姐姐*****")
for sister in manage.findsister(condition_age):
print(sister)
print("*****找出大90分以上的姐姐*****")
for sister in manage.findsister(condition_score):
print(sister)
print("*****找出160cm以上的姐姐*****")
for sister in manage.findsister(condition_height):
print(sister)
在这里声明下,不要迷惑为什么在前面封装属性的时候已经可以对数据进行条件限制,为什么多此一举再写一个函数式编程的来筛选呢?一开始给他把这个条件加上就行了呀。
所以一定区分意义,封装的时候讲的是数据的合理性,是在构造数据的前考虑的问题。而后筛选的应该是在构造数据之后,再考虑在原有数据源基础上根据特殊需求进行的筛选。不然如果那么说,Mysql数据库为什么不把条件判断全部加进底层实现的时候?这么写不省事了吗?这压根不在一个层面上,不现实也不可行。
对上面的代码再次优化,不要定义的condition_age、condition_score、condition_height方法了,使用lambda表达式。
lambda表达式可以使程序①参数传递时简单优雅、②可读性高、③减少程序耦合度、④随意创建和销毁。
格式为:lambda 形参:条件,自己默认自带返回值。
print("*****找出大于30的姐姐*****")
for sister in manage.findsister(lambda item:item.age >30):
print(sister)
print("*****找出大90分以上的姐姐*****")
for sister in manage.findsister(lambda item:item.score >90):
print(sister)
print("*****找出160cm以上的姐姐*****")
for sister in manage.findsister(lambda item:item.height >30):
print(sister)
这么调用,可以把上面原来做为条件的三个语句删除,完成了用lambda表达式进行的判断。