python

目录
  • 问题
  • 编程基础
  • python多版本管理工具---Pyenv
  • pip包管理器
  • Python基础语法
  • 内置数据结构
  • python的进程和线程

问题

Linux Centos7之由Python2升级到Python3

https://baijiahao.baidu.com/s?id=1650799838552962991&wfr=spider&for=pc


vs code 中 pylint(语句不自动检测)

(Settings)设置

关闭此项的默认值(取消掉打勾)
python.linting.pylintUse MinimalCheckers

使用安装解释器的操作系统上的,绝对路径
python.linting.pylintPath
/root/.local/lib/python3.6/site-packages/pylint

python.pythonPath
/usr/bin/python3

编程基础

编程基础

程序是什么
什么是计算机语言
什么是机器语言
什么是汇编语言
什么是电子计算机
现代计算机是怎么产生的
什么是冯诺依曼体系架构
语言分类,什么是低级语言
语言分类,什么是高级语言
低级语言到高级语言
高级语言的发展过程,非结构化语言
高级语言的发展过程,结构化语言
高级语言的发展过程,面向对象语言
高级语言的发展过程,函数式语言
静态编译语言
动态编译语言
强类型语言
弱类型语言
Python的语言类型
进制
表达式Expression
内存管理
程序控制
原码
反码
补码
负数表示法
程序的特点
写程序难点
Python解释器有哪几种

程序是什么

---

一组能让计算机识别和执行的指令

---

回去

什么是计算机语言

---

人与计算机之间交互的语言

---

回去

什么是机器语言

---

1、一定位数组成二进制的0和1的序列,称为机器指令。机器指令的集合就是机器语言

2、与自然语言差异太大,难学、难懂、难写、难记、难查错

---

回去

什么是汇编语言

---

1、用一些助记符号替代机器指令,称为汇编语言。ADD A,B 指的是将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中

2、汇编语言写好的程序需要汇编程序转换成机器指令

3、汇编语言只是稍微好记了些,可以认为就是机器指令对应的助记符。只是符号本身接近自然语言

---

回去

什么是电子计算机

---

1、够执行程序的机器

---

回去

现代计算机是怎么产生的

---

1、艾伦·麦席森·图灵(Alan Mathison Turing,1912年6月23日-1954年6月7日),英国数学家、逻辑学家,被称为计算机科学之父,人工智能之父。图灵提出的著名的图灵机模型为现代计算机的逻辑工作方式奠定了基础

2、冯·诺依曼著名匈牙利裔美籍犹太人数学家、计算机科学家、物理学家和化学家 ,数字计算机之父。他提出了以二进制作为数字计算机的数制基础,计算机应该按照程序顺序执行,计算机应该有五大部件。

---

回去

什么是冯诺依曼体系架构

---

1、艾伦·麦席森·图灵(Alan Mathison Turing,1912年6月23日-1954年6月7日),英国数学家、逻辑学家,被称为计算机科学之父,人工智能之父。图灵提出的著名的图灵机模型为现代计算机的逻辑工作方式奠定了基础

2、冯·诺依曼著名匈牙利裔美籍犹太人数学家、计算机科学家、物理学家和化学家 ,数字计算机之父。他提出了以二进制作为数字计算机的数制基础,计算机应该按照程序顺序执行,计算机应该有五大部件。

---

回去

什么是冯诺依曼体系架构

---

1、CPU由运算器和控制器组成

2、运算器,完成各种算数运算、逻辑运算、数据传输等数据加工处理

3、控制器,控制程序的执行

4、存储器,用于记忆程序和数据,例如内存

5、输入设备,将数据或者程序输入到计算机中,例如键盘、鼠标

6、输出设备,将数据或程序的处理结果展示给用户,例如显示器、打印机等

7、CPU中还有寄存器和多级缓存Cache

---

回去

语言分类,什么是低级语言

---

1、面向机器的语言,包括机器语言、汇编语言

2、不同的机器不能通用,不同的机器需要不同的机器指令或者汇编程序

---

回去

语言分类,什么是高级语言

---

1、接近自然语言和数学语言的计算机语言

2、高级语言首先要书写源程序,通过编译程序把源程序转换成机器指令的程序

3、1954年正式发布的Fortran语言是最早的高级语言,本意是公式翻译

4、人们只需要关心怎么书写源程序,针对不同机器的编译的事交给编译器关心处理

---

回去

低级语言到高级语言

---

1、语言越高级,越接近人类的自然语言和数学语言

2、语言越低级,越能让机器理解

3、高级语言和低级语言之间需要一个转换的工具:编译器、解释器

4、C、C++等语言的源代码需要本地编译

5、Java、Python、C#的源代码需要被解释器编译成中间代码(Bytecode),在虚拟机上运行

6、编译语言,把源代码转换成目标机器的CPU指令

7、解释语言,解释后转换成字节码,运行在虚拟机上,解释器执行中间代码

---

回去

高级语言的发展过程,非结构化语言

---

1、编号或标签、GOTO,子程序可以有多个入口和出口

2、有分支、循环

---

回去

高级语言的发展过程,结构化语言

---

1、任何基本结构只允许是唯一入口和唯一出口

2、顺序、分支、循环,废弃GOTO

---

回去

高级语言的发展过程,面向对象语言

---

1、更加接近人类认知世界的方式,万事万物抽象成对象,对象间关系抽象成类和继承

2、封装、继承、多态

---

回去

高级语言的发展过程,函数式语言

---

1、古老的编程范式,应用在数学计算、并行处理的场景。引入到了很多现代高级语言中

2、函数是“一等公民”,高阶函数

---

回去

静态编译语言

---

1、实现声明变量类型,类型不能再改变

2、编译时检查

静态编译语言最大的特点,要求所有的变量,必须声明他的类型,(事先声明标识符的类型,数值就是数值,字符串就是字符串,声明后不可以交叉赋值)

---

回去

动态编译语言

---

1、不用事先声明类型,随时可以赋值为其他类型

2、编程时不知道是什么类型,很难推断

---

回去

强类型语言

---

1、不同类型之间操作,必须先强制类型转换为同一类型。print('a'+1)

---

回去

弱类型语言

---

1、不同类型间可以操作,自动隐式转换,JavaScript中console.log(1+'a')

---

回去

Python的语言类型

---

