廖雪峰python笔记

python

我想说…python的语法真的是太多了,跟java真的有很多的不一样,可能是动态语言的原因,自己刚开始接触有很多不适应的地方。这一篇是自己根据廖雪峰的python教程写的笔记,初心是学习一下python的基础语法方便后续的机器学习等内容的学习,并且希望自己可以熟悉Markdown语法方便后来记笔记。自己还有很多不熟练的地方,后面继续练几个oj题并且做几个小项目跟进吧,希望自己的python能学好。
由于是快速入门,所以只写了一些我觉得比较有价值并且不熟悉的地方,对于java中也有的,我就懒得写了

python基础语法

可以用help(函数名)命令行来获得函数的信息

  • 冒号+缩进:python语法功能的一部分,表达代码的所属关系

  • 注释: 单行 #

    ​ 多行注释 ‘’‘这里是注释’’'

    ​ 续行符 \ (续行符后不能存在空格,必须直接换行)

  • 变量:程序中用于保存和表示数据的占位符号

      	 命名 大小写敏感,首字符不能是数字,不与保留字相同,*可以使用中文作为变量名*
    
  • 字符串: 使用双引号单引号,两者没有差别

    -12-11-10-9-8-7-6-5-4-3-2-1
    01234567891011

    s[N]通过序号获取某个字符

    s[N:M]获取从N到M(不含)子串

    用 **r’’**表示’'内部字符串默认不转义

    ord() 获取字符的整数表示

    chr() 把编码转换为对应的字符

  • print() : 可以接收多个字符串,用逗号分隔,依次打印,遇到逗号输出一个空格

  • input() : 可以接收字符串用作输入提示

    返回的数据类型是 str

  • 空值 : python中的控制用None表示

  • python中整数和浮点数没有大小限制,超出一定范围会直接表示为inf(无限大)

  • Unicode编码 、ASCII编码、UTF-8编码

    (1)ASCII编码是1个字节,Unicode编码是2个字节,而UTF-8编码是可变长编码

    (2)计算机内存中同意使用Unicode编码,当需要保存到硬盘或传输时转换为UTF-8编码

    (3)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25iTnMGH-1570083741503)(C:\Users\difendDF\AppData\Roaming\Typora\typora-user-images\1569900537659.png)]

  • bytes类型数据用带 b 前缀的单引号或双引号表示 eg. x = b’ABC’

  • 以Unicode表示的str通过 encode() 方法可以编码为指定的bytes eg.

    ​ >>> ’ABC‘.encode(‘ascii’)

    ​ b’ABC’

    ​ >>> ‘中文’.encode(‘utf-8’)

    ​ b’\xe4\xb8\xad\xe6\x96\x87

    把bytes变为str需要用 decode() 方法 eg.

    ​ >>> b’ABC’.decode(‘ascii’)

    ​ ‘ABC’

    ​ >>> b’\xe4\xb8\xad\xe6\x96\x87’.decode(‘utf-8’)

    ​ ’中文‘

    若bytes中有一小部分无效字节,传入 errors = ’ignore‘ 忽略错误的字节 eg.

    ​ >>> b’\xe4\xb8\xad\xff’.decode(‘utf-8’, errors=‘ignore’)

    ​ ’中‘

    len()函数计算str包含多少字符(如果是bytes则计算字节数) eg.

    ​ >>> len(‘ABC’)

    ​ 3

    ​ >>> len(‘中文’.encode(‘utf-8’))

    ​ 6

  • 为了让python解释器读取源码是按UTF-8编码,在文件开头写上

    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    

    第一行是告诉Linux/OS X系统这是一个python可执行程序

    第二行告诉Python解释器按UTF-8编码读取源代码

  • 格式化输出:采用 % 实现

    ​ >>> ‘Hi, %s, you have $%d.’ % (‘Michael’, 1000000)

    ​ ‘Hi, Michael, you have $1000000.’

    占位符替换内容备注
    %d整数
    %f浮点数
    %s字符串可以把任何数据类型转换为字符串
    %x十六进制整数

    format() :用传入的参数替换字符串占位符 eg.

    ​ >>> ‘Hello, {0}, 成绩提升了{1:.1f}%’.format(‘小明’, 17.125)

    ​ ‘Hello, 小明,成绩提升了 17.1%’

  • list:一种有序的集合,可以随时添加和删除其中的元素

    ​ >>> classmates = [’Michael‘,’Bob‘,’Tracy‘]

    用len()函数可以获得list元素的个数

    ​ >>> len(classmates)

    用索引来访问list中每一个位置的元素,索引从 0 开始

    向list中添加元素到末尾:classmates.append(’Adam‘)

    将元素插到指定的位置:classmates.insert(1,‘Jack’)

    删除list末尾元素:classmates.pop()

    删除指定位置元素:classmates.pop(1)

    替换某位置元素:classmates[1] = ‘Sarah’

    list中的元素数据类型可以不同,也可以是另一个list

  • tuple:一旦初始化就不能修改

    ​ >>> classmates = (‘Michael’,‘Bob’,‘Tracy’)

    如果tuple中只有一个元素,则必须加一个 **逗号,**来消除歧义

    ​ >>> t = (1,)

  • 条件判断:

    ​ if <条件判断1>:

    ​ <执行1>

    ​ elif <条件判断2>:

    ​ <执行2>

    ​ elif <条件判断3>:

    ​ <执行3>

    ​ else :

    ​ <执行4>

  • dict:字段,使用键-值存储,具有极快的查找速度

    ​ >>> d = {‘Michael’: 95, ‘Bob’: 75, ‘Tracy’: 85}

    ​ >>> d[‘Michael’]

    ​ 95

    通过 in 判断key是否存在

    通过**get()**方法,若key不存在范围None或指定 value

  • set:没有重复的key

    通过 add(key) 方法添加元素

    通过 remove() 方法删除元素

