一、Python中的变量是什么 Python和java中的变量本质不一样。java中的变量是一个盒子,声明时已经说明了盒子的类型,大小。Python的变量实质是一个指针。也可以理解成一个便利贴。可以贴在任何类型上面。
>>> a = [1, 2, 3] >>> b = a >>> a.append(4) #操作a实际上也就是操作b >>> b [1, 2, 3, 4]
如果把变量想象为盒子, 那么无法解释 Python 中的赋值;应该把变量视作便利贴, 这样就好解释了。先 生成变量,才把便利贴贴上。
为了理解Python中的赋值语句,应该始终先读右边,对象在右边创建或获取,在此之后左边的变量才会绑定到对象上,这就像为对象贴上标注。
二、==和is的区别 == 运算符比较两个对象的值(对象中保存的数据) , 而 is 比较对象的标识。
a = [1,2,3] b = a print (id(a), id(b)) print (a is b)
通常, 我们关注的是值, 而不是标识, 因此 Python 代码中 == 出现的频率比 is 高。然而, 在变量和单例值之间比较时, 应该使用 is。
class People: pass
person = People() if type(person) is People: print ("yes")
is 运算符比 == 速度快, 因为它不能重载, 所以 Python 不用寻找并调用特殊方法, 而是直接比较两个整数 ID。 而 a == b 是语法糖, 等同于a.__eq__(b)。
三、del语句和垃圾回收 del 语句删除名称, 而不是对象。 del 命令可能会导致对象被当作垃圾回收, 但是仅当删除的变量保存的是对象的最后一个引用, 或者无法得到对象时。 重新绑定也可能会导致对象的引用数量归零, 导致对象被销毁。
如果两个对象相互引用, 当它们的引用只存在二者之间时, 垃圾回收程序会判定它们都无法获取, 进而把它们都销毁。
在 CPython 中, 垃圾回收使用的主要算法是引用计数。 实际上, 每个对象都会统计有多少引用指向自己。 当引用计数归零时, 对象立即就被销毁: CPython 会在对象上调用 __del__ 方法(如果定义了) , 然后释放分配给对象的内存。 CPython 2.0 增加了分代垃圾回收算法。
a = object() b = a del a print(b) print(a) #无法输出a对象 四、函数的参数作为引用时 Python 唯一支持的参数传递模式是共享传参(call by sharing) 。 多数面向对象语言都采用这一模式, 包括 Ruby、 Smalltalk 和 Java(Java 的引用类型是这样, 基本类型按值传参) 。 共享传参指函数的各个形式参数获得实参中各个引用的副本。 也就是说, 函数内部的形参是实参的别名。 这种方案的结果是, 函数可能会修改作为参数传入的可变对象, 但是无法修改那些对象的标识(即不能把一个对象替换成另一个对象) 。
>>> def f(a, b): ... a += b ... return a ... >>> x = 1 >>> y = 2 >>> f(x, y) 3 >>> x, y (1, 2) >>> a = [1, 2] #可变对象 >>> b = [3, 4] >>> f(a, b) [1, 2, 3, 4] >>> a, b ([1, 2, 3, 4], [3, 4]) >>> t = (10, 20) >>> u = (30, 40) >>> f(t, u) (10, 20, 30, 40) >>> t, u ((10, 20), (30, 40)) 2、不要使用可变类型作为参数的默认值 可选参数可以有默认值, 这是 Python 函数定义的一个很棒的特性, 这样我们的 API 在进化的同时能保证向后兼容。 然而, 我们应该避免使用可变的对象作为参数的默认值。
class Company: def __init__(self, name, staffs=[]): self.name = name self.staffs = staffs def add(self, staff_name): self.staffs.append(staff_name) def remove(self, staff_name): self.staffs.remove(staff_name)
if __name__ == "__main__": com1 = Company("com1", ["tian1", "tian2"]) com1.add("tian3") com1.remove("tian1") # print (com1.staffs)
com2 = Company("com2") com2.add("tian") # print(com2.staffs) # print (Company.__init__.__defaults__) #(['tian'],) # com3 = Company("com3") com3.add("tian5") print (com2.staffs) #['tian', 'tian5'] print (com3.staffs) #['tian', 'tian5'] print (com2.staffs is com3.staffs) #True 问题在于, 没有指定初始员工的 Company实例会共 #享同一个乘客列表 # #com2和com3共用一个默认的空list 更多Python学习技术可关注:itheimaGZ获取(工囧号) |
|