0%

就是说我为什么这么和你对话呢

cat_by_ecksbloodecks_d95joe

Anaconda Navigator & Pyhton & Others

Anaconda Navigator 介绍 / 背景

conda anaconda anaconda-navigator pip virtualenv区别

  • Anaconda是一个包含180+的科学包及其依赖项的发行版本。其包含的科学包包括:conda, numpy, scipy, ipython notebook等。

  • conda是包及其依赖项和环境的管理工具。

  • pip是用于安装和管理软件包的包管理器。

  • virtualenv:用于创建一个独立的Python环境的工具。

  • “Anaconda-Navigator”中已经包含“Jupyter Notebook”、“Jupyterlab”、“Qtconsole”和“Spyder”。

conda基础操作

1
2
3
4
5
6
7
8
9
创建环境 conda create -n envname python=xxx

删除环境 conda remove -n envname --all

进入环境 conda activate envname (old version: source activate xxx)

离开环境 conda deactivate (old version: source deactivate)

列出所有环境 conda info -e

conda参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
conda install -y 覆盖提示,默认yes

The following NEW packages will be INSTALLED:

libgfortran: 1.0-0
numpy: 1.10.2-py27_0
openblas: 0.2.14-3
pandas: 0.17.1-np110py27_0
python-dateutil: 2.4.2-py27_0
pytz: 2015.7-py27_0
six: 1.10.0-py27_0

Proceed ([y]/n)? y
等于提前输入了这个y

-------------------

conda install -c 这个c的意思是channel,也就是指定了下载通道,在出现某些网络问题的情况下可以换一个下载源就这个意思

-------------------

conda install 和 pip install 的区别

1
2
3
pip只能安装python包,而conda可以安装由任何语言编写的包
pip不能创建虚拟环境,需要借助另外的包,例如virtualenv,而conda可以创建虚拟环境。
pip是按照python时自带的,而conda需要安装anaconda才能用。

具体区别可以在找个官网上找到 https://www.anaconda.com/blog/understanding-conda-and-pip

conda更新

很多时候打不开可能也是因为要更新了

管理员运行 conda prompt
然后 conda update anaconda-navigator

第三步 anaconda-navigator --reset

第四步 conda update anaconda-client

第五步 conda update -f anaconda-client

Jupyter Book

使用技巧

端口

1
默认8888 值得一提的是如果同时开启jupyter book和jupyterlab需要小心端口冲突

快捷键

1
快捷键这里不过多介绍,因为我本身就是远程到windows机器上 `等待补充`

显示多行输出

1
Jupyter Book默认只显示一行输出,要想显示多行输出,需要添加如下代码
1
2
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all'

简易命令

1
2
不必离开Jupyter笔记本来执行Shell命令,而是可以在命令开头使用感叹号(!)。例如,您可以安装软件包。
!pip install matplotlib

大量魔术命令

1
2
魔术命令(magic commands)是有助于提高生产率的特殊命令。您可能最熟悉下面的魔术命令,该命令让Notebook渲染Python Matplotlib创建的图表。
%matplotlib inline
1
2
3
4
5
6
7
%pwd #打印当前工作目录
%cd #更改工作目录
%ls #显示当前目录中的内容
%load [在此处插入Python文件名] #将代码加载到Jupyter Notebook
%store [在此处插入变量] #这使您可以传递Jupyter Notebooks之间的变量
%who #使用它列出所有变量
%lsmagic # 查看完整的魔术命令列表

记录单元格运行时间

1
%%time

显示函数文档

shift + tab

1
2
3
# 在Jupyter Book里面查看这个Book后面的Python版本的命令
import sys
sys.version

Python

python基础

1
2
# 照例来个 Hello World 先
print("Hello, Jupyter Book")
1
2
3
# 打印 Python 中的所有关键字
import keyword
print(keyword.kwlist)

[‘False’, ‘None’, ‘True’, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]

1
2
3
4
5
6
7
8
# 幂运算
1.01 ** 365
# 乘法运算符和字符串的混合使用
print('-------' * 10)
# 除法运算
10 / 20
# 取整运算
9 // 2 # 取整