函数

定义函数

定义一个函数要使用 def 语句,一次写出 函数名、括号、括号中的参数和冒号:

定义一个什么事也不做的空函数可以用 pass 语句 eg.

def nop():
    pass
  • python中可以返回多个返回值
import math

def move(x,y,step,angle=0):
    #返回的是一个(nx,ny)的元组
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx,ny
  • python中可以为参数指定默认值
def power(x,n = 2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

PS : 默认参数必须放在后面

​ 默认参数必须指向不变对象

可变参数

允许传入0个或人一个参数,这些可变参数在函数调用时自动组装成一个tuple

def	calc(*numbers):				
    sum	= 0				
    for	n in numbers:								
        sum	= sum +	n *	n				
    return	sum

​ >>>calc(1, 2)

​ 5

​ >>> calc()

​ 0

​ >>> nums = [1, 2, 3]

​ >>> calc(*nums)

​ 14

关键字参数

允许传入0个或人一个含参数名的参数,这些关键字参数在函数内部自动组装成一个dict

def	person(name, age, **kw):				
    print('name:', name, 'age:', age, 'other:',	kw)

​ >>> person(‘Bob’, 35, city=‘Beijing’)

​ name: Bob age: 35 other: {‘city’: ‘Beijing’}

​ >>> person(‘Adam’, 45, gender=‘M’, job=‘Engineer’)

​ name: Adam age: 45 other: {‘gender’: ‘M’, ‘job’: ‘Engineer’}

​ >>> extra = {‘city’: ‘Beijing’, ‘job’: ‘Engineer’}

​ >>> person(‘Jack’, 24, **extra)

​ name: Jack age: 24 other: {‘city’: ‘Beijing’, ‘job’: ‘Engineer’}

命名关键字参数

因为关键字参数可以不受限制的输入,如果我们想要限制关键字参数的名字,可以使用命名关键字参数,例如,只接受city和job作为关键字参数

def person(name,age,*,city,job):#*后面的参数被视为命名关键字参数
    print(name,age,city,job)

def person(name,age,*args,city,job):
    #函数中有可变参数则后面的命名关键字参数不需要一个特殊的*分隔符
    print(name,age,args,city,job)

参数组合

参数定义的顺序必须是 必选参数、默认参数、可变参数、命名关键字参数、关键字参数

def	f1(a, b, c=0, *args, **kw):				
    print('a =', a,	'b =',	b, 'c =', c, 'args =', args, 'kw	=',	kw)
def	f2(a, b, c=0, *, d,	**kw):				
    print('a =', a,	'b =', b, 'c =', c,	'd	='	d, 'kw	=',	kw)

>>>	f1(1, 2) 
a =	1 	b = 2	c =	0	args = ()	kw = {} 
>>>	f1(1, 2, c=3) 
a =	1	b =	2	c =	3	args = ()	kw = {} 
>>>	f1(1, 2, 3,	'a', 'b') 
a =	1	b =	2	c =	3	args = ('a', 'b')	kw = {} 
>>>	f1(1, 2, 3,	'a', 'b', x=99) 
a =	1	b =	2	c =	3	args = ('a', 'b')	kw = {'x': 99} 
>>>	f2(1, 2, d=99, ext=None) 
a =	1	b =	2	c = 0	d =	99	kw = {'ext': None}

高级特性

切片

选取一个范围内的元素

#设有一个列表
L = ['Michael','Sarah','Tracy','Bob','Jack']
#取前三个元素(左闭右开)
>>> L[0:3]
['Michael','Sarah','Tracy']
#若第一个索引是零,可以省略不写
>>> L[:3]
['Michael','Sarah','Tracy']
#python还支持倒数切片
>>> L[-2:]
['Bob','Jack']
>>> L[-2:-1]
['Bob']
#对于一个list可以进行跳跃取数
L = list(range(100))
>>> L[:10:2]#前10个数每两个取一个
[0,2,4,6,8]

PS:对于tuple和str也可以进行切片操作,不过tuple切片结果是tuple,str切片结果是str

迭代

python中只要是可迭代对象都可以进行迭代,通过 collections模块的Iterable类型判断 当前对象是否可迭代

>>> from collections import Iterable
>>> isinstance('abc',Iterable)#str是否可迭代
True
>>> isinstance([1,2,3],Iterable)#list是否可迭代
True
>>> isinstance(123,Iterable)#整数是否可迭代
False

python中内置的 enumerate 函数可以吧一个list变成 索引-元素对

for	i, value in	enumerate(['A', 'B', 'C']): 			
    print(i,value)
    
结果:0 A 1 B 2 C

注意 python中for循环内经常可以同时引用两个变量

for	x, y in	[(1, 1),(2,	4),	(3,	9)]:
    print(x, y) 

结果:  1	1
	   2  4 
	   3  9
#可以对字典的key和value进行取值
d = {'x': A, 'y': B, 'z': C}
for k,v in d.items():
    print(k,'=',v)
    
结果: y = B
	  x = A
      z = C

列表生成式

List Comprehensions是python中内置的用来创建list的生成式

>>> [x * x for x in range(1,11)]#生成0~10的平方数的list
[1,4,9,16,25,36,49,64,81,100]
>>> [x * x for x in range(1,11) if x % 2 == 0]#前10个偶数的平方数
[4,16,36,64,100]
>>> [m + n for m in 'ABC' for n in 'XYZ']#生成全排列
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

生成器

在python中可以不必创建完整的list,而采用一种边循环边计算的机制就是生成器: generator

g = (x * x for x in range(10))
>>> next(g)
0
#generator是可迭代对象所以可以采用for循环
for n in g:#这种方法不会产生StopIteration错误
    print(n)
#generator还可以在函数中,yield就是关键字    
'''在执行过程中遇到yield就中断,下一次继续执行,
	若想获取return语句的值就需要处理StopIteration异常'''
def	odd():			
    print('step	1')				
    yield	1				
    print('step	2')				
    yield(3)				
    print('step	3')				
    yield(5)
>>>	o =	odd() 
>>>	next(o) 
step 1 
1 
>>>	next(o) 
step 2 
3 
>>>	next(o) 
step 3 
5 

迭代器

可以直接作用于for循环的数据类型有:

一、集合数据类型,如:list、tuple、dict、set、str等

二、generator,包括:生成器和带yield的generator function

这些统称为可迭代对象:Iterable,不仅可以用于for循环还可以被next()函数调用

可以被next()函数调用并返回下一个值的对象成为迭代器:Iterator

*generator都是Iterator对象,list、dict、str不是Iterator,但是可以采用 **iter()*函数将Iterable转变成Iterator

函数式编程

高阶函数

python中变量可以指向函数,一个函数可以接收另一个函数作为参数,这种函数成为高阶函数

map/reduce

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回

def f(x):
	return x * x
r = map(f,[1,2,3,4,5,6,7,8,,9])
print(list(r))

[1,4,9,16,25,36,49,64,81]

reduce()函数接收两个参数,一个是函数,一个是序列,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算

reduce(f,[x1,x2,x3,x4]) = f(f(f(x1,x2),x3),x4)

#对一个序列求和
from functools import reduce
def add(x,y):
    return x + y
reduce(add,[1,3,5,7,9])

25

filter

python内置filter()函数用于过滤序列,filter()函数接收一个函数和一个序列,根据返回值是True还是False决定保留还是丢弃该元素

#删除一个list中的偶数,只保留奇数
def is_odd(n):
    return n % 2 == 1
list(filter(is_odd,[1,2,4,5,6,9,10,15]))

结果:[1,5,9,15]

#删除一个序列中的空字符串
def not_empty(s):
    return s and s.strip()
list(filter(not_empty,['A','','B',None,'C',' ']))

结果:['A','B','C']

sorted

sorted()可以对list进行排序,还可以接收一个key函数来实现自定义排序

#按绝对值排序
sorted([36,5,-12,9,-21],key = abs)
结果:[5,9,-12,-21,36]
#字符串排序
sorted(['bob', 'about',	'Zoo', 'Credit'],key = str.lower)
结果:['about', 'bob', 'Credit', 'Zoo']
#sorted()函数默认升序排序,若想要反向排序,可以传入第三个参数reverse=True
sorted(['bob', 'about',	'Zoo', 'Credit'], key=str.lower, reverse=True) 
结果:['Zoo', 'Credit', 'bob',	'about']

返回函数

python中可以把函数作为结果返回

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

#当调用lazy_sum()时,返回的结果是求和函数
f = lazy_sum(1,3,5,7,9)
f()
25

闭包

返回函数不要引用任何循环变量,或者后续会发生变化的变量

匿名函数

关键字 lambda表示匿名函数,冒号前面的变量表示函数参数,匿名函数只能有一个表达式,返回值就是该表达式的结果

list(map(lambda	x: x * x, [1, 2, 3, 4, 5, 6, 7,	8, 9])) 
[1,	4, 9, 16, 25, 36, 49, 64, 81]
#其实lambda等价于
def f(x):
    return x * x

装饰器

函数也是一个对象,函数对象有一个 **__name__**属性,可以拿到函数的名字

def now():
    print('2019-10-3')
>>> now.__name__
'now'

在代码运行期间动态增加功能的方式成为 装饰器(Decorator)

#想要在函数调用前后自动打印日志,但是不修改now()函数的定义
def log(func):
    def wrapper(*args,**kw):
        print('call %s()' % func.__name__)
        return func(*args,**kw)
    return wrapper
#可以看出decorator是一个返回函数的高阶函数
@log
def now():
    print('2019-10-2')

>>> now()
call now()
2019-10-2
#使用functools.wraps可以防止返回函数的名字被修改
import	functools
def	log(func):				
    @functools.wraps(func)				
    def	wrapper(*args, **kw):								
        print('call	%s():' % func.__name__)								return	func(*args,	**kw)				
    return	wrapper
#针对带参数的decorator
import	functools
def	log(text):				
    def	decorator(func):								
        @functools.wraps(func)								
        def	wrapper(*args, **kw):											print('%s %s():' % (text, func.__name__))						return	func(*args,	**kw)									return	wrapper				
     return	decorator

偏函数

python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function) 非数学意义上的偏函数

