python语言语法与环境
在anaconda中用 pip list可以查看所有安装过的工具包,用python可以进入编辑且运行python代码的状态,用exit()可退出此状态。
下载时换源:
pip install xxx=版本号 -i https://pypi.tuna.tsinghua.edu.cn/simple
删除:
pip uninstall xxx
终止下载或卸载:
ctrl+c
anaconda是一个关于python的发行版本。
pycharm是一个只为python而生的IDE(integrated development environment)。
dictionary字典有一个赋值陷阱:如果将元组A赋值给元组B,若B被更改,A也将被更改(B相当于是A的另一个名字),应使用deepcopy
from copy import deepcopy
b=deepcopy(a)
tuple元组不可赋值
list,tuple都是有序的,可以用索引表示的 dictionary和set都是无序的,没有索引
python中的:逻辑与 and 逻辑或 or 逻辑非 not
如何对anaconda进行换源:
在cmd 命令行中,输入添加以下命令:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes
恢复默认源:
conda config --remove-key channels
查看源:
conda config --show
如果出现了问题,就先恢复默认,再换国内源。
如何在anaconda中创建新环境:(在cmd中打开)
conda create -n new_enr_name python=3.8
解决jupyter不能自动打开浏览器问题:
点击Jupyter Notebook没有反应,不会自动打开浏览器_哔哩哔哩_bilibili
安装anaconda:
Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror
先在官网下载看看版本是什么,然后在这个链接找到对应的正确链接。
安装过程怎么选择:点击Jupyter Notebook没有反应,不会自动打开浏览器_哔哩哔哩_bilibili
python常见语法错误:
syntaxerror语法错误,syntax指语法
list2=list1
之后list1和list2指向的是同一块区域,一者变则另一者也变,要想消除这种危险,只要list2=listq.copy()
indentationerror缩进错误,indentation指缩进
程序执行原理:
CPU负责计算(一块集成电路),内存负责临时储存(4G/8G/16G/32G),硬盘负责永久储存(磁头在磁盘上转转转)
程序保存在硬盘中,运行时放在内存中供CPU调用
python程序要执行,就先将解释器放入内存,再将硬盘中的python程序翻译成机器语言,再执行(解释器在内存中就3MB左右)
python常见语法补充:
print("%s"%"sadd")
即可格式化输出sadd
命名:first_name FirstName
print("123",end="")
这样输出123不换行,end后的内容是对换行的替代
print("123",end="---")
print("456")
这样输出123---456
for循环:只有当for没有在break中退出,for循环全部执行了一遍时才会执行else
for i in [1,2,3]:
if(i==2):
print("找到2了")
break
else:
print("没有找到2")
pycharm使用技巧:
选中多行以后tab可以多行缩进,tab+shift可以取消缩进
调试时步入step into进入一个函数,一行行执行
步过step over不会让你看到函数执行的具体过程,直接跳到下一行代码
def add(a,b):
"""
一个加法器
:param a: 因数1
:param b: 因数2
:return: 和
"""
return a+b
print(add(1,2))
在函数定义的函数名上左键单击一下,稍等片刻,会出现一个小灯泡,在小灯泡中选择“插入docstring存根”,即可为你的函数加上非常专业的注释;
当你在调用函数时单击函数名,然后ctrl+q,即可看到此注释,可以用来装X
PYTHON之模块
其实就是一个个工具包啦,.py文件也可以作为模块,其中的全局变量和函数都可以被别的文件调用,调用时还可以用ctrl+q查看你写的docsrting存根,是不是非常神奇呢?
模块名也是标识符,不能以数字开头,否则就没法调用
python是一种解释性语言,import一个包以后一行一行解释未免太慢,所以系统会在import以后自动把这个包编译成一个二进制文件,也就是pyc文件,c表示complied已编译。这样可以大大提高运行程序的速度。
python高级变量(字典,元组,列表,字符串)之公共方法:
内置函数:(对字典,max和min只对key比较)
a=[1,2,3]
print(max(a))
print(min(a))
print(len(a))
del(a[0])
print(a)
di={"a":3,"b":2,"c":1}
print(max(di))
print([1,1,1]<[1,1])
print((1,2,3)<(1,2,4))
print("abc">"ab")
#列表,字符串和元组可以用来比较,字典不行
切片:
print([1,2,3,4][1:3])
print((1,2,3,4)[1:3])
print("1234"[1:3])
#除了字典之外的三种高级变量有左闭右开的切片功能,字典没有顺序,所以没有切片
运算符:
[1,2]+[3,4]#字典不适用
(1,2)*2#字典不适用
1 in [1,2]#成员运算符
3 not in [1,2]
#in 和 not in对字典来说指的是key值,不是value值
列表追加:
#法1运算符
a=[1]
a+=[2]
print(a)
#法2extend延展一个列表进来
a.extend([3])
print(a)
#法3append一个内容
a.append([4])
print(a)
python之变量
变量名和变量数据是分开储存在内存中的。用一个变量名把数据记录下来的行为叫做引用。变量数据储存在一个小盒子,变量名就是一张便签;用id()函数可以查看地址
一个很奇怪的地方,运行以下代码,明明函数传参传递的是地址,但在函数中做的修改却并不作数:
def f(num): num = 1 num = 2 f(num) print(num)
原因:在test函数中num改名为1时,实际上是新开了一个小盒子,小盒子里装着1,只不过装着1和装着2的小盒子同名而已(验证如下),效果看起来和C语言,C++一样,离开函数后局部变量就被回收
def f(num): num = 1 print("在函数内部num的地址是%s"% id(num)) num = 2 f(num) print(num) print("在函数外部num的地址是%s" % id(num))
如何在函数中修改全局变量呢?用global声明一下即可(用global声明时就不要再用num做函数的参数了)(全局变量前面可以加上g_来将之与其他变量区分)
def f(): global num num= 1 num = 2 f() print(num)
总而言之,通过赋值对参数进行修改,原参数不变(除非声明过了是全局变量);但如果参数是字典,列表这样的可变数据,且在函数内用append,extend等方法进行修改的话,那么原参数是会改变的(注:列表+=的本质是append,也可以修改参数)
def f(): a.extend([4]) a.append(4) a=[1,2,3] f() print(a)
小技巧:如何一次性修改一个变量名在多处的使用-->选中后鼠标右键单击,然后重构,然后重命名
可变类型与不可变类型:(用id函数可以验证)
不可变:数字,字符串,元组-->一旦数据内存确定了,数据就无法再改变;对变量名赋值的本质是新开一个小盒子
可变:列表,字典-->数据内存确定了,数据还可以改变;
字典的key只能是不可变类型:
本质原因:key是通过hash()函数将一个数据映射到另一个数据的,hash()接受的值只能是不可变的string,int,bool,long,float,double,tuple,不能是可变的list,dictionary
python之函数:
返回值可以不止一个
return a,b
这么返回的实际上是一个元组
接收方式有两种:
result = fuction()
a,b=function()
巧妙交换两个数字:
a,b=b,a
缺省参数(对应西佳佳中的默认参数):
默认参数要在多个参数的最末尾
def f1(a=1,b):#是错的 def f2(a,b=1):#是对的
如果要调用多个默认参数,记得加上参数名
def fun(a,b,c=1,d=2):
pass
fun(1,2,c=3,d=4)
多指参数:参数个数不确定时
def fun(a,*args,**kwargs):
print(a,args,kwargs)
fun(1,2,3,4,name="xiaoma",age="19")
args表示arguments,记录一个元组;kw表示keyword,记录一个字典
def fun(*args,**kwargs):
print(args)
gl_a=(1,2,3)
gl_d={"name":"xiaoma"}
fun(gl_a,gl_d)#这样的话a和d会构成一个元组传递给fun
fun(*gl_a,**gl_d)#这样就对了,这种语法叫做拆包,作用是简化多个参数的传递
python之面向对象--封装:
将方法封装起来,将含有方法的对象也封装起来便于开发。
类是对象的抽象,对象是类的具体;类是图纸,对象是飞机。
如何查看一个对象的属性:dir函数
def fun(a):
return a
print(dir(fun))
#如此看来函数也是一个对象
来从一只小猫的身上具体了解了解吧
class cat:
def __init__(self,new_name):#这个初始话方法是在创建对象时自动调用的,它的颜色和我自定义的eat不一样
self.love="mouse"
self.name=new_name
print("%s走了"%self.name)
def eat(self):
#对象是谁,self就是谁的引用
print("%s的爱是%s"% (self.name, self.love))
def __del__(self):#销毁对象时自动调用的
print("%s走了"%self.name)
def __str__(self):#直接print(tom)时会输出这个示例的名字和地址,__str__就是用来对输出内容自定义的方法
return "我踏马来啦!!!"#必须要return 一个字符串
tom=cat("蓝猫")#将cat类实例化
#tom.name="蓝猫"
#如果你不想修改类,又想给你的对象加一个属性,你就可以直接这么做;但请注意,属性的定义一定要在属性的使用之前
tom.eat()#调用tom对象的功能
print(tom)
class people:
def __init__(self,new_name):
self.name=new_name
def run(self):
print("我%s喜欢跑步!!!"% self.name)
def read(self):
print("我%s喜欢读书!!!"% self.name)
def __str__(self):
return "我踏马来啦!!!"
def __del__(self):
print("我踏马走啦!!!")
me = people("马小丫")
print(me)
me.run()
me.read()
class woman:
def __init__(self):
self.__age=18#加两个下划线就是私有属性,在类外不能访问(私有方法同理)
def __secret(self):
print("%d"%self.__age)#类内可以访问(私有方法同理)
#实际上python中没有真正意义上的私有,如果你想在类外访问,方法如下:
xiaofang=woman()
print(xiaofang._woman__age)
#在名字后面加上_类名再加私有的属性或方法就可以访问了
python之面向对象--继承:
想让子类dog拥有父类animal的方法和属性,只需要在创建类时:
class dog(animal):
父类等于基类,子类等于派生类,子从父继承等于派生类从基类派生
如果父类的方法f()不满足子类对f()方法的需求,1.那就在子类中将该方法重写;2.在重写def f(self)中先写上子类的特有方法,再用super().f()调用父类的方法,这样子类就既有新的方法,又有老的方法
def son(father):
def fun(self):
print("新内容")
super().fun()
super是python的一个类,super()就是将其实例化
def son(father):
def fun(self):
print("新内容")
father.bark(self)
这也是一种处理方法,但不建议使用(语法特殊,知道就行,省得看不懂别人写什么)
子类不能访问到父类的私有内容,但可以通过访问父类的公有方法去访问父类的私有方法(具体做法:直接在父类中开一个访问私有内容的共有方法,用子类调用之)
python之多继承:
一个子类可以有多个父类
class son(father,mother): pass
有时多个父类的属性或者方法会有重复,此时应当尽量避免使用这个重复内容,如果实在不能避免,可以通过__mro__来查看子类对父类的调用顺序
print(son.__mro__)#method resolution order方法搜索顺序
object是python3为所有类内置的一个基类,其中的属性可以通过dir函数进行查看。以object为基类的类是新式类,反之则是经典类,python3中的类自动以object为基类,也即全是新式类。是否新式类会影响到多继承时搜索方法的顺序,建议全部使用新式类。
python之类的扩展:
python之中一切皆对象,类也是一种对象
对象的调用方法:
对象.属性
对象.方法名()
类的调用方法:
类.属性
类.方法名()
类的属性:
示例:
class tool:
count =0
def __init__(self,name):
self.name=name
tool.count+=1
axe=tool("斧头")
cup=tool("水杯")
print(tool.count)
实际上,根据python的向上查找机制,通过对象也可以访问类的属性。但此处有一个陷阱:以赋值的方式从对象修改类的属性,会在对象中新开一个属性,并不对类的属性操作,并不向上搜索,类的属性并不发生改变。
class tool:
count =0
def __init__(self,name):
self.name=name
tool.count+=1
axe=tool("斧头")
cup=tool("水杯")
cup.count+=1
print(cup.count)
print(tool.count)
综上,访问类的属性最好通过类而不是通过对象。通过对象也可以访问,但在通过对象修改时会有陷阱。
类的方法:
class a(): #类方法可以调用本类(用cls代替)或其他类的方法,需要用@classmethod代替 @classmethod def f(cls): pass
如果一个方法不需要调用类/对象的属性/方法,那就叫它静态方法
class a(): @staticmethod def f(): pass
总结:如果一个方法要访问类属性,那就定义为类方法;如果要访问实例属性,那就定义成示实例方法;如果不访问属性,那就定义成静态方法;如果既要访问类属性,又要访问实例属性,那就定义为实例方法(经过以下测试,使用类方法也可以。但在逻辑上,使用实例方法给人的感觉更加丝滑,因为类属性只有一个,示例可以有很多)
class tool:
@classmethod
def broken(cls,name):
print("%s 坏了"% name)
axe=tool()
tool.broken("斧头")
python之单例设计模式:
设计模式:代码复用,使用前人代码
单例:确保类()返回的对象只有一个,内存中永远只有一个对象。比如音乐播放器的音乐,回收站操作的文件等等。
在示例化一个类时,系统会做好两件事:1.通过__new__分配空间2.通过__init__初始化。
掌握了__new__方法,我们就可以确保每次实例化的对象都在同一个地址。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
单例设计模式代码实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
想办法让__init__只进行一次:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
python之异常:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
完整语法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
异常具有传递性,一个函数或者方法出了错,就会把错误抛给函数或者方法的调用者。
项目开发中会遇到许多异常,不必在函数中处处费心思处理异常,只要在主函数中处理即可一劳永逸。
主动抛出异常:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
python之模块:
导入模块可以起别名(起了别名之后原名就用不了了)
import xx as xx
可以部分导入模块
from xx import xx
有这样一种情况:从两个模块导入的函数同名。这是后一个会覆盖前一个。处理方法:给其中一个起别名,这样就可以避免这种情况。
方便的导入方式(为什么不用import?因那样用函数还要先敲模块名,这样不用)(不推荐使用,因为模块的函数重名的话没法排查错误):
from xx import *
模块的搜索顺序:现在当前目录下搜索,搜不到的话再去系统目录搜索(不要让自定义的模块名和系统的模块名重名了)
模块的路径可以用__file__查看:
import random
print(random.__file__)
一个问题:在导入一个包时,被导入的包中所有没有缩进的代码都会执行一遍。但有时这些代码并不需要被执行。
解决方法:
__name__是python内置的一个包,其中储存着一个字符串,在执行自身时,__name__的内容是__main__;在被调用时,其内容是模块名
python之包:
一个目录,其中是封装好的库,此外还有一个__init__文件,这个文件储存对外提供的库的列表。
from . import xx
from . import xxx
这就叫包。
pycharm建包:右键-新建-python软件包。
numpy库:
n-dimension-array多维数组