- 变量不是盒子,变量是便利贴:把变量s分配给对象xxx
==
比较两个对象的值(存储的数据),is
比较对象的标识(identity)is
比==
快,因为它不能被重载,Python可以直接比较两个整数ID- 一般
is
都用于和None
做比较,但==
也能有同样的效果,只是速度慢一些
- 浅拷贝复制最外层容器,覆盖的是与源容器中的引用,如果有可变项,则会有意想不到的问题,这个时候应该使用深拷贝
- Python唯一支持的参数传递模式是共享传参(call by sharing),由此函数可能会修改作为参数传入的可变对象,而不改变其标识(it cannot altogether replace an object with another)
"""
>>> bus1 = HauntedBus(['Alice', 'Bill'])
>>> bus1.passengers
['Alice', 'Bill']
>>> bus1.pick('Charlie')
>>> bus1.drop('Alice')
>>> bus1.passengers
['Bill', 'Charlie']
>>> bus2 = HauntedBus()
>>> bus2.pick('Carrie')
>>> bus2.passengers
['Carrie']
>>> bus3 = HauntedBus()
>>> bus3.passengers
['Carrie']
>>> bus3.pick('Dave')
>>> bus2.passengers
['Carrie', 'Dave']
>>> bus2.passengers is bus3.passengers
True
>>> bus1.passengers
['Bill', 'Charlie']
>>> dir(HauntedBus.__init__) # doctest: +ELLIPSIS
['__annotations__', '__call__', ..., '__defaults__', ...]
>>> HauntedBus.__init__.__defaults__
(['Carrie', 'Dave'],)
>>> HauntedBus.__init__.__defaults__[0] is bus2.passengers
True
"""
class HauntedBus:
"""A bus model haunted by ghost passengers"""
def __init__(self, passengers=[]):
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
- 创建对象时没有传入passengers,导致对象去引用类创建时产生的默认列表,变量成为参数默认值的别名
- del和垃圾回收:Python垃圾回收使用的主要算法是引用计数,当其归零时立即被销毁
- 可以通过
weakref.finalize
注册回调函数,在销毁对象时调用- 传入这个函数的引用是弱引用,不会增加对象的引用计数
>>> import weakref >>> s1 = {1, 2, 3} >>> s2 = s1 >>> def bye(): ... print('...like tears in the rain.') ... >>> ender = weakref.finalize(s1, bye) >>> ender.alive True >>> del s1 >>> ender.alive True >>> s2 = 'spam' ...like tears in the rain. >>> ender.alive False
- 传入这个函数的引用是弱引用,不会增加对象的引用计数
- 可以通过
- 变量作用域
- Python does not require you to declare variables, but assumes that a variable assigned in the body of a function is local. This is much better than the behavior of JavaScript, which does not require variable declarations either, but if you do forget to declare that a variable is local (with var), you may clobber a global variable without knowing.
- local, global, nonlocal
- When a function is defined, the Python bytecode compiler determines how to fetch a variable x that appears in it, based on these rules:
- If there is a global x declaration, x comes from and is assigned to the x global variable module
- If there is a nonlocal x declaration, x comes from and is assigned to the x local variable of the nearest surrounding function where x is defined.
- If x is a parameter or is assigned a value in the function body, then x is the local variable.
- If x is referenced but is not assigned and is not a parameter:
- x will be looked up in the local scopes of the surrounding function bodies (nonlocal scopes).
- If not found in surrounding scopes, it will be read from the module global scope.
- If not found in the global scope, it will be read from
__builtins__.__dict__
.
>>> def f1(a):
... print(a)
... print(b)
...
>>> f1(3)
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in f1
NameError: name 'b' is not defined
>>> b = 6
>>> f1(3)
3
6
>>> def f2(a):
... print(a)
... print(b)
... b = 9
...
>>> f2(3)
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in f2
UnboundLocalError: local variable 'b' referenced before assignment
# tag::F1_DIS[]
>>> from dis import dis
>>> dis(f1)
2 0 LOAD_GLOBAL 0 (print) <1>
3 LOAD_FAST 0 (a) <2>
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
3 10 LOAD_GLOBAL 0 (print)
13 LOAD_GLOBAL 1 (b) <3>
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
19 POP_TOP
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
# end::F1_DIS[]
# tag::F2_DIS[]
>>> dis(f2)
2 0 LOAD_GLOBAL 0 (print)
3 LOAD_FAST 0 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
3 10 LOAD_GLOBAL 0 (print)
13 LOAD_FAST 1 (b) <1>
16 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
19 POP_TOP
4 20 LOAD_CONST 1 (9)
23 STORE_FAST 1 (b)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
# end::F2_DIS[]
PREVIOUS字典和集合
NEXTCS162Project1