#int()函数可以将字符串默认按十进制转换,还有一个base参数,可以按照我们想要的进制转换
>>> int('12345',base = 8)
5349
#functools.partial就是帮我们创建一个偏函数,把一个函数的某些参数给固定住,返回一个新函数,调用这个新函数会更简单
import functools
int2= funtools.partial(int,base = 2)
>>> int2('1000000')
64
#注意,int2仅仅把参数base的默认值设定为2,仍可以传入其他的值
>>> int2('1000000',base = 10)
1000000

模块

在Python中,一个.py文件称为一个模块(Module)

使用模块

#!/usr/bin/env	python3  #让这个py文件直接在Unix/Linux/Mac上运行
#-*- coding: utf-8 -*-   #表示这个py文件本身使用标准UTF-8编码 

' a	test module '   #模块的文档注释,任何模块代码第一个字符串被视为文档注释

__author__	= 'difendDF'

import	sys        #导入sys模块

def	test():				
    args = sys.argv				
    if len(args)==1:								
        print('Hello, world!')				
    elif len(args)==2:								
        print('Hello, %s!' % args[1])				
    else:								
        print('Too many	arguments!')
        
if	__name__=='__main__':		#运行测试		
    test()

面向对象编程

类和实例

定义类用 class关键字,紧接着类名,类名通常是大写开头的单词,紧接着是(object),表示从哪个类继承下来,类中属性的初始化采用 **__init__**方法

