>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
>>> a = []
>>> b = []
>>> a is b
False
>>> a = tuple()
>>> b = tuple()
>>> a is b
True
is 用来check两个对象是否是同一个, 可以理解为是同一个地址的对象,是引用的测试
== 是用来比较两个对象的值
当启动python时候,会分配-5到256的对象。这是因为这些值使用的很频繁
The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you just get back a reference to the existing object. So it should be possible to change the value of 1. I suspect the behavior of Python, in this case, is undefine
>>> id(256)
10922528
>>> a = 256
>>> b = 256
>>> id(a)
10922528
>>> id(b)
10922528
>>> id(257)
140084850247312
>>> x = 257
>>> y = 257
>>> id(x)
140084850247440
>>> id(y)
140084850247344
同样的优化适应于不可变的对象,比如空tuple,而list是可变的,所以is判断为假。
Both a and b refer to the same object when initialized with same value in the same line.
>>> a, b = 257, 257
>>> id(a)
140640774013296
>>> id(b)
140640774013296
>>> a = 257
>>> b = 257
>>> id(a)
140640774013392
>>> id(b)
140640774013488
python中字典的相等性测试是by equivalence, not identity. 尽管5,5.0,5 + 0j都是不同对象,但是都相等
>>> 5 == 5.0 == 5 + 0j
True
>>> 5 is not 5.0 is not 5 + 0j
True
>>> some_dict = {}
>>> some_dict[5.0] = "Ruby"
>>> 5.0 in some_dict
True
>>> (5 in some_dict) and (5 + 0j in some_dict)
True
内心深处,我们都一样
class WTF:
pass
>>> WTF() == WTF() # two different instances can't be equal
False
>>> WTF() is WTF() # identities are also different
False
>>> hash(WTF()) == hash(WTF()) # hashes _should_ be different as well
True
>>> id(WTF()) == id(WTF())
True
未完待续
keep trying..
def some_func():
try:
return 'from_try'
finally:
return 'from_finally'
def another_func():
for _ in range(3):
try:
continue
finally:
print("Finally!")
def one_more_func(): # A gotcha!
try:
for i in range(3):
try:
1 / i
except ZeroDivisionError:
# Let's throw it here and handle it outside for loop
raise ZeroDivisionError("A trivial divide by zero error")
finally:
print("Iteration", i)
break
except ZeroDivisionError as e:
print("Zero division error occurred", e)
>>> some_func()
'from_finally'
>>> another_func()
Finally!
Finally!
Finally!
>>> 1 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> one_more_func()
Iteration 0
>>> board = [['']*3 for _ in range(3)]
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['', '', ''], ['', '', '']]
output function
funcs = []
results = []
for x in range(7):
def some_func():
return x
funcs.append(some_func)
results.append(some_func()) # note the function call here
funcs_results = [func() for func in funcs]
>>> results
[0, 1, 2, 3, 4, 5, 6]
>>> funcs_results
[6, 6, 6, 6, 6, 6, 6]
>>> powers_of_x = [lambda x: x**i for i in range(10)]
>>> [f(2) for f in powers_of_x]
[512, 512, 512, 512, 512, 512, 512, 512, 512, 512]
When defining a function inside a loop that uses the loop variable in its body, the loop function's closure is bound to the variable, not its value. So all of the functions use the latest value assigned to the variable for computation.
To get the desired behavior you can pass in the loop variable as a named variable to the function. Why does this work? Because this will define the variable again within the function's scope.
funcs = []
for x in range(7):
def some_func(x=x):
return x
funcs.append(some_func)
>>> funcs_results = [func() for func in funcs]
>>> funcs_results
[0, 1, 2, 3, 4, 5, 6]
list删除
list_1 = [1, 2, 3, 4]
list_2 = [1, 2, 3, 4]
list_3 = [1, 2, 3, 4]
list_4 = [1, 2, 3, 4]
for idx, item in enumerate(list_1):
del item
for idx, item in enumerate(list_2):
list_2.remove(item)
for idx, item in enumerate(list_3[:]):
list_3.remove(item)
for idx, item in enumerate(list_4):
list_4.pop(idx)
>>> list_1
[1, 2, 3, 4]
>>> list_2
[2, 4]
>>> list_3
[]
>>> list_4
[2, 4]
在遍历的过程中改变对象不是好主意。好的方式是通过迭代拷贝的对象,正如list_3[:]所做的。
>>> some_list = [1, 2, 3, 4]
>>> id(some_list)
139798789457608
>>> id(some_list[:]) # Notice that python creates new object for sliced list.
139798779601192
del remove 和 pop的区别
del var_name 就是 removes the binding of the var_name from the local or global namespace (That's why the list_1 is unaffected).
remove removes the first matching value, not a specific index, raises ValueError if the value is not found.
pop removes the element at a specific index and returns it, raises IndexError if an invalid index is specified
for x in range(7):
if x == 6:
print(x, ': for x inside loop')
print(x, ': x in global')
6 : for x inside loop
6 : x in global
# This time let's initialize x first
x = -1
for x in range(7):
if x == 6:
print(x, ': for x inside loop')
print(x, ': x in global')
# python 2
>>> x = 1
>>> print([x for x in range(5)])
[0, 1, 2, 3, 4]
>>> print(x)
4
# python3
>>> x = 1
>>> print([x for x in range(5)])
[0, 1, 2, 3, 4]
>>> print(x)
1
In Python, for-loops use the scope they exist in and leave their defined loop-variable behind. This also applies if we explicitly defined the for-loop variable in the global namespace before. In this case, it will rebind the existing variable.
Beware of default mutable arguments!
def some_func(default_arg=[]):
default_arg.append("some_string")
return default_arg
>>> some_func()
['some_string']
>>> some_func()
['some_string', 'some_string']
>>> some_func([])
['some_string']
>>> some_func()
['some_string', 'some_string', 'some_string']
>> some_func.__defaults__ #This will show the default argument values for the function
([],)
>>> some_func()
>>> some_func.__defaults__
(['some_string'],)
>>> some_func()
>>> some_func.__defaults__
(['some_string', 'some_string'],)
>>> some_func([])
>>> some_func.__defaults__
(['some_string', 'some_string'],)
使用None来避免
def some_func(default_arg=None):
if default_arg is None:
default_arg = []
default_arg.append("some_string")
return default_arg
Catching the Exceptions
some_list = [1, 2, 3]
try:
# This should raise an ``IndexError``
print(some_list[4])
except IndexError, ValueError:
print("Caught!")
try:
# This should raise a ``ValueError``
some_list.remove(4)
except IndexError, ValueError:
print("Caught again!")
# output 2.x
Caught!
ValueError: list.remove(x): x not in list
# output 3.x
File "<input>", line 3
except IndexError, ValueError:
^
SyntaxError: invalid syntax
对于python2
some_list = [1, 2, 3]
try:
# This should raise a ``ValueError``
some_list.remove(4)
except (IndexError, ValueError), e:
print("Caught again!")
print(e)
资料来源
is 和 ==
当启动python时候,会分配-5到256的对象。这是因为这些值使用的很频繁
同样的优化适应于不可变的对象,比如空tuple,而list是可变的,所以is判断为假。
Both a and b refer to the same object when initialized with same value in the same line.
hash
python中字典的相等性测试是by equivalence, not identity. 尽管5,5.0,5 + 0j都是不同对象,但是都相等
内心深处,我们都一样
未完待续
keep trying..
for
和这个类比:
for 语句的定义:
{exprlist} = {next_value} 在每次迭代的时候都会呗执行。 上面的代码执行:
list 坑
我们可以这样避免:
output function
list删除
在遍历的过程中改变对象不是好主意。好的方式是通过迭代拷贝的对象,正如list_3[:]所做的。
del remove 和 pop的区别
del var_name 就是 removes the binding of the var_name from the local or global namespace (That's why the list_1 is unaffected).
remove removes the first matching value, not a specific index, raises ValueError if the value is not found.
pop removes the element at a specific index and returns it, raises IndexError if an invalid index is specified
Why the output is [2, 4]?
Loop variables leaking out!
Beware of default mutable arguments!
使用None来避免
Catching the Exceptions
对于python2
对于python3
Wild imports *