Python是动态语言,强类型语言

---

回去

进制

---

介绍
    常见进制有二进制,八进制,十进制,十六进制,应该重点掌握二进制,十六进制
        十进制逢十进一;十六进制逢十六进一;二进制逢二进一

    0b二进制,b表示Binary(二进制)
    0o八进制,o表示Octal(Octal)(八进制用的少,一般在linux权限时使用)
    0x十六进制,x表示Hex(十六进制)

转换
    转为十进制---按位乘以权累加求和
        0b1110计算为 1*2**3 + 1*2**2 + 1*2**1 + 0*2**0 = 14
          1110权重分布(从右往左计算0=0次方,1=1次方,1=2次方,1=3次方)
                    1(是二进制从左到右的第一位,权重计算从0次方开始计算,)
                      2**3(权重,二进制的3次方,)

        0x41计算为4 * 16 + 1 * 1 = 65
          41权重分布(从右往左计算1=0次方,4=1次方)
                 4(是十六进制从左到右的第一位)
                     16**1(权重,十六进制的1次方)
         
         0o111计算为1 * 8 ** 2 + 1 * 8 ** 1 + 1 * 8 ** 0 = 73

    十进制转换回对应的进制---按要转换的进制(十六进制就除以16,二进制就除以2)
        十进制转换二进制,2除以十进制,除不进为1,除尽为0,结果从下往上
        十进制转换十六进制,16除以十进制,能除的数和余数为十六进制
   
    转为二进制
        0xF8按位展开即可,得到0b1111 1000
        127除以基数2,直到商为0为止,反向提取余数

    转为十六进制
        127除以基数16,直到商为0为止,反向提取余数

示例
    二进制转十进制
        1    0    0    1
        8 +  4 +  2 +  1 = 15(转换为十进制为15)

    十六进制转二进制
        0x    7    F
        0 1 1 1    1 1 1 1    (bytes 1个字节 = 8位 1位只能表示0、1,十六进制每4位一段)
          4+2+1=7  8+4+2+1=15(十六进制逢16进一,F表示十六进制最大数15)
            
---

回去

表达式Expression

---

介绍:
    由数字、符号、括号、变量等的组合
        算数表达式
            算数运算,加减乘除,位或异或,都是算数表达式

        逻辑表达式
            and、or、not是逻辑表达式

        赋值表达式
            谁等于谁,这是赋值表达式
            python中、赋值即定义,如果一个变量已经定义,赋值相当于重新定义
具体实现:

---

回去

内存管理

介绍

    变量无须事先声明,也不需要指定类型,动态语言的特性

    python编程中一般无须关心变量的存亡,也不用关心内存的管理

    python使用引用计数记录所有对象的引用数
        当对象引用数变为0,它就可以被 垃圾回收GC(GC叫垃圾回收)
        计数增加:
            赋值给其它变量就增加引用计数,例如x=3;y=x;z=[x,1]
            实参传参,如foo(y)
        计数减少:
            函数运行结束时,局部变量就会被自动销毁,对象引用计数减少
            变量被赋值给其它对象。例如x=3;y=x;x=4

    有关性能的时候,就需要考虑变量的引用问题,但是该释放内存,还是尽量不释放内存,看需求


具体实现

python是一门动态语言,运行在python虚拟机之上的,运行时某些特点很像java,
    这些特点是,所有的变量不需要我们清除,他可以帮你自动清除
                解决内存碎片,内存碎片的意思的,当内存中的单个空间被释放掉以后,于附近的空间不连续,(空的都空,有数据的都有数据)这个单独的被释放掉的空间叫做也叫内存空洞,如果有一批需求(比如数据结构,数据结构需要在内存中连续的排放)需要一片连续的内存空间,但发现内存总容量够,但是无法安排,这个时候内存资源在但是程序运行不了,开辟不了内存

    c或c++的特点,比如要在内存放数据,内存的开辟,需要自己开辟空间,有可能自己开辟的空间不回收,造成了内存的大量浪费,内存在不用的时候一定要释放掉,否者内存空间可能不够,
                                                             ,还有可能
    
    python和java的特点,他使用了一套引用计数记录机制,他能把这些所谓的不用的对象(我们称为垃圾)它可以用垃圾回收机制把这些垃圾回收掉,这个机制存在的原因就是怕你不释放,帮你释放,解决内存空间的问题,第二个他解决内存碎片,把那些长久不用的垃圾释放掉,把那些长久保留的数据,向某一个地方排列好,这样的好处就是出现了一个大段的连续的内存空间
        垃圾回收机制需要解决两个问题
            第一谁是垃圾,第二如何规整
               我们用的是变量指向的数据,他对这个数据会做计数,用1次加1,不用他就会想办法减1,当这个数减为0的时候他就是垃圾,但并不代表他是垃圾我就要立即处理,因为如果时刻处理内存中的垃圾,会导致内存的规整过程,内存的规整过程整个应用程序是不能动的,可以理解为正在打扫房间,请客人不要住了,他会在合适的时间规整内存时,清理计算为0的垃圾

        引用计数如何增加                     
import sys    sys非常底层的系统库,不管用不用,python解释器启动的时候必须加载这个库,不加载他跑不起来

x = []    赋值的过程就是一个对象被人记住了一次引用,此时引用计数为1

y = x    此时引用计数为2

z = x    此时引用计数为3

a = z    此时引用计数为4
    #变量本身就是一个标识符(名字)他的作用就是指向一个值,这就是那么多都记住了同一个值

print(sys.getrefcount(x))    getrefcount得到一个变量所指向的对象的引用计数。(x)实参传入,在传入的时候他的引用计数会加1

5    打印出来引用计数为5

---

x = []    赋值的过程就是一个对象被人记住了一次引用,此时引用计数为1

y = x    此时引用计数为2

z = x    此时引用计数为3

a = z    此时引用计数为4

x = 1    此时x不跟他们玩了
y = 2    此时x不跟他们玩了

print(sys.getrefcount(a))
4    打印出来引用计数为4,x不引用减1,当所有人都忘记这个值的时候,引用计数为0就会被当作垃圾回收

print(sys.getrefcount(x))    1是数值是常量,不光你用,解释器也需要1,不需要有很多份,内存很宝贵的就这一份,被引用了多少次谁也不知道
810
print(sys.getrefcount(y))    2是数值是常量常量,,不光你用,解释器也需要1,不需要有很多份,内存很宝贵的就这一份,被引用了多少次谁也不知道
101

