Python 小知识¶
关于局部变量和全局变量¶
在函数内部或代码块内是可以访问全局变量的,但是是以只读形式访问的,若不加 global 关键字 那么是不能对其进行修改的,若对全局变量进行赋值,默认是会创建一个新的同名局部变量的
而且 在一个代码块内部,如果有新声明的新同名变量,那么就算在其前面也是不能访问到外部的 全局变量的,此时若进行访问,会报错
var = 1
def func():
print(var) # ok 1
var = 1
def func():
print(var) # not ok referenced before assignment
var = 4
var = 1
def func():
var = 4
print(var) # ok 4
var = 1
def func():
global var
print(var) # ok 1
var = 4
print(var) # ok 4
print(var) # ok 4
注意函数返回的数据类型¶
- 注意是 list 还是 生成器
- 注意是 list/tuple 还是 单个变量
Python 很注重惰性计算,所以很多函数,方法返回的是 生成器 或者 map 类型,有些时候需要 转换 为 list tuple 等再进行使用
例如 plt.plot(...) 就返回一个 plot 对象的 list, 原因大概是可以这样写 plt.plot(x, y, x, z)
单元素 list tuple 的注意事项¶
很多函数可能需要返回多个值,所以就会返回 tuple 作为数据类型,但很多时候其返回的 tuple 中又只有一个元素,此时就加逗号咯
line, = ax.plot(Data[0, 0], Data[0, 1],color = 'red',lw = 1.5, label = 'Pos')
类似这样
有时候我们也需要返回一个 tuple 但只有一个元素,所以加逗号咯
def func():
something()
return res,
python 中的代码块¶
if 语句不会产生代码块,也就是不会生成新的变量空间,这点和其他语言不太一样
切片是目标对象的一个拷贝¶
Python 中,”==” 和 “is”的区别¶
前者是相等性比较,比较的是两个对象中的值是否相等,后者是一致性比较,比较的是两个对象的内存空间地址是否相同。
面向对象:类中的 __slots__
方法¶
定义了类可以使用的方法总和。仅对当前类起作用,其子类不受影响,除非子类中也定义了 __slots__
方法,那么子类的属性就是自身的 slots 属性加上其父类的 slots 里的属性
关于 python 里的函数调用和定义的顺序¶
一般情况下,是定义必须在调用之前,但是如果是一个函数内部调用另一个函数,则被调用的函数的定义可以在这个调用函数的后面。另外 类内的函数定义和调用似乎没什么先后顺序
关于 __new__()
¶
实际上 new 就相当于是 C++ 里的构造函数,但是不包含赋值和初始化的部分 一般情况下,不需要手动写 new
关于切片和拷贝的速度¶
想用 matplotlib 画一个动态图,但是数据是实现读取好的。所以只能不断改变画图数据的大小来实现 plot 的动态过程。 想到两种方法,一个是新建一个 array,然后每一次迭代都 append 一个数据进去,然后 plot 这个 array,另一种方法 是每次对原始数据进行切片,后画图。
后来采用的是切片的方法,发现速度竟然比 append 要快很多,总觉得每一步一次的 append 应该不会比对那么多数据进行浅复制的切片慢啊。
因为数据是存储在 numpy 的 ndarray 中和 Python 内置的 list 可能有些不一样。list 在切片的时候实际上是进行浅拷贝的,而 ndarray 在切片时是返回一个 view(numpy 名词),共享核心数据,但其他的属性例如 shape 等都是不影响的。可能 ndarray 的核心数据都是 flatten 之后存储的吧。
总之,append 很慢,如果知道数组长度就预先分配好空间,如果不知道也尽量少做 append 或者 resize 的操作,用空间换时间是更优解吧。
Python 里的函数可以嵌套定义¶
虽然这在装饰器里很常见,但如果不是装饰器的话看起来就有点奇怪了
def main():
def func():
print('shit')
func()
>>> main()
shit