Python3 学习笔记
macOS Python 环境配置
强烈建议使用
Anaconda
(https://www.anaconda.com/),Windows、Linux、Mac都有相应版本,而且安装包管理起来比较方便;不过 Anaconda 更新起来比较慢,建议换成国内镜像源;
安装完 Anaconda 后,如果终端窗口 conda 命令不能运行,可以先配置 .zshrc 文件;
打开终端,输入: vi ~/.zshrc 之后回车,然后按字母 i 进入插入编辑模式,输入下列代码: export PATH=/opt/anaconda3/bin
:$PATH ,其中红色字体要替换成你自己电脑上的conda所在目录,按 ESC 键,输入: :wq 三个字符,文件被保存后退出。终端再输入:source ~/.zshrc ,使其立即生效,这时就可以用: conda --version ,查看 conda 的版本信息。安装 OpenCV
打开终端,输入: sudo pip3 install opencv-python ,按提示输入密码,之后就是漫长的安装过程。
切换成国内镜像源会非常快:
sudo pip3 install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
直接运行 py 文件
.py
文件在Windows上是不能像exe文件直接执行的。但是,在Mac和Linux上是可以的,方法是在.py
文件的第一行加上一个特殊的注释:#!/usr/bin/env python3 print('hello, world')
然后,通过命令给
hello.py
以执行权限:$ chmod a+x hello.py
,就可以直接运行hello.py
了,执行:Air:~ sirit$ ./hello.py
print() 输出字符串
print()函数可接受多个字符串,用逗号“,”隔开,就可以连成一串输出,print()会依次打印每个字符串,遇到逗号“,”会输出一个空格
。
name = input('please enter your name: ')
print('hello,', name)
Python 基础
Python的语法采用缩进方式,应该始终坚持使用
4个空格
的缩进。Python程序是大小写敏感
的。
以#
开头的语句是注释。
Python3 的六个标准数据类型中:
- 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
- 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
字符串是以单引号'
或双引号"
括起来的任意文本。
转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
。Python用r''
表示''
内部的字符串默认不转义。
在Python中,可以直接用True、False表示布尔值(请注意大小写)。
空值是Python里一个特殊的值,用None表示。
变量本身类型不固定的语言称之为动态语言
,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。
在Python中,通常用全部大写的变量名表示常量。
Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647。Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大)。
list [ ] 是一种有序的集合,可以随时添加和删除其中的元素。
另一种有序列表叫元组:tuple ( )。tuple ( ) 和 list [ ]非常类似,但是 tuple 一旦初始化就不能修改。
条件判断
条件判断从上向下匹配,当满足条件时执行对应的块内语句,后续的elif和else都不再执行。
使用dict和set
请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
- 查找和插入的速度极快,不会随着key的增加而变慢;
- 需要占用大量的内存,内存浪费多。
而list相反:
- 查找和插入的时间随着元素的增加而增加;
- 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key。
set可以看成数学意义上的无序和无重复元素的集合,set和dict的唯一区别仅在于没有存储对应的value。
函数
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。
在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
空函数:如果想定义一个什么事也不做的空函数,可以用pass语句。
定义函数时,需要确定函数名和参数个数;如果有必要,可以先对参数的数据类型做检查;函数体内部可以用return随时返回函数结果;函数执行完毕也没有return语句时,自动return None。函数可以同时返回多个值,但其实就是一个tuple。
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
李笑来《the-craft-of-selfteaching》(Part.2.D.2-aargs.ipynb)面对许多参数,Python 需要按照既定的规则(即,顺序)判定每个参数究竟是哪一类型的参数:Order of Arguments
1.Positional
2.Arbitrary Positional
3.Keyword
4.Arbitrary KeywordPython的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
要注意定义可变参数和关键字参数的语法:
- *args是可变参数,args接收的是一个tuple;
- **kw是关键字参数,kw接收的是一个dict。
以及调用函数时如何传入可变参数和关键字参数的语法:
- 可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过args传入:func((1, 2, 3));
- 关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过kw传入:func({'a': 1, 'b': 2})。
使用 *args 和 **kw 是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符' *,',否则定义的将是位置参数。
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。针对尾递归优化的语言可以通过尾递归防止栈溢出。
高级特性
切片
默认情况下,dict迭代的是key。 >>> isinstance('abc', Iterable) # str是否可迭代
Python内置的 enumerate 函数可以把一个list变成索引-元素对。
在一个列表生成式中,for 前面的 if ... else 是表达式,而 for 后面的 if 是过滤条件,不能带 else。
要创建一个 generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [] 改成 (),就创建了一个 generator。如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator。
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的。
函数式编程
函数本身也可以赋值给变量,即:变量可以指向函数。把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。map()
函数接收两个参数,一个是函数,一个是 Iterable, map 将传入的函数依次作用到序列的每个元素,并把结果作为新的 Iterator 返回。
reduce 把一个函数作用在一个序列 [x1, x2, x3, ...] 上,这个函数必须接收两个参数,reduce 把结果继续和序列的下一个元素做累积计算。
Python内建的 filter() 函数用于过滤序列。filter() 也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是 True 还是 False 决定保留还是丢弃该元素。
Python内置的 sorted() 函数就可以对 list 进行排序。它还可以接收一个 key 函数来实现自定义的排序,要进行反向排序,不必改动key函数,可以传入第三个参数 reverse=True。
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值
返回。返回闭包
时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
关键字 lambda 表示匿名函数,冒号前面的 x 表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写 return ,返回值就是该表达式的结果。
在代码运行期间动态增加功能的方式,称之为“装饰器
”(Decorator)
简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
模块
在 Python 中,一个.py文件就称之为一个模块(Module)。使用模块可以避免函数名和变量名冲突。
为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。
类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用。
在Python中,安装第三方模块,是通过包管理工具pip完成的。
面向对象编程
注:本文为在 廖雪峰的官方网站 学习Python3的学习笔记。