b = [x]    列表是个箱子,把常量放在箱子里,这就是引用了,引用就可以加1
print(sys.getrefcount(y))
102
b = [x,1],在箱子里引用两次
print(sys.getrefcount(y))
104


回去

程序控制

---
介绍:
    在结构化编程中有三种

    顺序
        按照先后顺序一条条执行
            例如,先洗手,再吃饭,再洗碗

    分支
        根据不同的情况判断,条件满足执行某条件下的语句,分支只能执行其中的一个
            例如,先洗手,如果饭没有做好,玩游戏,如果饭做好了,就吃饭,如果饭都没有做,叫外卖

    循环
        条件满足就反复执行,不满足就不执行或不再执行
            例如,先洗手,看饭好了没有,没有好,一会来看一次是否好了,一会儿来看一次,直到饭好了,才可以吃饭。这里循环的条件是饭没有好,饭没有好,就循环的来看饭好了没有。(注意循环条件)


---

回去

原码

---

介绍:
    原码是给人看的,人容易理解但计算机不喜欢

具体实现:
00000001 +1 原码,反码,补码做加法都是一样的

10000001 -1 原码,左边第一位1表示负数符号,有效变化有255缩小位127,

5 => 0b101

1 => 0b1 

-1 => -0b1

bin(-1)    bin函数查看可以

---

回去

反码

---

介绍:
    了解补码,需要先了解反码
具体操作:
1    0000001
1    1111110 -1 反码,逐位取反
符号位
正数的反码与原码相同
负数的原码符号位不变其余按位取反


回去

补码

---

介绍:
    计算机喜欢补码

具体操作:
符号位
1    0000001
1    1111110 -1 反码,逐位取反
1    1111111 -1 补码,负数的反码符号位不变,其余按位取反,最后加1,在内存中16位FF显示,一个字节一个字节显示,内存中实际表现的1就是00000001,-1就是11111111

正数的补码与原码相同
负数的反码符号位不变其余按位取反后+1
补码在补码就是负数的原码,原码给人看的

示例:
5 - 1 = 5+(-1)    计算机中减法就是使用加法进行计算

5+(-1)
 00000101    5
 11111111 +   -1 这是二进制加法,需要进位
 --------------
100000100    4
 00000100    这是1字节的8位,超出1字节的叫溢出位,溢出位直接丢弃

10001010    <补码在补码    11110110=64   +   32   +   16   +   4   +   2=118符号位在需要补负号-118
1           1   1   1   0   1   1   0
符号位      64  32  16  8   4   2   0

000
---

回去

负数表示法

---
介绍:

    1、数字电路的CPU中的运算器实现了加法器,但是没有减法器,减法是转换成加法

    2、负数在计算机中使用补码存储,-1的补码为1111 1111

    3、5-1 => 5+(-1)直觉上是0b101-0b1,其实计算机中是0b101+0b11111111,溢出位舍弃

    4、~12为什么是-13? 

    5、 10^9 等于? 10^-9等于?为什么

具体操作:
4、~12为什么是-13? 
 ~12    ~按位取反
00001100    12
11110011    表示的时候,计算机发现,最高位是1,计算机当作负数处理,认为是负数的补码
1    0001101    -0x0d    -13    符号位不变,补码最后加1,补码的补码就是原码
符号位

5、 10^9 等于? 10^-9等于?为什么
10 ^ 9
1010
1001
-----
0111
7

---

回去

程序的特点

---

1、算法 + 数据结构 = 程序

2、数据一切程序的核心

3、数据结构是数据在计算机中的类型和组织方式

4、算法是处理数据的方式,算法有优劣之分

---

回去

写程序难点

---

1、理不清数据

2、搞不清处理方法

3、无法把数据设计转换成数据结构,无法把处理方法转换成算法

4、无法用设计范式来进行程序设计

5、世间程序皆有bug,但不会debug

---

回去

Python解释器有哪几种

---

1、官方CPython --- C语言开发,最广泛的Python解释器

2、IPython --- 一个交互式、功能增强的Cpython

3、PyPy --- Python语言写的Python解释器,JIT技术,动态编译Python代码

4、Jython --- Python的源代码编译成Java的字节码,跑在JVM上

5、IronPython --- 与Jython类似,运行在.Net平台上的解释器,Python代码被编译成.Net的字节码

---

回去

python多版本管理工具---Pyenv

Pyenv

Pyenv作用

Pyenv作用


介绍:
    可以实现多python解释器版本管理。多版本之间切换,避免开发环境出现版本冲突,版本之间互相隔离

具体实现:
    比如可以实现一个目录使用一个版本的python解释器

回去

pip包管理器

pip

pip作用
pip使用和配置

pip作用


介绍:
    python程序包管理的命令,类似于linux下的yum

具体实现:
    软件包如何安装,几乎所有的包都是从https://pypi.org这个网站来的

回去

pip使用和配置

---

命令:
    pip3 install xxx yyy
    pip3 list
        提示警告,这个情况一般是pip9会有警告,使用python -m pip install --upgrade pip升级

    #注意:python3默认没有pip,默认使用pip3

pip通用配置:
    linux下
        $vim ~/.pip/pip.conf    #没有此目录就手动创建    

[global]    #全局
index-url = https://mirrors.aliyun.com/pypi/simple/    #国内的源一般用阿里的

[install]
trusted-host=mirrors.aliyun.com

    windeows下
        windeows放在~/pip/pip.ini    #文件名不一样,配置内容一样

---

具体实现:
    安装一个IPython jupyter 

介绍
    IPython
        增强的Python Shell,自动补全,自动缩进,支持shell,增加了很多函数
    jupyter 
        他从IPython中独立出来的项目,独立的交互式笔记本,后台使用IPthon,快捷键:shift + Enter、Ctrl + Enter、dd、m

实现过程:

pip3 list
    pip (9.0.3)    #包管理工具
    setuptools (39.2.0)    #安装用的
    注意:这两个包是python环境必须有的,可以当作不存在,我们一个第三方包都没用,只有python的默认标准库

pip3 install ipython

pip3 install jupyter    #默认会自动安装ipython

