在python2中,传统除会根据操作数来判断: - 若操作数都为整数,则商舍去小数后的部分,返回整数 - 若操作数中有浮点数,则商为正确的值,返回浮点数
>>> 1 / 2 0 >>> 1 / 2.0 0.5若用地板除,则无论如何都舍去小数点后的部分,并根据操作数判断返回类型:
>>> 1 // 2 0 >>> 1 // 2.0 0.0在python3中,传统除不再根据操作数判断,而是直接执行精确除法:
>>> 1 / 2 0.5 >>> 1 / 2.0 0.5地板除还是和python2一样
>>> 1 // 2 0 >>> 1 // 2.0 0.0若循环后跟了else子句,则else子句中的部分在循环没有被break(即正常运行完)时执行: test1.py
for i in range(3): print(i) else: print("else") λ python test1.py 0 1 2 elsetest2.py
for i in range(3): print(i) if i == 2: break else: print("else") λ python test2.py 0 1 2python中的赋值相当于引用,变量更像是指针。如,a=1,创建了一个整数对象1,并且让a指向它;再赋值a=2,则另创建了一个整数对象2,让a指向它;再赋值b=a,则将b指向2这个对象:
>>> a = 1 >>> id(a) 1599559952 >>> a = 2 >>> id(a) 1599559968 >>> b = a >>> id(b) 1599559968此时赋值a=3,则b=2不变,因为a指向了另一个对象3,而b还是指向2:
>>> a = 3 >>> id(a) 1599559984 >>> b 2 >>> id(b) 1599559968然而如果赋予的值是可变对象如列表时,情况又会有所不同:
>>> aa = [1, 2] >>> bb = aa >>> id(aa), id(bb) (49214288, 49214288) >>> aa.append(3) >>> aa, bb, id(aa), id(bb) ([1, 2, 3], [1, 2, 3], 49214288, 49214288)可以看到,当bb=aa时,若aa改变了,bb也跟着一起变了。这是因为aa.append(3)语句并没有创建一个新的列表对象让aa指向它,而是再原来的对象上添加元素,而此时bb也指向这个对象,因此bb的值也跟着变了。而之前a=2和b=2由于2是整数即不可变对象,另外赋值时会新创建对象。 如果要让bb不跟随aa变化,就不能使用aa.append(3)的方式,而应该采用aa = aa[:]或aa = aa.copy()的方式,这样会复制aa指向的内容创建一个新的对象再让aa指向它,再执行aa.append(3)将不会影响bb:
>>> aa, bb, id(aa), id(bb) ([1, 2, 3], [1, 2, 3], 49214288, 49214288) >>> aa = aa.copy() >>> aa, bb, id(aa), id(bb) ([1, 2, 3], [1, 2, 3], 49213688, 49214288) >>> aa.append(3) >>> aa, bb, id(aa), id(bb) ([1, 2, 3, 3], [1, 2, 3], 49213688, 49214288)这种复制对象的方式叫做浅复制,因为它只能复制最外层的内容创建新的对象,而对于嵌套内的内容依然是指向关系:
>>> aaa = [1, [1, 2], 3] >>> bbb = aaa.copy() >>> aaa, bbb ([1, [1, 2], 3], [1, [1, 2], 3]) >>> aaa[0] = 4 >>> aaa[1][0] = 5 >>> aaa, bbb ([4, [5, 2], 3], [1, [5, 2], 3])由上可知bbb的外层元素因为是copy的缘故不受aaa影响,可是bbb[1]还是与aaa[1]指向同一个列表对象。如果需要将嵌套内的元素全部复制则需要用到copy标准库的deepcopy方法:
>>> aaa = [1, [1, 2], 3] >>> import copy >>> bbb = copy.deepcopy(aaa) >>> aaa, bbb ([1, [1, 2], 3], [1, [1, 2], 3]) >>> aaa[0] = 4 >>> aaa[1][0] = 5 >>> aaa, bbb ([4, [5, 2], 3], [1, [1, 2], 3])这种将嵌套内元素全部复制的方法叫深复制
经常能看到这样的函数定义:func(*args, **kwargs) 其中*前缀表示遍历args的元素作为参数依次传递给函数:
>>> a = "123" >>> b = (1, 2, 3) >>> c = [1, 2, 3] >>> d = {1: "11", 2: "22", 3: "33"} >>> print(*a, *b, *c, *d) 1 2 3 1 2 3 1 2 3 1 2 3而**前缀只跟字典类型,将字典中的key和value拿出来传递给函数:
>>> aa = {"a": "aa", "b": "bb"} >>> def f(b, a): ... print("b: {}, a: {}".format(b, a)) ... >>> f(**aa) b: bb, a: aa其中的f(**aa)就相当于f(a=”aa”, b=”bb”)
我们知道,像字符串,列表,字典等对象是可以用for来循环遍历的,然而我们自己建立一个普通的对象却不能用for遍历: test.py
class A: def __init__(self, data): self.data = data a = A("test") for c in a: print(a) λ python test.py Traceback (most recent call last): File "test.py", line 15, in <module> for c in a: TypeError: 'A' object is not iterable这是因为使用for时会默认调用iter()返回一个迭代器,迭代器包含next()函数来返回下一个元素。当迭代器中元素用尽后返回一个StopIteration异常告诉for循环该结束了:
>>> a = iter("123") >>> next(a) '1' >>> next(a) '2' >>> next(a) '3' >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration所以如果要让我们自己的对象含有迭代器特性,可以通过定义__iter__()方法使对象可迭代,通过定义__next__()方法定义每次迭代返回的元素: test.py
class A: def __init__(self, data): self.data = data self.index = 0 def __iter__(self): return self def __next__(self): if self.index == len(self.data): raise StopIteration self.index += 1 return self.data[self.index-1] a = A("test") for c in a: print(c) λ python test.py t e s t虽然python支持使用C语言风格的格式化方式,如:
>>> print("%d is a integer" % 2) 2 is a integer但是使用str.format()方法更强大便捷 普通情况下不用再指定需要代入的是什么类型,统一用 {} 就能搞定
>>> print("{}, {} and {}".format(1, '2', [3, 4, 5])) 1, 2 and [3, 4, 5]如果想得到repr()的内容使用{!r}:
>>> print("{!r}".format("Wow!!")) 'Wow!!'如果需要指定代入的参数,可以加上下标或者使用参数名:
>>> print("{2}, {0} and {1}".format(1, '2', {"w": 2})) {'w': 2}, 1 and 2 >>> print("{a}, {c} and {b}".format(a=1, b='2', c={"w": 2})) 1, {'w': 2} and 2 >>>可以获取参数的元素或属性:
>>> a = [1, 2, 3] >>> b = {"aa": 11, "bb": 22} >>> class C: ... value = 333 ... >>> c = C() >>> print("{0[2]}, {1[aa]}, {2.value}".format(a, b, c)) 3, 11, 333对齐及填充:
>>> print("{:<10}o".format("left")) left o >>> print("o{:>10}".format("right")) o right >>> print("o{:^10}o".format("center")) o center o >>> print("o{:*^10}o".format("center")) o**center**o >>> print("o{:>^10}o".format("center")) o>>center>>o >>> print("o{:A^10}o".format("center")) oAAcenterAAo控制小数位数等:
>>> print("{:.3f}".format(1234.44444)) 1234.444[1] Python中的除法 [2] python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
