提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 一、函数
- 1.高阶函数
- 2.返回函数
- 3.匿名函数
- 4.装饰器
- 二、实例
- 1.类和实例
- 2.限制访问
- 3. 继承和多态
- 4.实例属性和类属性
一、函数
1.高阶函数
- 1.1 map
- 1.2 reduce
- 1.3 filter
- 1.4 sorted
# 1.1 map()函数:把一个函数作用到一个Iterable的东西上# 参数:1.函数 2.Iterable# 返回值类型:map object# 举例:把平方作用到列表的每个值中def f(x):return x * xr = map(f,[1,2,3,4,5,6,7,8,9])list(r)
>>>[1, 4, 9, 16, 25, 36, 49, 64, 81]
# map()函数实际上就是不是运算规则抽象化了# 把list的每个数字变成strlist(map(str,[1,2,3,4,5,6,7,8,9]))
>>>[‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’]
# 1.2 reduce()函数:把一个函数累计作用到序列的下一个元素中# reduce(f,[x1,x2,x3]) == f(f(x1,x2),x3)# 举例,把[1,2,3]变成123from functools import reducedef fn(x,y):return x*10+yreduce(fn,[1,2,3])
>>> 123
# 1.3 filter函数:接收函数和序列,根据函数作用在序列的每个元素返回的True和False决定是否保留该元素# 返回类型:Iterator# 举例:只保留序列中的奇数def is_odd(n):return n%2==1list(filter(is_odd,[1,3,5,7,2,4,6,8]))
>>>[1, 3, 5, 7]
# 把一个序列中的空字符去掉def not_empty(s):return s.strip()list(filter(not_empty, ['A', '', 'B', 'C', '']))
>>>[‘A’, ‘B’, ‘C’]
# sorted对list进行排序sorted([32,12,-19,55,3])
>>>[-19, 3, 12, 32, 55]
# 参数:key,接收自定义排序函数# 举例:按照绝对值大小排序sorted([32,12,-19,55,3],key=abs)
>>>[3, 12, -19, 32, 55]
# 对于字符 是按照ASCII码进行排序sorted(['sb','Sb','SB'])
>>>[‘SB’, ‘Sb’, ‘sb’]
2.返回函数
- 2.1 函数作为返回值
- 2.2 闭包
# 2.1 高阶函数出了可以接收函数作为参数,还可以把函数作为结果返回# 一个可变参数的求和,如果不需要立刻求和,而是在后面的代码中,根据需要再计算def lazy_sum(*args):def sum():ax = 0for n in args:ax = ax + nreturn axreturn sum# 调用的时候返回的是求和函数f = lazy_sum(1,2,3,4)f>>> <function __main__.lazy_sum.<locals>.sum()># 调用函数f的时候,才是返回真正的求和结果f()
>>>10
# 在函数lazy_sum里面又定义了函数sum,内部函数可以引用外部函数的参数和局部变量# lazy_sum返回了sum的时候,相关的参数和变量都保存在了返回函数中,就是闭包# 每一次调用 返回的都是新的函数 但是传入的是相同的参数f1 = lazy_sum(1,2,3,4)f2 = lazy_sum(1,2,3,4)f1 == f2
>>>False
# 2.2 闭包# 要注意返回的函数没有立刻执行,要再一次的调用才会执行def count():fs = []for i in range(1,4):def f():return i * ifs.append(f)return fscount()f1,f2,f3 = count()print(f1(),f2(),f3())# 因为返回函数引用了i,并且并非立刻执行,3个函数都返回时,所以它引用的变量i已经变成3
>>>9 9 9
# 如果一定要引用循环的变量,就应该再创建一个函数,绑定循环变量def count():def f(j):def g():return j*jreturn gfs = []for i in range(1,4):fs.append(f(i))return fscount()f1,f2,f3 = count()print(f1(),f2(),f3())
>>>1 4 9
3.匿名函数
list(map(lambda x: x*x,[1,2,3]))
>>>[1, 4, 9]
# 相当于def f(x):return x * x
4.装饰器
# 函数也是对象,所以可以赋值给变量,通过变量来调用函数def now():print('2020-01-01')f = nowf()
>>>2020-01-01
# 想要增强now()的功能,在调用的前打印日志,有不改变函数本身的定义,这样动态增加功能的方法叫做装饰器# 本质上是一个返回函数的高阶函数def log(func):def wrapper(*args,**kw):print('call %s:'%func.__name__)return func(*args,**kw)return wrapper# %%@logdef now(x):print('2020-01-01')now(1)# %%
>>>
call now:
2020-01-01
# @log 放在now函数之前 相当于now = log(now)
# decorator也要传入参数,需要编写一个decorator的高阶函数def log(text):def decorator(func):def wrapper(*args,**kw):print('%s %s:'%(text,func.__name__))return func(*args,**kw)return wrapperreturn decorator# %%@log('execute')def now():print('2020-01-01')# %%now()
>>>
execute now:
2020-01-01
# 相当于now = log('execute')(now)# 先执行了log('execute'),返回了decorator函数,再调用返回函数,参数是now,返回的是wrapper# 也就是原来的now函数变成了现在的wrapper函数了now.__name__
>>>‘wrapper’
# 想要保持now的name的话 wrapper.__name__ = func.__name__# 可以用装饰器 @functools.wraps(func)import functoolsdef log(func):@functools.wraps(func)def wrapper(*args,**kw):print('call %s():' % func.__name__)return func(*args,**kw)return wrapper# %%@logdef now():print('2020-01-01')# %%now.__name__
>>>‘now’
二、实例
1.类和实例
- 1.1 基本定义
- 1.2 创建实例
- 1.3 绑定属性
- 1.4 _init_
- 1.5 数据封装
# 1.1 基本定义#class + 类名 + (object) 即从哪个类继承下来的class student(object):pass
# 1.2 创建实例# 类名+()bart = student()# 变量bart指向student类的实例,0x1064b1128是内存地址bartstudent
>>>
<main.student at 0x1064b1128>
main.student
# 1.3 绑定属性# 可以自由的给实例变量绑定属性bart.name = 'sb'bart.name
>>>‘sb’
# 1.4 __init__# 类就像是模版 当我们想创建实例的时候就把一些属性写进去 可以用__initclass student(object):# self 就是实例本身def __init__(self,name,score):self.name = nameself.score = scorebart = student('sb',0)bart.namebart.score
>>> ‘sb’ 0
# 1.5 数据封装# 比如一个函数本来就要用到学生类里面的数据,那当然就把函数放在类里面多好嘛class student(object):def __init__(self,name,score):self.name = nameself.score = scoredef print_score(self):print('%s:%s'%(self.name,self.score))bart = student('sb',0)bart.print_score()
>>>sb:0
2.限制访问
# 按照上述的定义,外部代码还可以自由修改实例的属性bart.scorebart.score = 100bart.score
>>>
0
100
# 我们更希望这些属性是私有的,不能被外部代码修改的class student(object):def __init__(self,name,score):self.__name = nameself.__score = scoredef print_score(self):print('%s: %s' % (self.__name, self.__score))bart = student('sb',0)bart.__name>>>---------------------------------------------------------------------------AttributeErrorTraceback (most recent call last)<ipython-input-24-1e120ece361e> in <module>----> 1 bart.__nameAttributeError: 'student' object has no attribute '__name'
# 这么做又有一个问题,虽然外部代码不能修改实例的属性了。但是我们还是希望外部代码可以获得他的值class student(object):def __init__(self,name,score):self.__name = nameself.__score = score# 让外部可以获得属性的值def get_name(self):return self.__namedef get_score(self):return self.__score# 让外部可以改变属性的值def set_name(self,name):self.__name = name# 可以通过这样改变属性的方法来做参数检查,避免传入无效参数def set_score(self,score):if 0 <= score < 100:self.__score = scoreelse:raise ValueError('bad score')bart = student('sb',0)bart.get_name()bart.set_name('SB')bart.get_name()
>>>
‘sb’
‘SB’
bart.set_score(50)bart.get_score()>>>50bart.set_score(250)>>>---------------------------------------------------------------------------ValueErrorTraceback (most recent call last)<ipython-input-40-6cf87971f6eb> in <module>----> 1 bart.set_score(250)<ipython-input-31-e38b3fe7e472> in set_score(self, score) 20 self.__score = score 21 else:---> 22 raise ValueError('bad score')ValueError: bad score
3. 继承和多态
- 3.1 继承
- 3.2 子类的特性
- 3.3 理解多态
# 现在我们已经有一个动物class,一个run()方法打印class Animal(object):def run(self):print("Animal is running...")
# 3.1 继承# 当我们需要具体的动物类时,可以从Animal继承class cat(Animal):passclass Dog(Animal):pass
# 继承最大的好处就是子类有了父类的全部功能dog = Dog()dog.run()
>>>Animal is running…
# 3.2 子类的特性# 子类可以增加新的方法也可以对父类的方法进行改进class Dog(Animal):# 改进父类方法def run(self):print('Dog is running...')# 新的方法def eat(self):print('Dog is eating...')dog = Dog()dog.run()dog.eat()
>>>
Dog is running…
Dog is eating…
# 3.3 理解多态# 定义一个class,实际上就是定义了一种数据类型a = list() # a是list类型b = Animal() # b是Animal类型c = Dog() # c是Dog类型
# c既是Dog也是Animal# 就是说Dog可以看成是一个Animalisinstance(c,Animal)isinstance(c,Dog)
>>>
True
True
# 理解多态的好处class Animal(object):def run(self):print("Animal is running...")def eat(self):print('Anumal is eating...')class Dog(Animal):def run(self):print('Dog is running...')def eat(self):print('Dog is eating...')def run_eat(a):a.run()a.eat()run_eat(Animal())
>>>
Animal is running…
Anumal is eating…
run_eat(Dog())# 多态的好处:传入的只要是Animal或者他的子类,就会自动调用实际类型的run()# 调用的时候只管调用,新加一个子类的时候只要保证他继承的方法没写错# 开闭原则:# 对扩展开放:允许增加子类# 对修改封闭:不需要修改类的run_eat()函数
>>>
Dog is running…
Dog is eating…
- 静态语言:利用多态特性的时候,传入的对象必须严格的是Animal类或者他的子类
- 动态语言:不要求严格的继承体系
- 鸭子类型:一个对象只要看起来像鸭子,走路也像鸭子,就能被看作是鸭子
- python:“file-like object”就是一种鸭子类型,某个对象有当前的这个函数方法,就可以当作是这个函数的对象了。
4.实例属性和类属性
# 给实例绑定属性# 1.通过实例变量 2.通过self变量class student(object):def __init__(self,name):self.name = names = student('sb')s.score = 0
# 直接给类绑定一个类属性class student(object):name = 'student'# 创建实例s = student()# 这个时候实例没有name,所以会向上找类的names.name
>>>‘student’
# 打印类的属性print(student.name)>>>student# 给实例绑定属性s.name = 'sb'print(s.name)>>>sbprint(student.name)>>>student