jupyter notebook
    注意windows有默认浏览器会自动转跳,输入密钥,也可以给定密码jupyter notebook -h使用帮助

回去

Python基础语法

Python基础语法

注释
数据类型,数值型
数据类型,字符串
转义字符
缩进
续行
标识符
常量
字面常量
变量
算数运算符
位运算符
比较运算符
逻辑运算符
赋值运算符
成员运算符
身份运算符
程序控制,单分支结构
程序控制,多分支结构
程序控制,分支嵌套
分支练习
循环——while语句
循环——for语句*
循环——continue、break语句
循环——else子句
循环练习

注释

介绍

python使用#(井号)开始,井号之后都是注释

回去

数据类型,数值型

介绍

python中数字分为 整数 和 浮点数 和 复数

回去

整数

介绍

Python3开始不区分long(长整形)和int(短整形),long被重命名为int,所以只有int了,所以说python3中这个整型可以很大很大,一直放到内存放不下为止,其他语言是分字节描述的,超过这个字节直接爆掉,抛异常

进制0xa、0o10、0b10,需要掌握,
0b二进制,b表示Binary(二进制)
0o八进制,o表示Octal(Octal)
0x十六进制,x表示Hex(十六进制)

整型中还存在bool型,2个值True、False,能行 还是 不能型,是不是用0 和 1,也可以表示开和关,bool型实际上是整形的子类,他就是整形,只不过是整形中的特殊的类型而已


回去

浮点数

介绍

浮点型的意思是,存储空间还是这么大,但是他的小数点一直在变化,要么保证数值特别大,要么保证小数点后面的位数特别多,意思是保证他的精度,一般情况下在做工程计算的时候,对小数点的位数有要求的时候,必须使用这个带精度的

精度也分双精度和单精度,但是python不管那么多,他使用的是c语言的double类型(双精度),可以理解为精度非常高,他描述的数据非常大


回去

复数

介绍

复数,1+2j

回去

数据类型,字符串

介绍

使用 ' " 单双引号引用的字符的序列

