Python基础-面向对象和函数式
这篇文章是对廖雪峰老师的python 3教程中python面向对象和函数相关章节的笔记。廖雪峰老师的python基础教程不仅细致的讲解了python的语法、还点出了语法中的注意点、python常用的模块、python的面向对象和函数式编程以及一些周边。对廖雪峰老师的python基础教程分为四部分。一、语法;二、面向对象和函数式;三、语言机制关系密切的模块;四、常用模块。
面向对象
类和实例
python类的定义,使用了__init__
函数就不能使用默认的构造函数了,构造函数的多态可以使用默认值的方式来模拟。
1 | #类定义 |
让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问(语言机制实现的:通过将变量重命名为_ClassName__name
)
获取对象类型
使用type和isinstance获取类型
1 | #type()返回对象对应的类型 |
- 获取所有属性和方法
- 在len()函数内部,它自动去调用该对象的
__len__
()方法,所以
1 | dir('ABC') |
- 使用getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态
1 | hasattr(obj, 'y') # 有属性'y'吗? |
面向对象高级编程
使用__slots__
- Python允许在定义class的时候,定义一个特殊的
__slots__
变量,来限制该class实例能添加的属性
1 | class Student(object): |
使用@property
- Python内置的@property装饰器就是负责把一个方法变成属性调用的
1 | class Student(object): |
多重继承
- 需要”混入”(MixIn)额外的功能,通过多重继承就可以实现
1 | #多重继承实现的混入 |
定制类
- 看到类似
__slots__
这种形如__xxx__
的变量或者函数名就要注意,这些在Python中是有特殊用途的。 __len__()
方法我们也知道是为了能让class作用于len()函数。__str__()
返回用户看到的字符串,使用print()打印时调用的函数__repr__()
返回开发者看到的字符串,使用直接在打印对象时显示
1 | class Student(object): |
__iter__()
方法,使该类可以被用于for…in循环__next__()
方法,Python的for循环就会不断调用该迭代对象的__next__()
方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
1 | class Fib(object): |
__getitem__()
方法,表现得像list那样按照下标取出元素(如果把对象看成dict,__getitem__()
的参数也可能是一个可以作key的object,例如str);与之对应的还有__setitem__()
方法,用于像list那样设置某个元素,__delitem__()
方法,用于删除某个元素
1 | class Fib(object): |
__getattr__()
方法,用于动态返回一个不存在的属性(只有没有的属性才会调用)
1 | class Student(object): |
__call__()
在实例本身调用方法(把实例当作一个方法)
1 | class Student(object): |
使用枚举类
- 枚举常量
1 | from enum import Enum |
- 派生枚举类
1 | from enum import Enum, unique |
使用元类
- 类的类型是type
- class的定义是运行时动态创建的,而创建class的方法就是使用type()函数
- 使用type创建类型
1 | def fn(self,name = 'world'): |
- 通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。
使用metaclass创建类
1 | # metaclass是类的模板,所以必须从`type`类型派生: |
函数式编程
高阶函数
高阶函数,接收另一个函数作为参数的函数或返回一个函数的函数。
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
1 | #list()将Iterator变为list |
reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
1 | def fn(x,y): |
应用,字符串转化为数字函数
1 | from functools import reduce |
- filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,返回的也是一个Iterator
1 | #判断是否回文数,如:989,121这样 |
sorted()默认从小到大排序,它还可以接收一个key函数来实现自定义的排序,第三个参数可以反转排序
1 | sorted(['bob', 'about', 'Zoo', 'Credit'],cmp=None, key=str.lower, reverse=True) |
闭包
与js相似的闭包概念
1 | #不使用f嵌套g,最后的结果都是9 |
匿名函数
使用lambda表达式(函数体只能有一个表达式,返回值就是该表达式的结果)
1 | list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) |
装饰器
函数对象有一个__name__
属性可以拿到函数的名字
python的@语法,类似于面向切面编程
1 | import functools |
- 可选参数的装饰器
1 | # -*-coding:utf-8-*- |
偏函数
偏函数,把一个函数的某些参数给固定住,使得函数的使用更加简单
1 | def int2(x,base = 2): |