37.78343433288728

----------------------------------------------------------------------

0.5

1
2
3
4
"""
多行注释
"""
print("多行注释")

'\n多行注释\n'

多行注释

1
2
3
4
5
# 按照是否是数字型类可以把python里面的类型分为两类,数字型和非数字型。
# 数字类型分为 int float bool complex(复数型),非数字型分为 字符串、列表、元组、字典。(这四种非数字型类型其实都可以看为容器或者序列)
# 判定类型 python 3 取消了python 2里面的长整形的概念
account = 1101
print(type(account))

<class 'int'>

1
2
3
# Bool 类型 参与计算 True 是 1, false 是 0
# input() 输入的总是String类型
inputStr = input("记录输入")

记录输入 (内容 )

1
2
# Python类型强制转换 强制把123字符串转换成了int
type(int("123"))

int

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 格式化字符串
# %s 字符串
name = "demo"
print("我的名字叫 %s" % name)
# %d 有符号十进制整数 %09d 的意思是如果没有get到9位的话,就用0补全,如果get到了 不进行别的多余操作
num = 1
print("学号是 %09d" % num)
# %f 取舍同上 %.2f 的意思是取小数点后两位,没有的话0补全
price = 8.5
weight = 7.5
money = price * weight
print("苹果单价 %.2f元/斤 ,购买了 %.3f斤,需要支付%.4f元" % (price,weight,money))
scale = 0.8
print("数据比例是 %.2f%%" % (scale * 100)) # 此处内部的括号如果省略的话,是另一种效果 --> 字符串 * 100

我的名字叫 demo
学号是 000000001
苹果单价 8.50元/斤 ,购买了 7.500斤,需要支付63.7500元
数据比例是 80.00%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 判断条件 没有括号 使用 and 和 or 作为逻辑判断连接符号 而不像Java里面的 & 和 | 。

# if not

# elif => else if in Java

# 多行if条件:
# if ((player == 1 and b == 2))
# or (...)
# or (...)

# break 和 continue
# break: 某一天剑满足时,退出循环,不再执行后续重复的代码
# continue: 某一条件满足时,不执行后续重复的代码
1
2
3
# 随机
import random
random.randint(10,20) # 10 <= n <= 20

16

1
2
# 赋值运算符
# = += -= *= /= //= %= **=
1
2
3
4
5
6
7
8
9
10
11
# 在控制台输出
# 1. 定义一个计数器变量,从数字1开始,循环会比较方便
row = 1

# 2.开始循环
while row <= 5:
print("*" * row)
row += 1

# print 详解
print() # <=> print("内容",end="换行符")
1
2
3
4
5
*
**
***
****
*****
1
2
3
4
5
6
7
8
9
# 经典 99 乘法表
row = 1
while row <= 9:
col = 1
while col <= row:
print("%d * %d = %d" % (col, row, col * row ), end = "\t")
col += 1
row += 1
print("")

1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 函数
def multiple_table():
row = 1
while row <= 9:
col = 1
while col <= row:
print("%d * %d = %d" % (col, row, col * row ), end = "\t")
col += 1
row += 1
print("")

multiple_table()

# 函数注释的说明
# 1. 注释写在方法名下面 2. 方法的第一排要和上面最后一行有两行空白的距离 3.pycharm中,鼠标放在方法名上,Ctrl+Q就可以调出注释。

1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81

1
2
3
4
5
6
# 函数参数
def sum_2_num(num1,num2):
result = num1 + num2
print("%d + %d = %d" % (num1,num2,result))

sum_2_num(50,20)

50 + 20 = 70

1
# pyc文件:python的编译后文件,浏览程序目录里面会有一个 __pycache__ 的目录,里面会有pyc为后缀的文件,就是编译后文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# List 是使用最频繁的数据类型,对应别的语言中的数组。
# 专门用于存储一串信息
# 列表用 [] 定义,数据之间使用 , 分隔
# 列表的索引从 0 开始 --> index

lname_list = []
# 增加
# 列表自带了很多的方法,
# 列表.insert(索引) 在指定位置插入数据
# 列表.append(数据) 在末尾追加数据
# 列表.extend(列表2) 将列表2 的数据追加到列岛