'''和""" 单双三引号,可以跨行、可以在其中自由的使用单双引号

r前缀:在字符串前面加上r或者R前缀,表示该字符串不做特殊的处理

f前缀:3.6版本开始,新增f前缀,格式化字符串


回去

转义字符

表达符号

\\    \t    \r    \n    \'    \"


具体操作

\\ 表示\没有特殊转义的意义,当作字符串存在
\t 表示Tab键
\r 表示换行符,在某些操作系统下比如windoes为换行符
\n 表示换行符
\' 表示'不是界定符,作为字符串存在
\" 表示'不是界定符,作为字符串存在

前缀r,把引号里面的所有字符(包括转义符)当普通字符对待
比如print(r"c:/ntc"),否则他会把\n当作换行符处理,在处理路径的时候会出现问题

回去

缩进

介绍

未使用C等语言的花括号,而是采用缩进的方式表示层次关系

约定使用4个空格缩进

回去

续行

介绍

字符串在引号内使用,在行尾使用 \,后面不能有任何字符,空白符号也不行

如果使用各种括号,认为括号内是一个整体,内部跨行不用 \

回去

标识符

介绍

1、一个名字,用来指代一个值,比如变量名

2、只能字母、下划线和数字

3、只能以字母或下划线开头,注意在python中下划线开头的标识符有特殊意义不能乱用,

4、不能是python的关键字,例如def、class关键字就不能作为标识符

5、Python是大小写敏感的

回去

常量

介绍

常量表示,一旦赋值就不能改变值的标识符,标识符(变量名)关联的对象(赋的值)不能在被改变了,这就叫常量

python中无法定义常量,在python中任何东西都可以改,一旦赋值后他就是一个变量,变量中的值随时可以该,灵活但是不安全

回去

字面常量

介绍

    赋值给变量名的值,他就是字面常量,是啥就是啥
    一个单独的量(字面意义),例如 12(12就是12)、"abc"(abc就是abc) 、'2341356514.03e-9'

回去

变量

介绍

    赋值后,可以改变值的标识符(变量名)就是 变量

回去

算数运算符

表达符号

    +    -    *    /    %    **    //


具体操作

**     平方

%    取模(取余),可以与2取模做奇数判断,9 % 2 = 1,结果为1就是奇数,结果为0就是偶数

//    整除向下取整数
print(5//2),除法结果是2.5向下取比2.5小的整数,就是2
2
print(-(5//2)),-单目运算符,先处理括号内的
-2
print(-5//2),除法结果是-2.5向下取比-2.5小的整数,就是-3
-3

整除数和取模可以得到 除法的商,和余数

回去

位运算符

介绍

    位运算,不管用什么描述,十进制还是十六进制,在位运算这里都是按照二进制的位进行计算,


表达符号

    &    |    ~    ^    <<    >>


具体操作

        &    位与,按每一位相乘,每一位只有0和1,1*1=1,1*0=0,0*0=0,0乘任何数都得0,可以与1位与做奇数判断9 & 1 = 1,结果为1就是奇数,结果为0就是偶数
            9 & 8 = 8
            1 0 0 1    9
            1 0 0 0 &    8
        ---------------
            1 0 0 0    8

        |    位或,按每一位相或(或是+(加))1+1=1,1+0=1,0+0=0
            9 | 8 = 8
            1 0 0 1    9
            1 0 0 0 &    8
        ---------------
            1 0 0 1    9

        ~    


        ^    异或,相异除1,相同除0
            9 ^ 8 = 1
            1 0 0 1    9
            1 0 0 0 ^    8
        ---------------
            0 0 0 1    1 


            1 0 0 1    9
            1 0 0 0 同或    8    同或,同或标识符⊙。(圆圈内为点),相同除1,相异除0,异或用的多
        ---------------
            1 1 1 0    1 

        >>    右移动运算符,只要是位就是二进制
            8 >> 3 = 1
            1 0 0 0    8     >>二进制右移三位
                    3>>
        --------------
                  1

        <<    左移动运算符,
            1 << 3 = 8
                  1
                    <<3    向后补零
        --------------
            1 0 0 0    8

回去

比较运算符

介绍

    比较运算,谁大于谁,谁小于谁


表达符号

    ==    !=    >    <    >=    <=


具体操作

    ==    =号是赋值,==就是比较
        1 == 1吗 = True    返回值是bool型

    !=    !=就是不等于
        1 != 1吗 = False    返回值是bool型

    >    大于
        b = 5
        10 > b and b > 3 = True,and表示条件是否同时成立,and表示乘法10 > 1表示True(1),b > 3表示True(1)    1 * 1 = 1

        b > 10 or b > 3 = True,and表示条件是否同时成立,or表示加法b > 10表示False(0),b > 3表示True(1)    0 = 1 = 1


回去

逻辑运算符

介绍

   与    或    非


表达符号

    and    or    not


具体操作

   短路运算符
        and 如果第一个表达式为False,后面就没有必要计算了,这个逻辑表达式一定是False

        or 如果第一个表达式True,后面没有必要计算了,这个逻辑表达式一定是True


回去

赋值运算符


介绍

   赋值运算符,a = min(3,5)特点先计算右边,然后将结果跟前面的“标识符”关联起来


表达符号

    =    +=    -=    *=    /=    %=    等


具体操作

    b += 1     #等价b = b + 1 ,赋值语句,赋值即重新定义

回去

成员运算符

表达符号

   in    not in

回去

身份运算符

表达符号

   is    is not


总结

    运算符规律(符号的优先级)
        算数运算符 > 位运算符 > 身份运算符 > 成员运算符 > 逻辑运算符

        单目 > 双目    单目就是-5操作一个操作数叫单目,5-3操作两个操作数的叫双目

        记不住,用括号

        长表达式,多用括号,易懂、易读

回去

程序控制,单分支结构

具体操作

    if语句
        if condition:
            代码块
        condition必须是一个bool类型,这个地方有一个隐式转换bool(condition)
        if 1<2: #if True:
            print('1 less than 2')


代码块

        类似于if语句的冒号后面的就是一个语句块
        在if、for、def、class等

回去

程序控制,多分支结构

具体操作

    if...elif...else语句
        if condition1:
            代码块1
        elif condition2:
            代码块2
        elif condition3:
            代码块3
        ......
        else:
            代码块


举例

a = 5
if a<0:
    print('negative')
elif a==0:
    print('zero')
else:
    print('positive')

回去

程序控制,分支嵌套


介绍

    嵌套结构,可以是分支、循环的嵌套
    可以互相嵌套多层

    多分支结构,只要有一个分支被执行,其他分支都不会被执行
    前一个条件被测试过,下一个条件相当于隐含着这个条件

具体操作

score = 80
if score<0:    条件为真进入代码块,如果不是布尔值,可以是等效
    print('wrong')
else:
    if score==0:
        print('egg')
    elif score <= 100:
        print('right')
    else:
        print('too big')


等效真值表,根据判断为真就可以进入代码块

    ""          假    |    False等价布尔值,相当于bool(value)
    "string"	真    |        空容器
    0           假    |            空集合
    >=1         真    |            空字典
    <=-1	真    |            空列表
    ()空元组	假    |            空元组
    []空列表	假    |        空字符串
    {}空字典	假    |        None对象    特殊值,什么都没有
    None        假    |        0


回去

分支练习


练习一:

输入2个数字,输出最大数,使用input函数
a = int(input("请输入第一个数:"))
b = int(input("请输入第二个数:"))

if a >= b:
    if a == b:
        print("%d == %d" % (a,b))
    else:
        print("%d > %d" % (a,b))
else:
    print("%d < %d" %(a,b))

练习二:

给定一个不超过5位的正整数,判断其有几位
val = input('>>>')
val = int(val)
if val >= 1000: #fold
    if val>=10000:
        print(5)
    else:
        print(4)
else:
    if val>=100:
        print(3)
    elif val >= 10:
        print(2)
    else:
        print(1)

回去

循环——while语句


介绍

    语法
        while condition:
            block

    当条件满足即condition为True,进入循环体,执行block(语句块)

举例
flag=10
while flag:
    print(flag)
    flag -= 1

执行结果是什么?为什么?
如果flag=-10可以吗?如何改造?


回去

循环——for语句*


介绍

    语法
        for element in iteratable:
            block

        当(iteratable)可迭代对象中有元素可以迭代(一个个去拿出来),进入循环体,执行block(语句块)

range函数

 可迭代对象是惰性的,只有在遍历的时候出元素,所以要用for循环

    for i in range(10):    #(0,10)从0开始到10stop,结果0-9,左闭右开的原则,10包含0-9,range当作计数器
    
    for i in range(1,11):    #(1,11)从1start到10stop,结果1-10

    for i in range(1,11,2):    #(1,11)从1start到10stop,2是步长,结果1,3,5,7,9

    for i in range(11,1,-2):    #(11,1)从11start到1stop,默认读取是正向的,11到1是不可能的不会输出,需要加上步长,使用负步长反向读取,结果11,9,7,5,3

举例

    打印1~10
        for i in range(10):
            print(i+1)

        执行结果是什么?为什么?
        如果想倒序打印呢?

    打印1~10的偶数
        for i in range(11):
            if  i % 2:    #取模后结果为0,0为假,不执行语句块,不打印,结果为1的值进行打印
                print(i)    #结果取出的都是质数

        for i in range(11):
            if not i % 2:    #取模为0的为真,加上not,取模为0的为真,打印取模为0的值
                print(i)    #结果取出的都是偶数

        for i in range(11):
            if not i & 1:    #与1做位与
                print(i)    #结果取出的都是偶数

        for i in range(0,10,2):    #使用步长取偶数,使用步长迭代次数更少,迭代5次,不用做运算,效率更高


回去

循环——continue、break语句

总结


continue和break是循环的控制语句,只影响当前循环,包括while、for循环

如果循环嵌套, continue和break也只影响语句所在的那一层循环

continue和break 不是跳出语句块,所以 if cond: break 不是跳出if,而是终止if外的break所在的循环


循环——continue语句

介绍:
    中断当前循环的当次执行,继续下一次循环

举例:
    计算10以内的偶数(for循环)
        for i in range(0,10,2):
            print(i)

        for i in range(0,10):
            if i & 1:
                continue
               print(i)


循环——break语句

介绍:
    终止当前循环

举例:
    计算1000以内的被7整除的前20个数(for循环)
        count = 0
        for i in range(0,1000,7):
            print(i)
            count += 1
            if count >= 20:
                break


循环--else子句

介绍:
    如果循环正常的执行结束,就执行else子句,即使循环都没有进去
    如果使用break终止,else子句不会执行

语法:
    while condition:
        block
    else:
        block
    for element in iteratable:
        block
    else:
        block


回去

循环练习

计算100以内的7的倍数

方法一:
for i in range(100):
    if i % 7:   #除不尽结果为1,条件为真,都打印出来
        print(i)    #不是我们想要的结果,7的倍数的值都条件为假没执行

for i in range(100):
    if i % 7 == 0 :     #i对7除尽并且等于0的,进行打印
        print(i)    #结果是我们想要的,都是7的倍数,应为都被7除尽了

方法二:
for i  in range(0,100,7):   #从0开始取步长为7的数,次方法处理这个效率最高
    print(i)

方法三,计算10000以内的7的倍数,只要前20个:
start=7
for i in range(20):     #循环20次,range只做计数器存在
    print(i,start)
    start +=7   #7的倍数有7相加运算得出

方法四:    
a = 1
for i in range(7,100000,7):
    print(i )
    if a == 5:
        break   #直接跳出循环体
    a += 1


给定一个不超过5位的正整数,判断该数的位数,依次打印出个位、十位、百位、千位、万位的数

方法一:
num = 12345
num = int(12345)

w = 10000
for i in range(5): 
    print(num // w )
    num = num % w
    w = w // 10

方法二:
num = int(54321)

for i in range(5):
    c = num // 10
    print(num - c * 10)
    num = c

方法三:


val = input('>>>')
val = int(val)
print(val)
if val >= 1000: # 折半
    if val>=10000:
        num = 5
    else:
        num = 4
else:
    if val>=100:
        num = 3
    elif val >= 10:
        num = 2
    else:
        num = 1
print(num)
c = val
for i in range(num):
    n = c // 10
    print(c - n*10)
    c = n # 如果打印顺序是从万位到个位,如何实现

算法:
假设输入为54321
第一趟:54321 // 10 = 5432
54321 - 543210 = 1
第二趟:5432 // 10 = 543
5432 - 54310 = 2
依次类推

方法四:
num = int("001230")
length = 5
w = 10000
flag = False

count = 0
while w:
    t = num // w
    if not flag:
        if t :
            flag = True
        else:
            length -= 1
    if  flag :
        print(t)
        count += 1
    num = num % w
    w = w // 10
print(length, '~~~~~~~~~~~')
print("count =",count)



val = input('>>>')
val = int(val)
print(val)
if val >= 1000: # 折半
    if val>=10000:
        num = 5
    else:
        num = 4
else:
    if val>=100:
        num = 3
    elif val >= 10:
        num = 2
    else:
        num = 1
print(num)
pre = 0
for i in range(num,0,-1):
    cur = val//(10**(i-1))
    print(cur - pre*10)
    pre = cur

算法:
假设输入为54321
第一趟:cur = 54321 // 10000 = 5
打印5 - 0
pre = 5
第二趟:cur = 54321 // 1000 = 54
打印54 - 5 * 10 = 4
pre = 54
第二趟:cur = 54321 // 100 = 543
打印543 - 54 * 10 = 3
pre = 543
依次类推


打印一个边长为n的正方形
要求:
    求100内所有奇数的和(2500) p 判断学生成绩,成绩等级AE。其中,90分以上为'A',8089分为'B',7079分为'C',6069分 为'D',60分以下为'E'
    求1到5阶乘之和
    给一个数,判断它是否是素数(质数)
        质数:一个大于1的自然数只能被1和它本身整除

方法一:
n = 5
print('*'*n)
for i in range(n-2):
    print('*'+' '*(n-2)+'*')
print('*'*n)

边为3,则 -1 0 1 => range(-1,2)
边为4,则 -2 -1 0 1 => range(-2,2)
边为5,则 -2 -1 0 1 2 => range(-2,3)
n = 5
e = -n//2
for i in range(e,n+e):
    if i == e or i == n+e-1:
        print('*'*n)
    else:
        print('*' + ' '*(n-2) + '*')


回去

内置数据结构

内置数据结构

随机数
数字的处理函数
列表list
元组tuple
集合set

随机数

介绍

random模块

randint(a,b)返回[a,b]之间的整数

choice(seq)从非空序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。random.choice([1,3,5,7])

randrange ([start,] stop [,step])从指定范围内,按指定基数递增的集合中获取一个随机数,基数的缺省值为1。random.randrange(1,7,2)

random.shuffle(list) -> None 就地打乱列表元素

sample(population,k)从样本空间或总体(序列或者集合类型)中随机取出k个不同的元素,返回一个新的列表
      random.sample(["a","b","c","d"],2)
      random.sample(["a","a"],2)会返回什么结果


回去

数字的处理函数

数字的处理函数

round(),四舍六入五取偶 # round()比较特殊,不但可以四舍五入,在5这里还可以向上取整,向下取整,原则就是离哪个偶数最近(4舍6入,5看整数部分靠近那个偶数,(2,偶数2),(3,偶数4)进到偶数)

floor()向下取整、ceil()向上取整  # ceil()最长用的,使用math模块(向上整,整数只要比整数部分大一点点就进制,比如2.1就进3)

int() 取整数部分  # int()最长用的

// 整除且向下取整 # //最长用的


min() #最小数
max() #最大数

bin(10) ,oct(10),hex(10) #返回的都是字符串

## 类型判断
type(obj) ,返回类型,而不是字符串

isinstance(obj, class_or_tuple),返回布尔值

举例:
type(a)
type('abc')
type(123)
isinstance(6, str) # 6是str吗,返回布尔值
isinstance(6, (str, bool, int)) # 6是其中一个类型吗,返回布尔值

type(1+True)
type(1+True+2.0) # 是什么?隐式转换

回去


列表list

介绍

一个队列,一个排列整齐的队伍

列表内的个体称作元素,由若干元素组成列表

元素可以是任意对象(数字、字符串、对象、列表等)

列表内元素有顺序,可以使用索引

线性的数据结构

使用 [ ] 表示

列表是可变的

列表list、链表、queue、stack的差异


示例

list() -> new empty list

list(iterable) -> new list initialized from iterable's items

列表不能一开始就定义大小

#空列表
l1 = list()
l2 = []

# 列表中多个元素
l3 = [2, 6, 9, 'ab']
l4 = list(range(5)) # for循环,将里面的元素一个个拿出来,装进列表当中
l5 = [1,'ab',True,None,[4,5,'abc'],str] #合法的都可以往里装

列表list、链表、queue、stack的差异


列表索引访问

索引,也叫下标
正索引:从左至右,从0开始,为列表中每一个元素编号
负索引:从右至左,从-1开始
正负索引不可以超界,否则引发异常IndexError
为了理解方便,可以认为列表是从左至右排列的,左边是头部,右边是尾部,左边是下界,右边是上界

列表通过索引访问
      list[index] ,index就是索引,使用中括号访问


列表查询

index(value,[start,[stop]])
      通过值value,从指定区间查找列表内的元素是否匹配
      匹配第一个就立即返回索引
      匹配不到,抛出异常ValueError

count(value)
      返回列表中匹配value的次数

时间复杂度
      index和count方法都是O(n) # n是元素的数量,大On表示遍历所有元素消耗的时间
      随着列表数据规模的增大,而效率下降

如何返回列表元素的个数?如何遍历?如何设计高效?
      len() # O(1),长度属性,加元素+1,减元素-1


列表元素修改

索引访问修改
      list[index] = value
      索引不要超界


列表增加、插入元素

append(object) -> None # -> None返回值
      列表尾部追加元素,返回None
      返回None就意味着没有新的列表产生,就地修改
      时间复杂度是O(1)

insert(index, object) -> None
      在指定的索引index处插入元素object
      返回None就意味着没有新的列表产生,就地修改
      时间复杂度是O(n)
      索引能超上下界吗?
            超越上界,尾部追加
            超越下界,头部追加

extend(iteratable) -> None
      将可迭代对象的元素追加进来,返回None
      就地修改

+ -> list
      连接操作,将两个列表连接起来
      产生新的列表,原列表不变
      本质上调用的是__add__()方法

* -> list
      重复操作,将本列表元素重复n次,返回新的列表
            列表 *重复的坑
            * -> list
                  重复操作,将本列表元素重复n次,返回新的列表
                  x = [[1,2,3]]*3
                  print(x)
                  x[0][1] = 20
                  print(x)

                  y = [1]*5
                  y[0] = 6
                  y[1] = 7
                  print(y)
                  上面代码运行结果是什么?为什么?


列表删除元素

remove(value) -> None
      从左至右查找第一个匹配value的值,移除该元素,返回None
      就地修改
      效率?

pop([index]) -> item
      不指定索引index,就从列表尾部弹出一个元素
      指定索引index,就从索引处弹出一个元素,索引超界抛出IndexError错误
      效率?指定索引的的时间复杂度?不指定索引呢?

clear() -> None
      清除列表所有元素,剩下一个空列表


列表其它操作

reverse() -> None
      将列表元素反转,返回None
      就地修改
      效率不高

sort(key=None, reverse=False) -> None
      对列表元素进行排序,就地修改,默认升序
      reverse为True,反转,降序
      效率不高
      key一个函数,指定key如何排序 # key仅仅用在比较时,不转换类型
            lst.sort(key=functionname)

in
      [3,4] in [1, 2, [3,4]]
      for x in [1,2,3,4]


列表复制

先看一段代码
      lst0 = list(range(4))
      lst2 = list(range(4))
      print(lst0==lst2)
      lst1 = lst0
      lst1[2] = 10
      print(lst0)

lst0==lst2相等吗?为什么?lst0里面存的是什么?
请问lst0的索引为2的元素的值是什么?
请问lst1 = lst0这个过程中有没有复制过程?

copy() -> List
      shadow copy返回一个新的列表

lst0 = list(range(4))      lst0 = [1, [2, 3, 4], 5]
lst5 = lst0.copy()         lst5 = lst0.copy()
print(lst5 == lst0)        lst5 == lst0
lst5[2] = 10               lst5[2] = 10
print(lst5 == lst0)        lst5 == lst0
                           lst5[2] = 5
                           lst5[1][1] = 20
                           lst5 == lst0

lst0和lst5一样吗?     
对比左右程序的差别     

shadow copy
      影子拷贝,也叫浅拷贝,遇到引用类型,只是复制了一个引用而已

深拷贝
      copy模块提供了deepcopy
            import copy
            lst0 = [1, [2, 3, 4], 5]
            lst5 = copy.deepcopy(lst0)
            lst5[1][1] = 20
            lst5 == lst0 
                        

回去


集合set

介绍

约定
      set 翻译为集合
      collection 翻译为集合类型,是一个大概念

set
      可变的、无序的、不重复的元素的集合 # 注意集合的去重的能力,非常强大
      不可以索引,


举例

set() -> new empty set object
set(iterable) -> new set object

# 空集合
s1 = set()
s2 = {}  # 字典,空大括号被字典占用了

#集合多个元素
s3 = set(range(5))
s4 = set(list(range(10)))
s5 = {9,10,11,9} # set,9只出现一次,去重
s6 = {(1,2),3,'a'}
s7 = {[1],(1,),1} # ?



set的元素

set的元素要求必须可以hash

目前学过的不可hash的类型有list、set

元素不可以索引

set可以迭代


set增加

add(elem)
      增加一个元素到set中
      如果元素存在,什么都不做

update(*others)
      合并其他元素到set集合中来
      参数others必须是可迭代对象
      就地修改


set删除

remove(elem)
      从set中移除一个元素
      元素不存在,抛出KeyError异常。为什么是KeyError?

discard(elem)
      从set中移除一个元素
      元素不存在,什么都不做

pop() -> item
      移除并返回任意的元素。为什么是任意元素?
      空集返回KeyError异常

clear()
      移除所有元素


set修改、查询

修改
      要么删除,要么加入新的元素
      为什么没有修改?

查询
      非线性结构,无法索引

遍历
      可以迭代所有元素

成员运算符
      in 和 not in 判断元素是否在set中 
      效率呢?


set成员运算符的比较

list和set的比较
lst1 = list(range(100))
lst2 = list(range(1000000))
-1 in lst1、-1 in lst2 看看效率
set1 = set(range(100))
set2 = set(range(1000000))
-1 in set1、-1 in set2 看看效率


set和线性结构

线性结构的查询时间复杂度是O(n),即随着数据规模的增大而增加耗时

set、dict等结构,内部使用hash值作为key,时间复杂度可以做到O(1),查询时间和数据规模无关

可hash
      数值型int、float、complex
      布尔型True、False
      字符串string、bytes
      tuple
      None
      以上都是不可变类型,成为可哈希类型,hashable

set的元素必须是可hash的


回去


python的进程和线程

python的进程和线程

并发和线程

并发和线程


使用方法

# 开辟线程的模块threading

import threading
def foo(x,i=100):
    print(x,'test',i)

t = threading.Thread(target=foo,name='m1',args=(123,),kwargs={'i':200})
t.start()

# 创建了一个函数
# Thread是个函数,在threading模块内
# target= 这个线程调用的对象,可以使用foo(123)函数调用,直接传承,或者使用args=外部传参
# args= 为目标函数传递实参为一个元组 
# kwargs= 为目标函数传递实参为一个字典,表示传关键字参数 
# 线程传参本质上就是函数传参
# t.start() 启动这个线程

退出线程

import threading
def foo(x,i=100):
    while True:
        print(x,'test',i)

t = threading.Thread(target=foo,name='m1',args=(1,),kwargs={'i':200})
t.start()

# 死循环,线程无法退出,除非有退出条件或抛异常

import threading
def foo(x,i=100):
    count = 0
    while True:
        count += 1
        print(x,'test',i)
        if count >= 5:
            # break
            # raise Exception ('exit')
            return foo

t = threading.Thread(target=foo,name='mi',args=(1,),kwargs={'i':200})
t.start()

# 循环添加计数器
# bread 可以退出
# raise 抛出异常可以退出
# return 给函数返回值可以退出

# python线程没有提供退出线程的方法,除非线程内的代码正常执行完毕,或者raise抛出异常


threading模块的属性和方法
方法 作用 详细
threading.current_thread() 显示当前线程 可以区分各个线程,在函数内打印这个方法显示这个函数的的id号和name名字(current 当前,thread 线程)
threading.main_thread() 返回主线程 只用在返回主线程对象(main 主,thread 线程)
threading.main_thread() 返回主线程 只用在返回主线程对象(main 主,thread 线程)
threading.active_count() 返回当前存活(active 活动)的线程个数 (active 活动,count 个数)
threading.enumerate() 返回当前活着的线程对象 返回一个列表 (enumerate 枚举)
threading.get_ident() 只返回当前线程的id (get 得到,ident 身份)

threading.current_thread()


import threading
def foo(x,i=100):
    print('线程允许中,current_thread, foo',threading.current_thread())
    
    count = 0
    while True:
        count += 1
        print(x,'test',i)
        if count >= 5:
            # break
            # raise Exception('error')
            return foo

print('线程启用前,current_thread',threading.current_thread())

t = threading.Thread(target=foo,name='m1',args=(1,),kwargs={'i':200})
t.start()

print('线程结束后,current_thread',threading.current_thread())

# 结果
线程启用前,current_thread <_MainThread(MainThread, started 139900523468608)>
线程允许中,current_thread, foo 
线程结束后,current_thread <_MainThread(MainThread, started 139900523468608)>
1 test 200
1 test 200
1 test 200
1 test 200
1 test 200




import threading
def foo(x,i=100):
    print('current_thread, foo',threading.current_thread())
    print('main_thread, foo',threading.main_thread())
    print('active_count, foo',threading.active_count())
    print('enumerate(), foo',threading.enumerate())
    print('get_ident(), foo',threading.get_ident())
    
    count = 0
    while True:
        count += 1
        print(x,'test',i)
        if count >= 5:
            # break
            # raise Exception('error')
            return foo

print('t.start(),还没有启用前,current_thread',threading.current_thread())
print('t.start(),还没有启用前,main_thread',threading.current_thread())
print('t.start(),还没有启用前,active_count',threading.active_count())
print('t.start(),还没有启用前,enumerate()',threading.enumerate())
print('t.start(),还没有启用前,get_ident()',threading.get_ident())
t = threading.Thread(target=foo,name='m1',args=(1,),kwargs={'i':200})
t.start()

print('t.start(),结束后,current_thread',threading.current_thread())
print('t.start(),结束后,main_thread',threading.current_thread())
print('t.start()结束后,active_count',threading.active_count())
print('t.start(),结束后,enumerate()',threading.enumerate())
print('t.start(),结束后,get_ident()',threading.get_ident())


Thread实例的属性和方法

import threading
import time
def foo(x,i=100):
    print('active_count, foo',threading.active_count())
    print('current_thread, foo',threading.current_thread().name)
    print('main_thread, foo',threading.main_thread())
    print('enumerate, foo',threading.enumerate())
    print('get_ident, foo',threading.get_ident())
    count = 0
    while True:
        time.sleep(1)
        count += 1
        print(x,'test',i)
        if count >= 5:
            # break
            # raise Exception('error')
            return foo

print('t.start() 启动前,active_count',threading.active_count())
print('t.start() 启动前,current_thread',threading.current_thread().name)
print('t.start() 启动前,main_thread',threading.main_thread())
print('t.start() 启动前,enumerate',threading.enumerate())
print('t.start() 启动前,get_ident',threading.get_ident())
t = threading.Thread(target=foo,name='m1',args=(1,),kwargs={'i':200})
t.start()
print('t.start() 启动后,active_count',threading.active_count())
print('t.start() 启动后,current_thread',threading.current_thread().name)
print('t.start() 启动后,main_thread',threading.main_thread())
print('t.start() 启动后,enumerate',threading.enumerate())
print('t.start() 启动后,get_ident',threading.get_ident())

while True:
    time.sleep(1)
    if t.is_alive():
        print('t.name   {},t.ident  {}~~~~~alive'.format(t.name,t.ident))
    else:
        print('t.name   {},t.ident  {}~~~~ ~dead'.format(t.name,t.ident))
        t.start()
        
# name 获取线程名字,只是标识符方便人看可以重复,cunrrent_thread() 返回的是一个对象,可以使用.name获取对象名
# ident 获取线程id,线程死掉后id号回收,id可重复使用
# is_alive 查看线程是否存在,返回bool值,存在为False

回去

你可能感兴趣的:(python)