未理解点:

函数的参数

[函数的参数](重要)(https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431752945034eb82ac80a3e64b9bb4929b16eeed1eb9000)

什么叫可变对象和不可变对象

  • 位置参数
  • 默认参数
  • 可变参数
  • 关键字参数
  • 命名关键字参数
    如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
  • 参数组合
    `def f2(a, b, c=0, *, d, **kw):
    print(‘a =’, a, ‘b =’, b, ‘c =’, c, ‘d =’, d, ‘kw =’, kw)
    输入:

args = (1, 2, 3)
kw = {‘d’: 88, ‘x’: ‘#’}
f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {‘x’: ‘#’}`

请问,为啥命名关键字参数d 可以从关键字参数中“提取”出来啊?
定义默认参数要牢记一点:默认参数必须指向不变对象! 这一句话是什么意思,我得操作一下。
为什么要设计str、None这样的不变对象呢?

试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
在变量前加上星号前缀(*),调用时的参数会存储在一个 tuple(元组)对象中,赋值给形参。在函数内部,需要对参数进行处理时,只要对这个 tuple 类型的形参(这里是 args)进行操作就可以了。因此,函数在定义时并不需要指明参数个数,就可以处理任意参数个数的情况。
今天来说说最为灵活的一种参数传递方式:

func(**kargs)

**上次说的 func(*args) 方式是把参数作为 tuple 传入函数内部。而 func(kargs) 则是把参数以键值对字典的形式传入。

示例:
def printAll(**kargs):
for k in kargs:
print k, ‘:’, kargs[k]

printAll(a=1, b=2, c=3)
printAll(x=4, y=5)

输出:
a : 1
c : 3
b : 2
y : 5
x : 4

字典是无序的,所以在输出的时候,并不一定按照提供参数的顺序。同样在调用时,参数的顺序无所谓,只要对应合适的形参名就可以了。于是,采用这种参数传递的方法,可以不受参数数量、位置的限制。

当然,这还不够。Python 的函数调用方式非常灵活,前面所说的几种参数调用方式,可以混合在一起使用。看下面这个例子:

def func(x, y=5, *a, **b):
print x, y, a, b

func(1)
func(1,2)
func(1,2,3)
func(1,2,3,4)
func(x=1)
func(x=1,y=1)
func(x=1,y=1,a=1)
func(x=1,y=1,a=1,b=1)
func(1,y=1)
func(1,2,3,4,a=1)
func(1,2,3,4,k=1,t=2,o=3)

输出:
1 5 () {}
1 2 () {}
1 2 (3,) {}
1 2 (3, 4) {}
1 5 () {}
1 1 () {}
1 1 () {‘a’: 1}
1 1 () {‘a’: 1, ‘b’: 1}
1 1 () {}
1 2 (3, 4) {‘a’: 1}
1 2 (3, 4) {‘k’: 1, ‘t’: 2, ‘o’: 3}

在混合使用时,首先要注意函数的写法,必须遵守:
带有默认值的形参(arg=)须在无默认值的形参(arg)之后;
元组参数(*args)须在带有默认值的形参(arg=)之后;
字典参数(**kargs)须在元组参数(*args)之后。

可以省略某种类型的参数,但仍需保证此顺序规则。

调用时也需要遵守:
指定参数名称的参数要在无指定参数名称的参数之后;
不可以重复传递,即按顺序提供某参数之后,又指定名称传递。

而在函数被调用时,参数的传递过程为:
1.按顺序把无指定参数的实参赋值给形参;
2.把指定参数名称(arg=v)的实参赋值给对应的形参;
3.将多余的无指定参数的实参打包成一个 tuple 传递给元组参数(*args);
4.将多余的指定参数名的实参打包成一个 dict 传递给字典参数(**kargs)。

是不是乍一看有点绕?没关系,赶紧打开你的编辑器,自行体会一下不同调用方式的用法。然后在未来的编程实践中慢慢熟悉吧。

迭代

    1. 字典迭代的三种方式
    1. 如何检查迭代情况
    1. 要对list实现类似Java那样的下标循环怎么办?

列表生成式

    1. 使用的时候注意由简到繁、尽量简化代码

生成器

    1. 改变括号
    1. 循环生成
    1. yield(难点)
    1. 注意区分普通函数和generator函数
    1. 多多训练一下yield生成器,看视频什么的都可以,在后面会大量的使用

迭代器

    1. 迭代器和可迭代对象的区别
    1. 如何转换
    1. 有啥关系

函数式编程

    1. 计算机和计算有啥区别
    1. 什么叫函数式编程
    1. 函数式编程特点以及意义

高阶函数

    1. 变量可以指向函数
    1. 函数名也是变量
    1. 传入函数(重点)
    1. 后面一直在使用,是Python的关键点

map/reduce

阅读:http://research.google.com/archive/mapreduce.html

    1. 了解什么是map/reduce
    1. 完全没看懂!

filter

    1. 将函数作用于每一个参数,根据结果的True还是False保留或放弃
    1. 弄懂埃氏筛法(算法)
    1. 重新复习一下lambda表达式
    1. 注意搞清楚如何筛选,思路很重要(难点)

sorted

    1. 这里一直在阐述高阶函数的内容
    1. 在字母排序中是否注意到了list的可变性?

返回函数

    1. 函数作为返回值
    1. 什么叫“闭包”,如何操作 (难点)

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

匿名函数

    1. 匿名函数的特点

装饰器

    1. 如何拿到函数名
    1. 什么叫“装饰器”?
    1. 什么叫Python的@语法?

偏函数

    1. 什么叫偏函数,为啥要创建偏函数。
    1. 如何创建偏函数?

模块

无重要内容

使用模块

    1. 任何模块代码的第一个字符串都被视为模块的文档注释;
    1. 作用域

安装模块

    1. 为啥使用Anaconda
      https://www.zhihu.com/question/58033789

面向对象编程

    1. 面向对象编程的特点:数据封装、继承和多态是面向对象的三大特点

类和实例

    1. 数据封装(遗忘)

访问限制

__name:表示private变量
_name:傲娇变量:表示“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

继承和多态

    1. 继承
    1. 多态:多态中run_twice功能没有实现(难点)
    1. 多态中的“开闭”原则
    1. 什么叫“鸭子”类型(难点)

获取对象信息

    1. isinstance 和 type :总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。
    1. dir()

获取对象信息

    1. 获取实例属性和类属性的关系

面向对象高级编程

    1. 多重继承、定制类、元类等概念

使用__slots__

    1. 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的,如果想要子类也起作用,就必须要在子类中设置__slots__属性

@property

    1. 使用property的目的
    1. 只定义getter方法,不定义setter方法就是一个只读属性

多重继承

    1. 多重继承实在是太爽啦
    1. 有个问题:在改为MinIn时,后面多重继承的类名也要改成这个吧?

定制类

str
iter
- 1. __iter__是用来干嘛的?
- 2. 后面的完全没有弄懂在讲什么
getattr
call

使用枚举类

    1. Enum:可以把一组相关常量定义在一个class中,且class不可变,而且成员可以直接比较。

使用元类

    1. type():为啥说 因为type就是表示“类”
    1. 通过type()创建类和通过class创建类的区别
    1. metaclass:元类(超类)(难点,多看)
    1. ORM框架