# 修改
# 列表[索引] = 数据 修改指定索引的数据

# 删除
# del 列表[索引] 删除指定索引的数据
# 列表.remove[数据] 删除第一个出现的指定数据
# 列表.pop 删除末尾数据
# 列表.pop(索引) 删除指定索引数据
# 列表.clear 清空列表

# 统计
# len(列表) 列表长度
# 列表.count(数据) 数据在列表中出现的次数

# 排序
# 列表.sort() 生序排序
# 列表.sort(reverse=True) 降序排序
# 列表.reverse() 逆序、反转
1
2
3
4
5
# List之遍历
# 类比 Java 里面的 foreach
# 语法形式:
# for 别名 in List:
# 理论上List是可以存储不同类型的数据的, 习惯上 使用元组保存不同类型的数据,使用List保存相同类型的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 元组 Tuple
# 元组的元素不能修改
# 使用()定义,索引从0开始
info_tuple = ("zhangsan",18)

# 混淆点 定义只有一个变量的元组 需要加上一个逗号
single_tuple = (5)
type(single_tuple) #int
single_tuple = (5,)
type(single_tuple) # tuple

# 但是如果是定义一个空的元祖的话,我们只需要定义一个括号即可

# 格式化字符串 % 后面的本质上就是一个元组, 使用元组来拼接一个新的字符串效果相同

# List 和 Tuple 的转换 List(元组) 可以把元组转换成List,使用tuple(列表)可以把列表转换成元组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 字典 dictionary 使用 {} 定义,类似于 Map
# 字典无序 List有序 字典的key必须是不可变类型
# 值可以是任何数据类型,键只能使用字符串、数字或者元组
xiaoming = {
"name": "小明",
"age": 18,
"gender": True,
"height": 1.75,
"weight": 75.6,
}

print(xiaoming)
print(xiaoming["name"])

# 增加 / 修改
xiaoming["age"] = 10 # 如果这个值得没有的话,就会新建

# 删除 pop
xiaoming.pop("age")

# 合并字典 update
zidian = {"key": "value"}
zidian.update(xiaoming)
print(zidian)

# 清空 clear
zidian.clear()
print(zidian)

for k in xiaoming:
print("%s - %s" % (k, xiaoming[k]))

{‘name’: ‘小明’, ‘age’: 18, ‘gender’: True, ‘height’: 1.75, ‘weight’: 75.6}
小明

10

{‘key’: ‘value’, ‘name’: ‘小明’, ‘gender’: True, ‘height’: 1.75, ‘weight’: 75.6}
{}
name - 小明
gender - True
height - 1.75
weight - 75.6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 字符串
# 单引号和双引号都能定义字符串 但是单引号不推荐
str1 = "hello python"
print(str1[0])

for k in str1:
print(k)

# 统计长度
print(len(str1))

# 统计出现次数
print(str1.count("o"))

# 某个字符串出现的位置 (第一个字母出现的index)
print(str1.index("o"))

h
h
e
l
l
o

p
y
t
h
o
n
12
2
4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 字符串切片 List和tuple也能切片 字典不能切片
num_str = "0123456789"

num_str[2:6] # index 2 - 5 含头不含尾 '2345'

num_str[2:] # index 2 到末尾 '23456789'

num_str[:6] # 开始 -> index 6 之前的所有char, 前6位 '012345'

num_str[:] # 全部 '0123456789'

num_str[::2] # 从头开始 步长为1取值 '02468'

num_str[1::2] # 从index = 1 开始 步长为1取值 '13579'

num_str[2:-1] # 负数代表从后面往前 '2345678'

# 字符串逆序 *
num_str[-1::-1] # '9876543210'
num_str[::-1] # '9876543210'
1
2
3
4
5
6
# 公共方法 
# len() # 容器内元素个数
# del() # del 有两种方式 还有一种是作为关键字
# max() # 返回容器中元素的最大值
# min() # 返回容器中元素的最小值
# cmp() # python 3 中取消了这个函数
1
2
3
4
5
6
7
# 运算符在高级类型中的作用