class student(Object):
    #参数self均不用传参
    def __init__(self,name,score):
        self.name = name
        self.score = score
    def print_score(self):
        print('%s : %s' % (self.name,self.score))      

访问限制

python中类也有共有和私有之分,如果想让内部属性不被外部访问,可以把属性名称前加两个下划线__,实例中变量名如果以 __ 开头就变成了一个私有变量

class student(Object):
    def __init__(self,name,score):
        self.__name = name
        self.__score = score
    def print_score(self):
        print('%s : %s' % (self.__name,self.__score))      

python中 以双下划线开头,双下划线结尾的变量是特殊变量

获取对象信息

**type()**函数可以判断对象类型

>>>	type(123) 
<class 'int'> 
>>>	type('str') 
<class 'str'> 
>>>	type(None) 
<type(None) 'NoneType'>
>>>	type(abs) 
<class 'builtin_function_or_method'> 
>>>	type(a) 
<class '__main__.Animal'>
>>>	import	types 
>>>	def	fn(): 
...		pass 
... 
>>>	type(fn)==types.FunctionType 
True 
>>>	type(abs)==types.BuiltinFunctionType 
True 
>>>	type(lambda	x : x)==types.LambdaType 
True
>>>	type((x	for	x in range(10)))==types.GeneratorType 
True

