python基础回顾
1.第二个缺点就是代码不能加密。如果要发布你的Python程序,实际上就是发布源代码,这一点跟C语言不同,C语言不用发布源代码,只需要把编译后的机器码(也就是你在Windows
上常见的xxx.exe文件)发布出去。要从机器码反推出C代码是不可能的,所以,凡是编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去。
这个缺点仅限于你要编写的软件需要卖给别人挣钱的时候。好消息是目前的互联网时代,靠卖软件授权的商业模式越来越少了,靠网站和移动应用卖服务的模式越来越多了,后一种
模式不需要把源码给别人。
再说了,现在如火如荼的开源运动和互联网自由开放的精神是一致的,互联网上有无数非常优秀的像Linux一样的开源代码,我们千万不要高估自己写的代码真的有非常大的“商业价
值”。那些大公司的代码不愿意开放的更重要的原因是代码写得太烂了,一旦开源,就没人敢用他们的产品了。
2.几种解释器区别
3.你看到提示符>>>就表示我们已经在Python交互式环境中了,可以输入任何Python代码,回车后会立刻得到执行结果。现在,输入exit()并回车,就可以退出Python交互式环境(直
接关掉命令行窗口也可以)。
4个空格的缩进,在文本编辑器中,需要设置把Tab自动转换为4个空格
大小写敏感
4.请注意区分命令行模式和Python交互模式。看到类似C:\>是在Windows提供的命令行模式,在命令行模式下,可以执行python进入Python交互式环境,也可以执行python hello.py运
行一个.py文件。看到>>>是在Python交互式环境下:在Python交互式环境下,只能输入Python代码并立刻执行。在命令行模式运行.py文件和在Python交互式环境下直接运行Python代
码有所不同。Python交互式环境会把每一行Python代码的结果自动打印出来,但是命令行模式下运行Python代码却不会
print('hello, world')例如C:\work,把文件保存为hello.py,就可以打开命令行窗口,把当前目录切换到hello.py所在目录,就可以运行这个程序了:C:\work>python hello.py
hello, world
直接运行py文件.有同学问,能不能像.exe文件那样直接运行.py文件呢?在Windows上是不行的,但是,在Mac和Linux上是可以的,方法是在.py文件的第一行加上一个特殊的注释:
#!/usr/bin/env python3
print('hello, world')
然后,通过命令给hello.py以执行权限:$ chmod a+x hello.py
就可以直接运行hello.py了
5.print('The quick brown fox', 'jumps over', 'the lazy dog') The quick brown fox jumps over the lazy dog
print('100 + 200 =', 100 + 200) 100 + 200 = 300
如果字符串内部既包含'又包含"怎么办,可以用转义字符\来标识,r'?'表示'?'内部的字符串默认不转义, print('''line1
... line2
... line3''')
6.理解变量在计算机内存中的表示也非常重要。
a = 'ABC'时,
Python解释器干了两件事情:
在内存中创建了一个'ABC'的字符串;
在内存中创建了一个名为a的变量,并把它指向'ABC'。
a = 'ABC'
b = a
a = 'XYZ'
print(b)弄懂输出是ABC
7./除法,//地板除(留整)
8.1 最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),一个字节能表示的最大的整数是255(11111111),ASCII编码把127个字母被编码到计算机里,也就是大小写
英文字母、数字和一些符号。但是要处理其他比如中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,各国有各国的标准,就会不可避免地出现冲突,结
果就是,在多语言混合的文本中,显示出来会有乱码。因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
UTF-8(可变长编码)编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个
字节。克服了存储和传输的文本包含大量英文字符时用Unicode编码比ASCII编码需多一倍的存储空间的情况。
UTF-8编码有一个额外的好处,就是ASCII编码可以被看成是UTF-8编码的一部分,所以ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
计算机系统通用的字符编码工作方式:
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。
浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器,很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。
8.2 Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes,bytes的每
个字符都只占用一个字节。bytes类型的数据用带b前缀的单引号或双引号表示:x = b'ABC'
8.3 反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str
9.#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须还要确保菜单栏encoding中选中UTF-8 without BOM。
10.%运算符是用来格式化字符串的,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。
%整数和浮点数可以指定是否补0和整数与小数的位数。
>>> 'Hello, %s' % 'world’ 'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
>>> '%2d-%02d' % (3, 1) '_3-01'
>>> '%05.2f' % 3.1415926 ’003.14’
11.列表list[]是有序的集合,可以随时添加和删除其中的元素。用索引来访问list中每一个位置的元素,索引是从0开始,最后一个元素的索引是len(classmates) - 1,范围超出报
错。还可以用-1做索引,直接获取最后一个元素,以此类推。
把某个元素替换成别的元素,可直接赋值给对应的索引位置 >>> classmates[1] = 'Sarah'
list里面的元素的数据类型也可以不同,list元素也可以是另一个list 访问如二维数组。
12.元组tuple()是和list类似的有序集合,但是tuple一旦初始化就不能修改。它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用
classmates[0],classmates[-1],但不能赋值成另外的元素。
只有1个元素的tuple定义时必须加一个逗号 , ,来消除歧义。
>>> t = ('a', 'b', ['A', 'B'])中可改变t[2][0]和t[2][1],因为改变的是本身可变的List,而tuple的每个指向并没变。
13.if : elif : else :
if语句是从上往下判断,如果在某个判断上是True,把该判断对应的语句执行后就忽略掉剩下的
if的判断条件还可以简写,如:if x: print('True') 只要x是非零数值、非空字符串等,就判断为True,否则为False
14.for in : whlie : break continue
break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环,并直接开始下一轮(不是下一个)循环。这两个语句通常都必须配合if语句使用。
break和continue会造成代码执行逻辑分叉过多,容易出错。都可以通过改写循环条件或者修改循环逻辑,去掉break和continue语句。
15.字典dict{ : , : ,...... }
把数据放入dict的方法,除了初始化时指定外,还可以通过key放入如 d['Adam'] = 67 in 判断key是否存在
查找和插入的速度极快,不会随着key的增加而变慢;需要占用大量的内存,内存浪费多,与list相反。
key必须是不可变的对象。
16.集合set([])是一组不重复的key的集合,重复元素被自动过滤,原理和dict一样。
set可以看成数学意义上的无序和无重复元素的集合,两个set可以做数学意义上的交集、并集等操作:& 和 |
17.调用对象自身的方法不会改变对象自身的内容,相反,这些方法会创建新的对象并返回。
18.函数体内部的语句在执行时,一旦执行到return时函数就执行完毕,并将结果返回,没有return语句,也会返回结果,只是结果为None,return None可以简写为return。
pass语句什么都不做,可用作占位符,如现在还没想好怎么写函数的代码就可以先放一个pass,让代码能运行起来,有些控制语句中不放pass会有语句错误。
python函数可以返回多值,但其实是返回了一个省略()的tuple
19.函数接口定义的关键点是 参数的名字 和 位置 ,除了正常参数外,还可以使用默认参数、可变参数和关键字参数。
1.默认参数放在正常参数后面。变化小的在变化大的后面,变化小的可做默认参数。1.2.默认参数必须指向不变对象,否则函数会记住先前每次的操作结果。
2.1可变参数就是传入的参数个数是可变的,定义时在参数前加*:def calc(*numbers):,调用:calc(1, 3, 5, 7),参数numbers接收到的是一个tuple。
如果已经有了一个list或tuple:>>> nums = [1, 2, 3] >>> calc(*nums)
2.2上面两个情况不用可变参数的解决方法是,定义def calc(numbers): 调用calc((1, 3, 5, 7)) 【也可list】
>>> nums = [1, 2, 3] >>> calc(nums[0], nums[1], nums[2])
2.3定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号,这种写法相当有用且常见,允许你传入0个或任意个参数。
3.1关键字参数允许你传入0个或任意个含参数名的参数,定义时在参数前加**,这些关键字参数在函数内部自动组装为一个dict。
定义:def person(name, age, **kw): print('name:', name, 'age:', age, 'other:', kw)
调用及结果:>>> person('Adam', 45, gender='M', job='Engineer') >>> name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去>>> extra = {'city': 'Beijing', 'job': 'Engineer'}>>>def person(name, age, **kw)
>>>person('Jack', 24, **extra) name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
3.2不用关键字参数写法:>>> extra = {'city': 'Beijing', 'job': 'Engineer'} >>>def person(name, age, kw) >>> person('Jack', 24, city=extra['city'],
job=extra['job']) name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
3.3 kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。
4.1命名的关键字参数是为了限制调用者可以传入的参数名。分隔符是*或写在可变参数*args后面,定义def person(name, age, *, city, job):
print(name, age, city, job) 调用及结果>>> person('Jack', 24, city='Beijing', job='Engineer') Jack 24 Beijing Engineer
4.2必须传入参数名,否则像这样>>> person('Jack', 24, 'Beijing', 'Engineer')调用会报错。
4.3定义时命名的关键值参数可设置默认值。
5.1 5种参数都可以组合使用,但参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a, b, c=0, *args, **kw): print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
5,2 调用形式有两种:一. f1(1, 2, 3, 'a', 'b', x=99) a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
二.通过一个tuple和dict:>>> args = (1, 2, 3, 4)>>> kw = {'d': 99, 'x': '#'}>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参
数是如何定义的。
20.递归函数过深的调用会导致栈溢出。
21.Python就是要写更少更简单的代码,可使用高级特性实践这个思想。
21.1切片[:]前包括后不包括,可以用负号引索,最后一个元素引索是-1,第一个引索0和最后一个引索-1可以省略
元组和字符串可以切片,但是不会改变本身
21.2如果给定一个可迭代对象,可以通过for循环来遍历这个对象,这种遍历称为迭代。for key in d ,for value in d.values(),for k, v in d.items()。
21.3列表生成式例子 表达式后加for循环[x * x for x in range(1, 11)][1, 4, 9, 16, 25, 36, 49, 64, 81, 100],加判断[x * x for x in range(1, 11) if x % 2 == 0][4,
16, 36, 64, 100],两层[m + n for m in 'ABC' for n in 'XYZ']['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'],一层两个变量d = {'x': 'A', 'y': 'B', 'z':
'C' }[k + '=' + v for k, v in d.items()],使用方法[s.lower() for s in L]
L1 = ['Hello', 'World', 18, 'Apple', None] L2=[] [L2.append(s.lower()) for s in L1 if isinstance(s,str) == True]
21.4一边循环一边计算的机制,称为生成器,可以在循环的过程中不断推算出后续的元素,不必创建完整的list节省大量空间。
创建生成器第一种方法是把列表生成式的[]改为(),用next()函数获得下一个值(基本不用),一般用for来迭代打印。生成器保存的是算法,第二种方法是把算法函数中的print改
为yield,使函数变为生成器,生成器函数在每次调用next()的时候执行,执行顺序是遇到yield返回值,然后若再次调用next()时执行到下一个yield并返回值,以此类推
while true:并不是无限的循环,而是在第一次执行后使函数处于监听模式,什么时候监听到了动静什么时候继续往下执行一下循环,如果没连接,就不会执行下一循环.(nest())
21.5可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator,
凡是可作用于for循环的对象都是Iterable类型;凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列,可以表示一个无限大的数据流;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
22.if __name__=='__main__': test() 保证模块不被多个文件同时导入,并且这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的是运行测试。
模块文件中外部不需要引用的函数全部定义成_private,只有外部需要引用的函数才定义为public
安装第三方模块,是通过包管理工具pip完成的。Mac或Linux安装pip本身这个步骤就可以跳过。Windows,在命令提示符窗口下尝试运行pip。安装命令是pip install 模块名,已安
装模块的存放路径查看 import sys sys.path
函数:
print()
input()返回的数据类型是str
ord()获取字符的编码数表示
chr()把编码转换为对应字符
len()计算str字符数,计算bytes字节数:
range()生成一个整数序列0....,内为个数
list()
isinstance( ,Iterable)存在collections模块中判断对象是否可迭代
enumerate()把一个list变成索引-元素对
isinstance( ,str)判断对象是否为字符串
isinstance( ,Iterator)判断对象是否是为迭代器
方法:
encode()将str编码为指定的bytes
>>> 'ABC'.encode('ascii') b'ABC'
>>> '中文'.encode('utf-8') b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii') Error
decode()将bytes变为str
append()往list中追加元素到末尾
extend()往list中追加list到末尾
insert( ,)在list中把元素插入到指定的位置
pop()在list中删除指定位置的元素
get()在dict中获取key值,key不存在返回不显示的None或指定值(加,和参数)
pop()在dict中删除该key以及其值
add()在set中添加元素
remove()在set中删除元素
弄清这几个概念:递归、迭代、列表生成式、生成器、迭代器
cmd交互式环境中,python 打开python交互模式、python 文件名.py 运行python文件、more 文件名.py 查看文件源代码
汉诺塔问题递归实现:
def move(n, a, b, c):
if n == 1:
print('move', a, '-->', c)
return
move(n-1, a, c, b)
print('move', a, '-->', c)
move(n-1, b, a, c)
杨辉三角生成器与列表生成式实现:
def triangles():
L = [1]
while True:
yield L
L.append(0)
L = [L[i - 1] + L[i] for i in range(len(L))]
调用:
n = 0
for t in triangles():
print(t)
n = n + 1
if n == 10:
break
#第一次输出L=[1];第二次L=[1,0] range(L)=range(2)有两个元素,第一个元素根据表达式L[-1]+L[0]=1,第二个元素L[0]+L[1]=1,输出[1,1];第三次L=[1,1,0]range(L)=range
(3)有三个元素第一个元素L[-1]+L[0]=1,第二个L[0]+L[1]=1+1=2,第三个L[1]+L[2]=1.后面一样。(三角算法看了10小时心疼自己。。。)