# + 合并 : 字符串 列表 元组
# * 重复 : 字符串 列表 元组
# in 判断是否存在: 字符串 列表 元组 字典
# not in 和上面对应
# > >= == < <= 元素比较 :字符串 列表 元组
1
2
3
4
# 完整 for 循环
# 也就是 for 下面 跟了 一个 else , 如果for循环没有被break打断就会执行else里面的内容,如果被break打断了 ,就不会执行

# 使用场景: 迭代遍历 所需要的数据类型,查找某个元素,如果存在,整体退出循环,如果不存在,在整体循环结束后,进行统一的操作。
1
2
# python 查看内存地址
# id()
1
2
3
4
5
# 可变和不可变类型
# 区分标准是 内存中的数据能否修改
# 可变类型只有两个就是 列表和字典 ,可变类型的数据变化是通过方法来实现的

# 可变类型 被函数里面修改的时候(并不是创建新的内存使用,而是修改内存里面的数据),虽然是通过参数传入的,但是原值还是会被修改,不可变类型并不会
1
2
3
4
5
6
# 因为Python是解释型语言 所以在Python中原则上不允许直接修改全局变量的值,如果在函数中对全局变量进行复制操作的话,Python会自己创造一个局部变量
# 所以在这个地方对全局变量进行的修改操作时无效操作。

# 但是,凡事无绝对,如果一定想要在函数里面修改全局变量的话,我们会在变量前面加上一个Global,这样就不会在函数中重新创建这个局部变量了。

# 为了避免全局变量和局部变量在明明的时候出现混淆,一般来说习惯上会在全局变量命名的时候前缀加上一个g_或者gl_
1
2
3
4
# 如果函数返回的类型是元组,我们的小括号可以省略

# return (temp, wetness)
# return temp, wetness # 小括号可以省略
1
2
3
4
5
6
7
8
# Python中特有的交换两个值的方式
a = 6
b = 100

a,b = (b,a)

print(a)
print(b)
1
2
3
4
5
6
7
8
9
10
11
12
# 缺省参数 具有默认值的参数就叫做缺省参数

# 在函数里面定义形参的时候直接写 gender = True ,默认就是True的意思
num_list = [7, 5, 4, 9]
# 默认就是升序排序,因为这种需求更多
num_list.sort()
print(num_list) # 4,5,7,9
# 只有当降序排序时,才需要传递reverse参数
num_list.sort(reverse=True)
print(num_list) # 9,7,5,4

# 缺省参数后面不能再跟参数

case:

image-20220728223807310

1
2
3
4
5
6
7
# 多值参数
def demo(num, *nums, **numss):
print(num)
print(nums)
print(numss)

# 习惯上 多值参数里面,我们使用*args表示元组,使用*kwargs表示键值对参数
1
demo(1,2,3,4, age=18)

1
(2, 3, 4)
{‘age’: 18}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 拆包 字典和元组作为参数传进参数的时候会变成一个整体传入,我们为了拆解这个参数,在传入参数的时候,根据他们的类型在前面 添加一个 * 或者两个 *

run(1,2,3)

def run(a,*args):
#第一个参数传给了a
print(a) # 1
# args是一个元组,里面是2和3两个参数
print(args) # (2,3)
# *args是将这个元组中的元素依次取出来
print("对args拆包")
print(*args) # *args 相当于 a,b = args 结果是 2 3
print("将未拆包的数据传给run1")
run1(args) # 输出元组 ((2,3),) 对元组进行拆包 (2,3)
print("将拆包后的数据传给run1")
run1(*args) # 输出元组 (2,3) 对元组进行拆包 2 3

def run1(*args):
print("输出元组")
print(args)
print("对元组进行拆包")
print(*args)

# 我对装包,拆包的理解是 参数中的*/**是装包,在函数内部使用这个*的意思就是拆包
1
2
3
4
5
6
7
8
9
10
11
12
def run(**kwargs):#传来的 key = value 类型的实参会映射成kwargs里面的键和值
# kwargs是一个字典,将未命名参数以键值对的形式
print(kwargs)
print("对kwargs拆包")
# 此处可以把**kwargs理解成对字典进行了拆包,{"a":1,"b":2}的kwargs字典又
# 被拆成了a=1,b=2传递给run1,但是**kwargs是不能像之前*args那样被打印出来看的
run1(**kwargs)

