零零散散知道些python的语法,但是没有系统的学习。今天开个系列好好学一下python~里面的知识点大多数是根据B站视频python编程基础入门【廖雪峰】_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili学习的。
- 注释
# 单行注释
"""
多行注释
多行注释
"""
'''
多行注释
多行注释
'''
解释器与编译器
解释器:逐句翻译为可执行语句。资源有限情况下更好些,python考虑到跨平台,采用解释方式。
编译器:整体拿来,全部翻译为可执行语句,然后再执行。性能更好些。文件后缀
.pyc python字节码文件 c:code-byte
.pyo python优化文件 o:optimizing 执行效率更高输出函数
a=100
print "a=%d" % a
print "a=",a
python2: print value
python3: print(value)
版本查看: python --version python3 --version
变量:本质为可修改的内存空间。在python中变量是关联一个对象的符号,包含一些可调用函数。命名以下划线或字母开头。
核心数据类型和内置对象
1)数字类型包含复数类型。
2)数字常量表示方法:
二进制:0b开头 eg:a=0b1101 a=13
八进制:0o开头 eg:a=0o17 a=15
十六进制:0x开头 eg:a=0x1A a=26
3)浮点数(小数)
.907=0.907=9.07e-1(e-1表示10的2次方)
4)Bool类型:True值为1,False值为0。
5)空值 None,不属于任何类型。
6)C/C++中定义类型后不能再变,python中的变量均为对象,类型可变,动态、灵活。
- 算术运算符
a=10 b=3
a/b=3.33333333(除:正常除(C/C++中若为整型,会截取。浮点型不截取))
a//b=3(地板除:截取小数点后面)
10**3=1000(**幂运算,表示10的3次方)
表达式:变量/常量+运算符组合而成。常量:只读,const。
程序四大部分:代码段、数据段、堆、栈。数据段中包含只读和普通的。
a=[1,2,3,4]
b=a
a[0]=100
a=b=[100,2,3,4]
a和b均指向同一块内存区域,由于内存上的数据被修改了,所以修改a,b也发生变化。浅拷贝。原因:节省时间,但并不安全。
- 序列赋值语法:
a, b, c = 10, 20, "hello"
- is / is not
判定两个变量是否绑定同一对象。
a=1; b=1
a is b True
c=2; d=c-1
a is c False
a is d True
- del 删除变量,同时解除与对象的关联。若对象不被任一变量引用,则释放对象空间。
a=1; b=a; c=a
del a; del b (删除变量a和b,解除对1的引用)
c=1 (c仍然可以引用1)
关系运算符 支持 2 < a < 5 这种格式
生成对象函数
a=123; b="456";
c=a+int(b)=579
b=str(123);
b='123'
type(x) 返回x的类型
预置的数值型函数:
取绝对值 abs(x)
四舍五入 round(x, n) n为小数向右取整的位数
幂运算 pow(x, y) x的y次方
- 条件语句:注意else if用elif表示,且条件语句后有冒号:
if XXX:
语句1
elif XXX:
语句2
else:
语句3
条件表达式:
表达式1 if 真值表达式 else 表达式2
x=x if x > 0 else -x 等同于x=abs(x)
pass语句,空语句,什么也不做,用来填补语法空白。
布尔运算
1)运算符 not and or。不用!, &&, ||。在C里面&表示位逻辑与(两个数对应的每个位进行与运算),&&表示逻辑与(表达式逻辑关系与操作)
2)and运算符
表达式1 and 表达式2
优先返回为假值(False)的对象。当表达式1的值为True时,返回表达式2,若表达式2为假值返回表达式1。
0 and 100 返回0
100 and 200 返回200
100 and 0 返回0
3)or运算符
表达式1 and 表达式2
优先返回为真值(True)的对象。当表达式1的值为True时,返回表达式1,若表达式1为假值返回表达式2。
0 or 100 返回100
100 or 200 返回100
100 or 0 返回100
bitmap位图:节省空间,I/O速度快,可存入cache(CPU与内存之间的高速缓存,CPU先去cache,再去内存)
位运算
位与10 & 20 = 0 0b01010
0b10100
0b00000
应用:IP地址与子网掩码
IP地址: 192.168.1.100
子网掩码: 255.255.255.0
与运算表示网段地址:192.168.1.0
或运算表示广播地址:192.168.1.255
位或10 | 20 = 30 0b01010
0b10100
0b11110
位异或10 ^ 20 = 30 0b01010
0b10100
0b11110
左移 10 << 2 = 40 左移2位,低位补0。相当于乘以2的2次方。10 << n表示10乘以2的n次方。
右移 10 >> 2 = 2 右移2位,相当于除以2的2次方,小数部分舍弃。10 >> n表示10除以2的n次方。
左移右移的应用:掩码mask,1 << 3 = 1000(二进制)
计算优化:
a = 6; b = 4
c=a*b=a << 2
a = 6; b = 12
c=a*b=(a << 3) + (a << 2) +优先级高于左移右移
a = 100; b = 8
c=a%b=a&7(高位均为8的倍数,只取后三位)
按位取反 ~ 0b1010 = 0b0101
bin(x)将x转换为二进制的字符串。
- 成员运算符
in / not in
a=[1,2,4,8] 4 in a 10 not in a
多条语句写在同一行中间需要; print(x); c=a+b
折行符 \ 放在一行的末尾,表示下一行也是本行的语句基本输入输出
输入 input()
a=input() 输入进去的是字符串,想要整型a=int(input())或int(a)
输出函数
print(1,2,3)
1 2 3
print(1,2,3, sep=',')
1,2,3
print(1,2,3, sep=',',end='a')
1,2,3a
print(1,2,3,file=sys.stdout)
1 2 3 输出在屏幕(默认)
- 循环语句
while 真值表达式:
语句1
else:(可省略)
语句2
for循环语句(更常用,也称范围for语句,避免超出内存)
可迭代对象包括:字符串、列表、元组、字典、集合等。
for 变量列表 in 可迭代对象:
语句1
else:(可省略)
语句2
range()函数
for i in range(10): [0,10)
for i in range(1,10,2): [1,3,5,7,9] 步长为2
range()创建会消耗时间,占用空间。
- 字符串str(string) 以\0为结束符
表示方法
a='hello'
a="hello"
a='''hello''' (可换行)
a="""hello""" (可换行)
字符串分割,a.split(" ")以空格分割
- raw转义失效
b="\""
"
b=r"\""
\\"
- ascii编码 0~127
扩展ascii编码 0~256 高位为1
Unicode编码:国际编码
utf-8编码:单字节第一位为0,后7位ascii。
GB2312 编码:256*256=65536。小于127与ascii相同,约能表示7000汉字
GBK编码:国标扩展编码。扩展20000新的汉字。与utf-8不兼容。
python源码默认存储方式为ascii
Linux推荐utf-8 #coding=utf-8
Windows推荐GBK #coding=gbk
#coding=utf-8 放在第一行,表示代码存储方式为utf-8,编码格式为unicode。
a=u"你好" 使用unicode编码作为中间媒介
utf-8 -> unicode -> gbk -> unicode -> utf-8 ......
\u表示 unicode16位
string.encode('gbk') unicode转gbk
string.decode('gbk') gbk转unicode
- 字符串处理
1)a="123"+"456"
"123456"
2)a="123"*2
"123123"
3)字符串的> 、<比较,比较其ascii码值。
4)a="1234567890" 切片操作
a[3:6]='456' [3,6)
a[3:]='4567890'
a[3::2]='4680' 步长为2
a[-1::-1]='0987654321' 逆序
[起始:终止:步长]
5)a.isdigit() / isalpha() / islower() /isupper() 判断字符串是否全为数字/英文字符/小写/大写
a.center(10,' ') 字符串居中,长度为10,不足部分用' ' 补齐
a.count('str',index) 计算在a中从index开始str子串出现次数,index可省略。不存在即为-1。
a.lower() / upper() 转换为小写/大写
a.replace("123","aaa") 将原字符串中的123替换为aaa
- 列表
list可以看作是一种支持泛型的序列。
空列表:L=[] L=list()
非空列表:L=[1,2,"hello",3.0,[4,5,6] ]
a=list('hello')
a=['h','e','l','l','o'] 对字符串进行拆分
a=[1,2,3] b=[4,5,6]
a+b=[1,2,3,4,5,6]
列表的比较,各个位进行比较。
string不支持元素的赋值,list支持。
切片赋值:
a=[1,2,3]; a[0:2]=[100,200,300]
a=[100,200,300,3] 步长为1则连续替换。步长不为1,则逐位替换,替换的位数必须一致。
常用函数:a=[1,2,3,4]
len(a) / max(a) / min(a) / sum(a) 返回长度/最大/最小/求和
属性方法:
a.index(v) 返回下标
a.add(v) 增加元素
a.contain(v) 判断包含
a.remove(v) 删除第一次出现
a.insert(index,v) 在index位置添加v元素
a.clear() 清空
a.sort(reverse=False) 排序(默认升序,否则用参数)
a.reverse() 列表反转
a.pop() / a.pop(index) 列表末尾元素出栈 / 索引为index元素出栈
a.copy() 列表元素拷贝(浅拷贝)
浅拷贝示例:
a=[1,2,3,4]; b=[100,200,a,300]; c=b.copy()
b[0]=10000
output:
b=[10000,200,[1,2,3,4],300]
c=[100,200,[1,2,3,4],300]
a[0]=10000
output:
b=[100,200,[10000,2,3,4],300]
c=[100,200,[10000,2,3,4],300]
深拷贝,有自己独立的内存空间
import copy
a=[1,2,3,4]; b=[100,200,a,300]; c=copy.deepcopy(b)
b[0]=10000
output:
b=[10000,200,[1,2,3,4],300]
c=[100,200,[1,2,3,4],300]
a[0]=10000
output:
b=[100,200,[10000,2,3,4],300]
c=[100,200,[1,2,3,4],300]
列表是可迭代的对象
L=[2,3,5,7]
for x in L:
print(x)
列表推导式
a=[1,2,3,4,5,6]
L=[i**2 for i in x]
[1, 4, 9, 16, 25, 36]
L=[i**2 for i in range(1,11)] #1到10的平方
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
L=[i**2 for i in range(1,11) if i % 2 == 0] #2,4,6,8,10的平方
[4, 16, 36, 64, 100]
x=[10,20,30]
y=[3,4,5]
Z=[i*j for i in x for j in y]
[30, 40, 50, 60, 80, 100, 90, 120, 150]
- 元组 tuple,不可改变的序列,即只可读的List
t=()
t=tuple()
t=(1,2,"hello")
a,b = 10,20
a,b = b,a
两数值交换不借助额外存储空间能否成功?
可以。
1)加减法。但可能出现溢出问题
```python
a=a+b;
b=a-b;
a=a-b
2)通过异或操作
a=a^b
b=a^b b=a^b^b 任何数x^x=0 b=a^b^b=a
a=a^b a=a^b^a a=b
- 字典(dict)逻辑存储方式不是连续的,采用树的数据结构。
1)字典是一种可变的容器,可存储任意类型的数据
2)每个数据用键-key进行索引,不可用下标索引
3)字典的存储是无序的
4)数据以键值对key-value形式进行存储,key是唯一的,value可重复
5)表示方式以{}括起来
6)字典中的key必须为不可变类型的值:
不可变类型:bool, int, float, complex, str, tuple, frozenset(固定集合)
其中不可变表示其字面值不可变。
可变类型:list, dict, set
d={}
d=dict()
d={"name": "dong", "age":22, "score":100.0}
d["name"]=dong
d["age"]=22
d["gender"]=male 若没有这个key,则新建。
d={"name": "dong", "age":22, "score":100.0}
for k,v in d.items(): #d.items()返回可迭代的dict_items对象,类似还有d.keys(),d.values()
print(k," ",v
name dong
age 22
score 100.0
- 集合(set)
1)集合是可变的容器
2)集合内数据对象都是唯一的,不能重复。
3)集合是无序的存储结构
4)相当于只有键,没有值的字典。也使用{}
5)集合内的元素必须为不可变得对象
a={1,2,3}
b={2,3,4}
a | b = {1,2,3,4} 并集
a&b = {2,3} 交集
固定集合frozenset,内部元素不可改变。
- 函数(function)
1)函数本身也是一个变量,该变量类型是可调用类型,只读。
2)函数有自己的命名空间,若让函数处理外部的数据需要用参数传给函数
3)函数代码块部分不能省略,若为空语句需要填充pass
4)若不包含return,则返回None
5)函数调用作为模块内部语句时,必须先定义函数,后调用函数
6)可返回多个值,如return (max, min),类型为元组tuple。
7)函数定义的结束,缩进与函数相同的语句。
8)关键字传参:fun(a=1,b=2,c=3) 或 fun(b=2,c=3,a=1) 与顺序无关。但fun(b=2,a=1,3)错误,缺少关键字。
9)序列传参:
序列类型:list、tuple、string作为参数列表
fun(a,b,c)
L=[1,2,3]
fun(*L) 等同于 fun(L[0],L[1],L[2])
10)字典关键字传参
d={"age":22, "name":"dong","gender":"male"}
fun(**d)
11)缺省参数:函数的形参被赋予默认值,在函数调用时,若无实参传递值,则使用默认值计算。缺省参数其右侧均为缺省参数。
12)不定长参数
a)星号元组形参
def myfun(*args):
print(args)
for x in args:
print(x)
myfun("12",3,4,"hello")
('12', 3, 4, 'hello')
12
3
4
hello
b)双星号字典形参
def myfun(**kwargs):
print(kwargs)
for k,v in kwargs.items():
print(k,":",v)
myfun(name="dong",age=22)
{'name': 'dong', 'age': 22}
name : dong
age : 22
可变类型:里面的元素可变,只修改对应内存的值。
列表list、集合set、字典dict不可变类型:更改时释放原内存空间,再申请新的内存空间。
frozenset、tuple、str、numbers(int、float)python在函数外部定义的变量为全局变量,但只影响当前模块(当前.py文件)。函数内部定义的变量为局部变量,包含函数参数。
python作用域的四个分类
1)局部作用域(函数内)
2)外部嵌套函数作用域
3)函数定义所在模块(文件)作用域(全局作用域)
4)python内置模块的作用域(doc文件开头""" """内的注释)
范围依次增大
若想要在函数中修改全局变量,则需声明global。且函数中参数不能与全局变量同名。
global说明:
1)全局变量若要在函数内部被赋值,必须经过全局声明,否则被认为是局部变量。
2)全局变量在函数内部不经过声明就可以直接读取访问(不可改写)
3)不能先声明局部变量,再用global声明为全局变量
4)global变量列表的变量名不能出现在此作用域的参数列表里
v=100
def fun():
global v
v=200
fun()
print(v)
200
nonlocal:告诉解释器,nonlocal声明的变量不是局部变量也不是全局变量,而是外部嵌套函数内的变量。
locals()返回所有局部变量
globals()返回所有全局变量
模块化:大的功能拆分为小的模块。组件化:小的函数通过组合形成新功能。
map函数
map(func, *iterable)对于迭代器中的每个元素执行func函数,并返回一个map类型。
def power2(x):
return x**2
X=map(power2,range(1,11))
for i in X:
print(i,end=" ")
print(X)
1 4 9 16 25 36 49 64 81 100 <map object at 0x000002E0B0B7B358>
- sorted函数
sorted(iterable, key=None, reverse=False) 默认升序
key函数用于提供一个值,这个值作为排序的依据。
L=[5,-8,4,3,6]
L2=sorted(L)
print(L2)
[-8, 3, 4, 5, 6]
L2=sorted(L,reverse=True)
print(L2)
[6, 5, 4, 3, -8]
L2=sorted(L,key=abs)
print(L2)
[3, 4, 5, 6, -8]
name=["dong","yu","yue","di","xi"]
name2=sorted(name)
print(name2)
['di', 'dong', 'xi', 'yu', 'yue']
name2=sorted(name,key=len)
print(name2)
['yu', 'di', 'xi', 'yue', 'dong']
- lambda表达式(匿名函数)
作用:创建一个无名的函数对象。与def类似,但不提供函数名。通常应用于较少次数使用该函数,用完拉倒,无需费力起名字。
myadd = lambda x,y : x+y #作用等同于def myadd(x,y): return x+y
print(myadd(100,200))
300
- 闭包:若一个内嵌还是访问函数外部作用域的变量,则这个函数就是闭包。
def make_power(x):
def fun(arg):
return arg**x
return fun
f1 = make_power(2)
print(f1(3))
9
print(make_power(2)(3))
9
- 装饰器:是一个函数,用来包装另一个函数或类。包装的目的:在不改变原函数名的情况下,改变被包装函数(对象)的行为。
def deco(fun):
print("装饰器被调用")
return fun
@deco #若去掉@deco,则只打印myfun
def myfun():
print("myfun")
myfun()
#加上@deco相当于myfun=deco(myfun)
装饰器被调用
myfun
再举个栗子
def msg_device(fun):
def save_money2(name,money):
print("hello,",name)
fun(name,money)
print("Goodbye")
return save_money2
@msg_device
def save_money(name,money):
print(name,"save",money)
save_money("dong",1024)
hello, dong
dong save 1024
Goodbye
结合不定参数使用效果更佳~能够装饰有任意个参数的函数。
def deco(fun):
def _deco(*args,**kwargs):
print("before",fun.__name__)
fun(*args,**kwargs)
print("After",fun.__name__)
return _deco
@deco
def myfun1(name,money):
print(name,"save",money)
myfun1("dong",1024)
@deco
def myfun2(name,money,gender):
print(name,"save",money,"gender is ",gender)
myfun2("yu",1024,"female")
before myfun1
dong save 1024
After myfun1
before myfun2
yu save 1024 gender is female
After myfun2
函数的属性(所有函数都继承了一个原函数,包含以下属性)
1)name 记录函数名
2)doc 函数的文档(第一行注释)模块(module)
1)包含一系列变量、函数、类等组成的程序组
2)模块是一个文件,模块文件名通常以.py结尾。
.py -> .pyc -> .pyo ->pvm(解释变为字节文件,变为目标文件,变为虚拟机)
.c -> .i -> .s -> .o -> bin(预处理,编译,汇编,链接变为二进制)
分类:
1)内置模块,解析器内部可直接使用
2)安装的标准库模块
3)第三方模块(开源)
4)自己编写的模块
1)模块的导入 import,将模块整体导入到当前模块
2)dir(obj)函数,返回模块所有属性的字符串列表。
3)from 模块名 import 模块属性名:将模块内的一个或多个属性导入当前模块 。
若用import只是导入了当前模块,若使用内部的函数仍需要以“模块名.函数()”来调用。若用from import来导入则将内部的属性和函数全部导入,可直接使用其内部的函数。举个栗子:
import math
print(math.sin(3.1415926/2))
0.9999999999999997
from math import *
print(sin(3.1415926/2))
0.9999999999999997
对于被执行的主模块,模块名为main
- 包(package)
1)包是将模块以文件夹的组织形式进行分组管理的方法。
2)作用:将一系列模块进行分类管理,防止命名冲突。可以在需要时加载一个或部分模块,而不是全部模块。
3)相比于目录,包内包含init.py。
4)init.py作用:在包被加载时自动调用。在内部填写包的文档字符串。加载此包所依赖的一些其他模块或包
- 类
类的创建语法
class 类名(继承列表):
"类文档字符串"
实例方法(只有类实例化的对象可以使用)
类变量
类方法(类和实例化对象都可使用)
静态方法
class本身也是个对象,class实例化也是个对象。二者不同
1)实例变量
定义语法:self.变量名 一般在init.py中定义,通过传参来初始化。
def init(self,x1,x2,x3): 第一个参数必须为self
2)实例方法
class 类名:
def 实例方法名(self,x1,x2):
a)实例方法实质是函数,是定义在类内的函数
b)实例方法属于类的属性
c)实例方法的第一个参数代表调用这个实例方法的对象,一般为Self
3)调用方法:
实例.实例方法名(参数) dog1.say
类名.实例方法名(实例, 参数) Dog.say(dog1)
4)构造方法:创建对象时初始化实例变量
a)构造方法名必须为init,不可改变
b)在一个类中只能有一个init构造方法
c)构造方法在实例创建时自动调用,且将实例自身通过第一个参数slef传入init方法
d)构造方法若没有return语句,则返回self自身。
析构方法:在对象销毁时被自动调用
del(self):
5)类变量
a)在类class内定义的变量,此变量属于类,不属于此类的对象(实例)
b)类变量,可以通过该类直接使用
c)类变量可以通过类的实例直接访问
d)类变量可以通过此类的对象的class属性间接访问
6)类方法:需要添加@classmethod
与实例方法的区别:
类方法能够访问类变量,不能访问实例变量;
实例方法能够访问类变量,也能访问实例变量。
类方法可以用实例来调用,也可以用类来调用;
实例方法调用时必须传入实例。
7)isinstance(obj,类)
判断这个对象是否为某个类的对象,是返回true。
id(obj)函数
返回对象的id(地址)