1. 不论是import还是from...import,初始化代码都会被执行
2. if __name__ == __main__下面的语句,不会在这个py文件导入的时候调用,只会在执行这个文件的时候调用,相当于程序的入口
3. 关于import 和 from ... import
(1)import 模块 可以
(2)import 包 不可以
(3)from 包 import 模块 可以
(4)from 包 import * (这里*指函数或者类) 可以,并且这里和__all__这个东西无关
(5)from 包 import 包 不可以,没有这种写法
(6)import 包 import * (这里的import后面接的包,包里面必须含有模块,不然也是不可以的) 如果是这种写法,那么在这个包对应的__init__.py下面,必须用__all__指明对外暴露的模块,不然搜不到
(7)__all__里面装的是模块,不是包
(8)from 包 import 函数 / 类 可以
4. 关于generator, next, send和yield
# !user/bin/python
# -*- coding: UTF-8 -*-
def f():
print('start...')
a = yield 5
print('a = ', a)
b = yield 6
print('b = ', b) # 永远不会被执行
ob = f() # 带有yield的函数就是一个生成器
res1 = next(ob) # 首次运行生成器不能传参,因为还没碰到yield,这里将执行第一个yield之前的程序,并且将yield的返回值传给res1,函数里面的a,因为没有传参进来,所以目前是None
print('res1:', res1) # 此时res1为5,程序此时停留在'a = yield 5'这一行,因为next遇到yield跳出来了
res2 = ob.send('msg') # 第二次运行生成器,此时停留在'a = yield 5'这一行,因此,a从None变成'msg',并且继续执行代码直至遇到下一个yield并停留在yield那一行然后退出
print('res2:', res2) # 此时res2返回6,然后跳出函数,b这个时候为None,可惜永远都输出不了了
# start...
# res1: 5
# a = msg
# res2: 6
new_ob = f()
for i in new_ob:
print(i)
# start...
# 5
# a = None
# 6
# b = None
5. 关于切片到底是深拷贝还是浅拷贝的问题
Python中:深拷贝,地址不同,修改不影响原来的值
Numpy中:浅拷贝,虽然地址不同,但是修改却会影响原来的值
也就是说,在Numpy中,要对Ndarray进行深拷贝的话,最好用copy函数,其他的都不好使
总结:
(1)Python中,除了直接赋值都是深拷贝
(2)Numpy中,除了copy都是浅拷贝(着重强调Numpy中的view和切片,虽然是地址会变,但是仍然会影响原来的值,故而为浅拷贝)
# !user/bin/python
# -*- coding: UTF-8 -*-
import numpy as np
# 副本:深拷贝,即内容完全相同,地址不同
# 视图:浅拷贝,共享内存
# 浅拷贝:直接赋值
a = np.arange(10)
b = a
print(id(a) == id(b)) # True
# 浅拷贝:调用view函数 / 切片
# view函数或者切片,区别于直接赋值,因为地址会改变,但是内容仍指向原来的内容
b = a.view()
print(id(a) == id(b)) # False
print(a is b) # False
b[0] = 100
print(a) # [100 1 2 3 4 5 6 7 8 9]
print(b) # [100 1 2 3 4 5 6 7 8 9]
# 浅拷贝:切片
# 会更改原来的值,但是地址不同,等同于view
print('*' * 50)
a = np.arange(10)
b = a[:]
c = a[1:]
b[0] = 101
c[0] = 102
print(a) # [101 102 2 3 4 5 6 7 8 9]
print(b) # [101 102 2 3 4 5 6 7 8 9]
print(c) # [102 2 3 4 5 6 7 8 9]
print(id(a), id(b), id(c)) # 2355930764512 2355930764592 2355913162544
# 然而,在Python中,切片却是深拷贝
print('-' * 50)
words = ['cat', 'dogdog', 'mouse']
new_words = words[:]
new_words[0] = 'puppy'
print(words) # ['cat', 'dogdog', 'mouse']
print(new_words) # ['puppy', 'dogdog', 'mouse']
print(words is new_words) # False
6. 三目运算符
x if(x>y) else y
7. matplotlib的legend要放在plot的后面
8. 想通过函数改变numpy数组的时候,这个函数一定要用np自带的函数
下面这个执行不成功,因为ff没有用np的函数
# !user/bin/python
# -*- coding: UTF-8 -*-
import numpy as np
# f = lambda x : x if x > 0 else 0
a = np.random.randn(10, 10)
def ff(x):
if x > 0:
return x
else:
return 0
def fff(x):
return np.exp(x)
print(ff(a))
如果用fff就可以了,因为fff里面用到了numpy的函数
9. np,max和np.maximum
(1)np.max(a, axis=None, out=None, keepdims=False)
求序列的最值
最少接受一个参数
axis默认为axis=0即列向,如果axis=1即横向
ex:
-
>> np.max([-2, -1, 0, 1, 2])
-
2
(2)np.maximum(X, Y, out=None)
X和Y逐位进行比较,选择最大值.
最少接受两个参数
ex:
-
>> np.maximum([-3, -2, 0, 1, 2], 0)
-
array([0, 0, 0, 1, 2])
10. 捕获warnning,在需要知道warnning的时候很管用,这样可以将警告升级为异常
>>> import warnings
>>>
>>> warnings.filterwarnings('error')
>>>
>>> try:
... warnings.warn(Warning())
... except Warning:
... print 'Warning was raised as an exception!'
...
Warning was raised as an exception!
10. 不要对np.array这样的ndarray数据进行int或者float等强制类型转化操作
11. 广播的时候不能用 += /= 这样的便捷操作符
12. 解包操作
a = (2, 3)
print(*a)
print(a)
2 3
(2, 3)
13. 2019.8.21挖坑
父类的构造函数调用了其他函数,子类重载了调用的那个函数,那么构造子类对象的时候,调用父类的构造函数的时候,是用的子类重载后的,还是父类原有的呢?
答案是重载后的。
import numpy as np
import matplotlib.pyplot as plt
class A:
def __init__(self):
self.hello()
def hello(self):
print('hello')
class B(A):
def __init__(self, x = 5):
super().__init__()
self.x = x
def hello(self):
super().hello()
print('nihao')
b = B()
hello
nihao
14. 继承的时候,super()最好写在所有代码后面,因为可能会出现重载的函数要调用子类方法或者变量的情况,如果先写super()可能会找不到子类中的对象或者方法
下面是正确输出的代码
import numpy as np
import matplotlib.pyplot as plt
class A:
def __init__(self):
self.hello()
def hello(self):
print('hello')
class B(A):
def __init__(self, x = 5):
self.x = x
super().__init__()
def hello(self):
super().hello()
print('ciaos')
print(self.x)
b = B()
hello
ciaos
5
下面是错误输出的代码
import numpy as np
import matplotlib.pyplot as plt
class A:
def __init__(self):
self.hello()
def hello(self):
print('hello')
class B(A):
def __init__(self, x = 5):
super().__init__()
self.x = x
def hello(self):
super().hello()
print('ciaos')
print(self.x)
b = B()
AttributeError: 'B' object has no attribute 'x'
15. np.random.permutation(x),x是一个一位数组或者是一个数,用于输出打乱的数据
16. 字符串去掉引号变成函数,用eval
def test():
print('hello')
string = 'test'
eval(string)()
17. np二维矩阵随机打乱各行,列不变
import numpy as np
a = np.arange(16).reshape(4, 4)
print(a)
permutation = np.random.permutation(a.shape[0])
print(permutation)
print(a[permutation, :])
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]
# [12 13 14 15]]
# [0 3 1 2]
# [[ 0 1 2 3]
# [12 13 14 15]
# [ 4 5 6 7]
# [ 8 9 10 11]]
18. sort和sorted用于对字典进行排序
## 面试很可能会遇到
dic = {'a':2,'b':1}
1、按照key排序
d = sorted(dic.items(),key = lambda k:k[0])
2、按照values排序
e = sorted(dic.items(), key = lambda k:k[1])
强烈推荐这篇博客
https://www.cnblogs.com/dyl01/p/8563550.html
19. 字典排序
items()方法返回带有键值对的数组
import numpy as np
a = {'A':1,'B':20,'C':5}
print(sorted(a.items(), key = lambda x : x[1], reverse = True))
print(a.items())
# [('B', 20), ('C', 5), ('A', 1)]
# dict_items([('A', 1), ('B', 20), ('C', 5)])
20. Pandas中,如果用字典构造系列和数据帧,如果强行指定index或者column,则以强行指定的为准,指定的index或者column中没有,但是字典本身有的数据将被忽略,指定的index或者column中有,但是字典本身没有的数据将被置NaN
21. 列表推导式实践——根据两个数组生成字典
a = [0, 1, 2, 3]
b = ['A', 'B', 'C', 'D']
c = {a[i] : b[i] for i in range(len(a))}
print(c)
{0: 'A', 1: 'B', 2: 'C', 3: 'D'}
思考:列表推导式的思想就是 [表达式 for 迭代变量 in 可迭代对象 [if 条件表达式] ]
其中迭代变量一定会出现在表达式中,那么这个表达式一定都和a和b有关,到底什么是a和b共有的呢?下标!所以用i来代替下标就好了!
22. 20191217碰到的坑
二维数组的深拷贝
如上面那张图所示,当使用[:]自以为是深拷贝,其实如果改变第二维的数值,还是浅拷贝。
当然,如果还是只改第一维,那么还是深拷贝,因为第一维的值却是不是共享同一片内存。但是第二维并不是。
所以,如果要完全的深拷贝一个二维数组,应该像下面这样。
23. a for b in c for a in b等价于
for b in c:
for a in b:
24. split()返回的是一个字符串list