def run1(a,b): #此处的参数名一定要和字典的键的名称一致
print(a,b)

run(a=1,b=2)

{‘a’: 1, ‘b’: 2}
对kwargs拆包
1 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# OOP 面向对象
# 通用方法:dir(对象) 能够把对象里面所有能调用的方法都调用出来
# 添加属性 Python特有的方法,先把对象创建出来,然后直接使用 .属性名 就可以为这个对象添加新的属性,这种方式虽然简单,但是是不推荐的。

# 对象初始化
# 当使用类名创建对象时,会自动执行以下操作
# 1. 为对象在内存中分配空间 -- 创建对象
# 2.为对象的属性设置初始值 -- 初始化方法 int
# 这个初始化方法就是 __intit__方法 ,是对象的内置方法
# __init__方法是专门用来定义一个类有哪些属性的方法


# 初始化
"""
__init__方法是专门用来定义一个类具有哪些属性的
"""


class Cat:

# 设置默认值
def __init__(self, new_name):
print("初始化")

# 属性
self.name = new_name

def eat(self):
print("%s 爱吃鱼" % self.name)

# __del__
# 对象被销毁前执行的方法
def __del__(self):
print("%s 我去了" % self.name)

# 必须返回字符串 类似于Java的toString方法
def __str__(self):
# print("我是小猫 %s" % self.name) 错误示例
return "我是小猫 %s" % self.name


# 使用类名()创建对象的时候,会自动调用初始化方法__init__
tom = Cat("TomDemo")

# 可以用__init__方法内部使用self.属性名 = 属性的初始化值 就可以定义属性
# 定义属性之后,再使用Cat类创建的对象,都会拥有该属性
print(tom.name)
tom.eat()

# del 销毁是在一个python文件即将运行到结尾的时候
print(tom)

# Python 能够自动的将一堆括号内部的代码链接在一起

# 运行结果里面的del方法的位置我完全没有看懂,这个坑以后再填,花了点时间没有整明白

"""
身份运算符
is is是判断两个标示符是不是引用同一个对象
is not is not 是判断两个表示服是不是引用不用对象

is 与 == 的区别
is用于判断两个变量引用对象是否为同一个
==用于判断引用变量的值是否相等
"""

初始化
TomDemo 我去了
TomDemo
TomDemo 爱吃鱼
我是小猫 TomDemo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 封装 继承 多态

# 继承
class Animal:
def eat(self):
print("吃")

def drink(self):
print("喝")

def run(self):
print("跑")

def sleep(self):
print("睡")


wangcai = Animal()

wangcai.eat() #吃
wangcai.drink() #喝
wangcai.run() #跑
wangcai.sleep() #睡

# 子类拥有父类的所有方法
class Dog(Animal):

def bark(self):
print("汪汪叫")


wangwang = Dog()

wangwang.eat() #吃
wangwang.drink() #喝
wangwang.run() #跑
wangwang.sleep() #睡
wangwang.bark() #汪汪叫


class XiaoTianQuan(Dog):

def fly(self):
print("我会飞")

def bark(self):

print("我是啸天犬")

# 调用父类的bark方法
super().bark()
# Python2.0 如果要实现上面的功能,有点复杂 代码如下
"""
Dog.bark(self)
"""

print("aafsdwaerwgybds")

# 有没有括号 对Python来说 说法很大
xtq = XiaoTianQuan()
xtq.bark() #我是哮天犬 汪汪叫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class A:
# 属性在init方法中定义 使用__(两个下划线)定义的属性是私有属性,无法被子类访问
def __init__(self):
self.num1 = 100
self.__num2 = 200

def __test(self):
print("私有方法 %d %d" % (self.num1, self.__num2))


class B(A):

def demo(self):

# 在子类的对象方法中不能访问父类的私有属性和方法
# 但是可以通过调用父类的共有方法间接调用父类的公有属性和方法
print("访问父类的私有属性 %d" % self.__num2)


