Python 小知识笔记

由于我学Python的时候是跟着菜鸟教程学的,只花了一周时间就粗糙地开始使用Python了,导致还有很多的Python小知识或者小技巧我还没有掌握,所以在这里记录一下,查漏补缺:

1.切片 [start:end:step] 和 range(start, end, step) 取数是一样的

>>> a = list(range(10))
>>>
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> a[0:6:2]
[0, 2, 4]
>>>
>>>
>>> b = list(range(0, 6 ,2))
>>>
>>> b
[0, 2, 4]

可以看到 start=0, end=6, step=2, 取出来的结果是0,2,4而没有包含6,也就是不包含 end

补充:np.linspace(start, stop, num) 是包含 stop 的而且 num 是取的点的个数

>>> import numpy as np
>>>
>>> c = np.linspace(0, 6, 3)
>>>
>>> c
array([0., 3., 6.])

2.使用 enumerate() 就可以既获得列表的内容又能获取对应的索引了

>>> ass = list("fuck")
>>>
>>> ass
['f', 'u', 'c', 'k']
>>>
>>> for index, char in enumerate(ass):
...     print(index, char)
...
0 f
1 u
2 c
3 k

3.使用iter()配合trainload或者对其他可迭代对象使用:

dataiter = iter(trainloader)
images, labels = dataiter.next()


>>> ls = list(range(10))
>>> ls
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> i = iter(ls)
>>>
>>> next(i)
0
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)
4

4. zip() 方法就像一条拉链一样可以把两个列表并排啮合起来使用:

>>> a = list(range(4))
>>>
>>> b = list("LOVE")
>>>
>>> for i, j in zip(a, b):
...     print(i, j, sep=": ")
...
0: L
1: O
2: V
3: E

5. Python的3种格式化字符串的方法

>>> fruits = "apples"
>>> price = 9.99
>>>
>>> print("These {:7s} are {:.2f} yuan.".format(fruits, price))
These apples  are 9.99 yuan.
>>>
>>> print(f"These {fruits:7s} are {price:.2f} yuan.")
These apples  are 9.99 yuan.
>>>
>>> print("These %7s are %.2f yuan." % (fruits, price))
These  apples are 9.99 yuan.
>>>

6. 注意要实例化类的对象来操作而不是直接调用类

今天写了一段错误的代码但是一开始怎么也没想通哪里出错了:

from from torchvision.transforms import ToPILImage

image = input
image = torch.squeeze(image, dim=0)
image = ToPILImage(image)  # 这样用法是错误的
# toPIL = ToPILImage()
# image = toPIL(image)
plt.imshow(image)
plt.show()

当我把那个标记的错误的用法改成注释里写的用法之后程序就可以正确执行了

为什么呢?因为ToPILImage是一个类,我把这个类当成了函数使用,必然是错误的

正确的用法是实例化一个ToPILImage对象toPIL,然后就可以调用toPIL对象了

其他类似的例子还有:

loss_func = torch.nn.MSELoss()
loss = loss_func(prediction, labels)
# 而不能直接 loss = torch.nn.MSELoss(prediction, labels)当成一个函数

m = torch.nn.Linear()
out = m(input)
# 而不能直接使用 out = torch.nn.Linear(input)

也就是说,我们一定要明辨一个东西到底是类还是函数或者对象

如此,类和函数对象等命名规范的重要性可见一斑!!!

7. Python的传参机制:

1.函数传参过程中,对于一些基本数据类型,如int(整型),float(浮点型),str(字符串)等,是值传递,函数内部对以上数据类型的数据进行修改时并不会改变原值。

2.对于list(列表)、dict(字典)、tuple(元组)则是地址传递,函数内部对以上数据类型操作时会改变原数据值。

其实函数不函数的不是关键,关键在于Python的赋值“=”符号做了什么,赋值”=“的作用机制也是符合上述两条规则,下面用代码来验证:

例如:对于list,形如b=a的操作不是将a复制一份给b,而是使b和a公用了同一个变量的地址:

a = [1, 2, 3]
b = a 
b.append(4)
print(a)

Out: [1, 2, 3, 4]


# 正因为这里b和a这两个list实际使用的是同一个内存单元的变量
# 才会导致对b进行就地修改,结果a的值也发生了改变
 

# 但下面的代码不会发生这样的情况

a = [1, 2, 3]
b = a 
b = b + [4]
print(a)

Out: [1, 2, 3]

# 这里a的值没有被改变是因为 b = b + [4]这个操作重新对b进行了赋值,相当于创建了一个新的b
# 这样就破坏了原来a和b绑定的状态,也就是使得a和b不再使用同一内存单元

# 如果将b = b + [4]换成b += [4]又会回到第一种情况
# a的值又会发生改变,因为 += 是一个就地操作

总结:

其实不可以单纯地用C语言的值传递和指针传递来理解Python的传参,因为Python里面的赋值很要命,很容易出现赋值之后此变量非彼变量的情况

8. 生成器(generator): Python生成器(Generator)详解_python_脚本之家 (jb51.net)

generator是一个像list一样的东西,但是不需要像list那样使用一大片连续的内存,这样就节省了内存,但同时它就不能像list一样直接使用索引来访问元素了。

# 只需要将list的[]改成()就可以创建generator
g = (x for x in range(10))
# 可以使用next()方法访问generator的元素
next(g)
Out: 0
# 更普遍的是使用for循环来访问
g = (x for x in range(3))
next(g)
0
for i in g:
    print(i)
    
Out: 1
Out: 2

懒得打字了,暂时先记到这里吧......

你可能感兴趣的:(小知识笔记,python,list)