要判断class类型可以使用**isinstance()**函数

>>>	isinstance([1,	2,	3],	(list,	tuple)) 
True
>>>	isinstance((1,	2,	3),	(list,	tuple)) 
True

如果要获得一个对象的所有属性和方法,可以使用**dir()**函数,返回一个包含字符串的list

getattr()、setattr()、hasattr()可以直接操纵一个对象的状态

class MyObject(object): 
	def	__init__(self): 								
        self.x = 9 					
        def	power(self):								
            return	self.x * self.x 
obj	= MyObject()

>>> hasattr(obj,'x')#有属性'x'吗
True
>>> obj.x
9
>>> setattr(obj,'y',19) #设置一个属性‘y’
>>> getattr(obj,'y') #获取属性‘y’
19
>>> getattr(obj,'z',404) #获取属性'z',若不存在则返回默认值404

面向对象高级编程

使用__slots__

python是动态语言,我们可以随时给class的实例添加属性或方法,但是如果想要限制实例的属性的话就需要**__slots__**来实现

class Student(object):
    __slots__ = ('name','age') #用tuple定义允许绑定的属性名

>>>	s =	Student()	#创建新的实例
>>>	s.name = 'Michael'	#绑定属性‘name’
>>>	s.age =	25	#绑定属性'age'
>>>	s.score	= 99	#绑定属性'score' 
Traceback (most	recent call	last):		
    File "<stdin>",	line 1,	in <module> 
AttributeError:	'Student' object has no	attribute 'score'

注意:__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用

定制类

__str__

>>>	class Student(object):
    def	__init__(self,	name): 							
        self.name =	name
        def	__str__(self):								
            return	'Student object	(name:	%s)' %	self.name 
        
>>>	print(Student('Michael')) 
Student	object (name:	Michael)

class Student(object):
    __slots__ = ('name','age') #用tuple定义允许绑定的属性名

>>>	s =	Student()	#创建新的实例
>>>	s.name = 'Michael'	#绑定属性‘name’
>>>	s.age =	25	#绑定属性'age'
>>>	s.score	= 99	#绑定属性'score' 
Traceback (most	recent call	last):		
    File "<stdin>",	line 1,	in <module> 
AttributeError:	'Student' object has no	attribute 'score'

注意:__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用

定制类

__str__

>>>	class Student(object):
    def	__init__(self,	name): 							
        self.name =	name
        def	__str__(self):								
            return	'Student object	(name:	%s)' %	self.name 
        
>>>	print(Student('Michael')) 
Student	object (name:	Michael)


版权声明:本文为qq_39526294原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。