b = B() # <__main__.B object at 0x0000020EA7593BE0>
print(b)
"""
在外界不能直接访问对象的私有属性,调用方法
print(b.__num2)
b.__test()
"""
print(b.num1) #100
b.demo() # 'B' object has no attribute '_B__num2'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 多继承
class C:

def test(self):
print("test 方法")


class D:

def demo(self):
print("demo 方法")


# 多继承
class E(C, D):

pass


# 创建子类对象
e = E()
e.test()
e.demo()

# 应该避免两个父类汇总存在同名的属性和方法
"""
python中多继承两个父类出现相同的方法 属性名的时候
使用MRO选择执行顺序的
"""
print(E.__mro__)
# (<class '__main__.E'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)


"""
新式类 以Object为基类的对象
旧式类 不以Object为基类的对象
两者在多继承时 会影响到方法的搜索顺序
"""

test 方法
demo 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 私有属性 / 方法

class Woman:

def __init__(self, name):
self.name = name
self.__age = 18

def secret(self):
print("%s 的年龄是 %d" %
(self.name,
self.__age))


xiaofang = Woman("小芳")
# 私有属性不能直接调用 但是Python中没有真正的私有属性和方法 可以使用下面第二行的代码调用
print(xiaofang.__age) # 报错,因为不能直接调用
print(xiaofang._Woman__age) # 18
xiaofang.secret() # 小芳 的年龄是 18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 多态

# 类的结构
"""
__init__ 为对象初始化
实例方法(self)


类对象 模版 只有一个
实例对象 可以有很多个

"""


# 类方法
class Tool(object):

count = 0

def __init__(self, name):
self.name = name

Tool.count += 1

@classmethod
def show_tool_count(cls):

print("工具对象的数量 %d" % cls.count)


# 创建工具对象
tool1 = Tool("斧头")
tool2 = Tool("榔头")

# 调用类方法
Tool.show_tool_count() # 工具对象的数量 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 单例

"""
python 中的self和cls一句话描述:self是类(Class)实例化对象,cls就是类(或子类)本身,取决于调用的是那个类。

__new__
为对象分配空间
返回对象的引用

python获得了对象的引用后,将引用作为第一个参数,传递给__init__方法

重写__new__方法的代码非常固定 如下

"""


class MusicPlayer(object):

def __new__(cls, *args, **kwargs):

# 创建对象时,new方法会被自动调用
print("创建对象,分配空间")

# 为对象分配空间
instance = super().__new__(cls)

# 返回对象的引用
return instance

def __init__(self):
print("播放器初始化")


player = MusicPlayer()
print(player) # 每次都指向内存中不同的位置

"""
单例:让类创建的对象,在系统中只哦与唯一的一个实例
"""
print("--------完整单例-------")


class SingleMusicPlayer(object):
instance = None

init_flag = False

def __new__(cls, *args, **kwargs):

# 1 判断类属性是否是空对象
if cls.instance is None:
# 2 调用父类方法,为第一个对象分配空间
cls.instance = super().__new__(cls)

# 返回类属性保存的对象引用
return cls.instance

def __init__(self):

# 1 判断是否执行过初始化动作
if SingleMusicPlayer.init_flag:
return

# 如果没有初始化过
print("初始化播放器")

SingleMusicPlayer.init_flag = True


player1 = SingleMusicPlayer()
print(player1)

player2 = SingleMusicPlayer()
print(player2) # 和上面相同的地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 异常
"""
try:
尝试执行的代码
except:
出现错误的处理
"""

try:
num = int(input("请输入一个整数:"))

result = 8 / num

print(result)

except ZeroDivisionError:
# 错误的处理代码
print("请输入正确的整数")
except ValueError:
print("请输入正确的整数")
# 捕获未知错误
except Exception as result:
print("未知错误 %s" % result)
else:
# 没有异常的时候才会执行的,这个else出现的位置和Java并不是一脉相承的,他这个else针对的是except
print("尝试成功")
finally:
# 总是会执行的代码
print("总是会执行")

print("-" * 50)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
"""
异常的传递
python 会把异常一直向上传递
"""


def demo1():
return int(input("输入整数:"))


def demo2():
return demo1()


print(demo2())

'''
ValueError Traceback (most recent call last)
Input In [2], in <cell line: 47>()
43 def demo2():
44 return demo1()
---> 47 print(demo2())

Input In [2], in demo2()
43 def demo2():
---> 44 return demo1()

Input In [2], in demo1()
39 def demo1():
---> 40 return int(input("输入整数:"))

ValueError: invalid literal for int() with base 10: 'dsf'
'''
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 导入

"""
from package import sth
from package import *
"""


# 所有倒入的模块 没有缩进的部分都会被执行一次

"""

__name__的用法
如果需要测试模块 就增加一个条件判断
这样增加了判断之后,在作为被包倒入的时候 下面的代码不会执行
"""

"""
模版
# 导入模块
# 定义全局变量
# 定义类
# 定义函数

def main():
# ...
pass

# 根据__name__判断是否执行下方代码
if __name__ == "__main__"
main()
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Package


"""
包是一个包含多个模块的特殊目录
目录下有一个特殊的文件 __init__.py
包名的命名方式和变量名一直,小写字母+_

好处
使用import 包名 可以一次性倒入包中所有的模块

在__init__.py文件中用
from . import 模块名
制定外部文件需要倒入的模块
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 发布
"""
发布模块
三步
1. 创建setup.py

"""


"""
发布
固定模版:

from distutils.core import setup

# 多值的字典参数,setup是一个函数
setup(name="Hello", # 包名
version="1.0", # 版本
description="a simple example", # 描述信息
long_description="简单的模块发布例子", # 完整描述信息
author="FlyHugh", # 作者
author_email="flyhobo@live.com", # 作者邮箱
url="flymetothemars.github.io", # 主页
py_modules=["hello.request",
"hello.response"]) # 记录包中包中包含的所有模块
"""

"""
第二步
构建
python3 setup.py build
"""

"""
第三步
python3 setup.py sdist
"""

"""
安装
tar zxvf 解压
sudo python3 setup.py install

然后打开python3运行即可

"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File

# Python 文件指针
# 文件指针标记从哪个位置开始读取数据,第一次打开文件时,通常文件指针会指向文件的开始位置
# 当执行了 read 方法后,文件指针对移动到 读取内容的末尾

# 也就是说
# 第一次读取了之后,文件指针移动到了文件末尾,再次调用不会读取到任何内容

# f = open("文件名","访问方式")
# r w a r+ w+ a+ 具体见百度


"""
python操作文件

open 打开文件 返回文件对象
read 文件内容读取到内存
write 将内容写入文件
close 关闭文件

文件指针
open()方法有两个参数 第二个参数制定的是打开的方式
存在r w a r+ w+ a+这些方式 用str格式传入

readline 按行读取
"""


"""
小文件复制
file_read = open("README")
file_write = open("README[复件]","w")

text = file_read.read()
file_write.write(text)

file_read.close()
file_write.close()


复制大文件 用readline
"""

"""
倒入 import os
rename 重命名
remove 删除

listdir 目录列表
mkdir 创建目录
rmdir 删除目录
getcwd 获取当前目录
chdir 修改工作目录
path.isdir 判断是否是文件
"""

"""
python2.x 默认ASCII编码
python2 使用
# *-* coding:utf-8 *-*
来指定编码格式
python3.x 默认使用UTF-8

"""
1
# eval 函数 -- 将字符串当成有效的表达式 来求值 并 返回计算结果

Python随机随到的一些问题,那你妈逼随机就这么容易随到的啊

anaconda代理问题

设置代理的方法:找到位置在path-for-install目录下.condarc文件,添加Http和Https的代理,这里默认本地cfw

1
2
3
proxy_servers:
http: http://127.0.0.1:7890
https: http://127.0.0.1:7890

如果有密码的话

1
2
3
proxy_servers:
http: http://user:password@xxxx:8080
https: https://user:password@xxxx:8080
1
anaconda 并不能被Clash4Windows在Tun模式下代理,虽然不知道原因(后续知道了会在这补上),anaconda只能在配置了proxy之后才能被代理流量

python和Clash4windows的冲突问题

现象: 和pip有关的几乎一切指令都会报错

1
2
3
4
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError(0, 'Error'))': /simple
/gitpython/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError(0, 'Error'))': /simple
/gitpython/

ts:

遇到这种问题那肯定是直接debug走起,首先用文本搜索到抛这个错的函数,然后在嫌疑语句上都打上断,我们就能找到罪魁祸首:

image-20220727225126154

同时发现windwos中原生的python环境并没有这个问题,于是和venv外没问题的老版pip一比较,很容易就能发现不对劲:选中的那两行在老版是不存在的

image-20220727225518321

有了这个额外信息,我们很容易就能找到这个 Support for web proxies is broken in pip 20.3 · Issue #9190 · pypa/pip (github.com) 来说明问题,2016年底,curl加入了这个把https协议前缀另加解释与定义的联盟:HTTPS proxy with curl | daniel.haxx.se,而urllib3显然也跟上了这个脚步:

因为前缀设置了 tls_in_tls_required 之后,urllib3会企图把这个代理服务器看作一个套了tls的http CONNECT代理。
但是问题是,我并没有设置 https:// 前缀的代理服务器,这个行为是什么神奇的情况呢?
继续向下追,找到如何获取代理的:

image-20220727225732878

确实,env里面没有proxy,那按照windows的习俗找找注册表也情有可原对吧?
这个函数的内部实现是这样:

image-20220727225820001

看红框的行为是不是好像很眼熟?IE的代理设置似乎就是这样的?

不,并不是一样的,因为IE的代理设置把HTTPS(在zh-MS方言里叫安全)代理定义为支持 CONNECT 动词的HTTP代理,尽管很久以来人们都是这样用的,但是当它前面出现一个协议前缀的时候就不一样了。

因为clash for windows打开系统代理的代理配置看起来并没有写明了protocol:

image-20220727230459589

所以首先,我们的py会根据IE时代的约定俗成把这样一个没有指明protocol的proxy url自动补全三种协议然后再按照约定俗成的行为为https请求使用https_proxy最后在一个http代理上试图开tls

这个配置在IE时代行为会是正常的,在现代的库中行为也是正常的,但是对于这样一个混杂了两种行为的库,模糊不清就成了问题。
上面的截图并不是urllib3的,而是 属于py自己的标准库urllib的,也算是urllib3开发人员的思想和urllib的历史遗留实现冲突了吧。

似乎此问题在新版Python中的报错信息会变成 There was a problem confirming the ssl certificate: HTTPSConnection
Pool(host='pypi.org', port=443): Max retries exceeded with url: /simple/plotly/ (Caused by SSLError(SSLEOFError(8, 'EOF 
occurred in violation of protocol (_ssl.c:1123)'))) 或者类似的错误。

在后续的版本更新中,CFW解决了Specify Protocol解决了部分此问题,但是解决的并不是很好,启用Specify Protocol会导致只设置http代理,https无代理。

image-20220727231553719

可以看到如果只是单纯地把注册表项的内容由 127.0.0.1:7890改为http://127.0.0.1:7890的话,urllib只会返回一个只有一个key也就是http的代理dict。
这时候从pip的请求调用链往上找,可以看到负责决定使用这个dict中那个代理的代码是 requests/utils.pyselect_proxy函数:

因为红框中的部分的限制,当你请求https://pypi.org的时候,只有key为https/https://pypi.org/all/all://pypi.org的代理会被使用,上面那个http的代理自然也就不会被使用。
BTW,因为这个代码是requests库的,这也就意味着在Windows平台上Clash for Windows的系统代理不会影响到大部分py应用的http请求。
而正确的做法是什么呢?让我们在IE中设置上代理,然后看一看它给出的行为:

image-20220727231825488

image-20220727231841031

同时,因为urllib中还存在代理的类型推测代码,所以正确的设置应该是:
http=http://127.0.0.1:7890;https=http://127.0.0.1:7891

python和解释性语言

https://blog.csdn.net/balabalamerobert/article/details/1649490