深入学习 Python 中的几个知识点

之前只是简单会用,现在重新按照官网的 Tutorial 来学

python 中一切变量都是引用(指针)

对于内置类型来说,有不可变类型和可变类型之分,不可变类型的意思是不能重新赋值,需要重新生成一个新对象,因此使用 operator= 相当于是做深拷贝。可变类型则不同, operator= 只是浅拷贝。
可变对象: list , dict, set
不可变对象:tuple, string, int, float, bool

最简单的例子:

def func(ll):
    ll.append(42)

ll = [1, 2]
func(ll)
print(str(ll))  #输出 [1, 2, 42]

虽然函数传参是 pass by value,但是那只是指针值的value
对于 list 来说,使用[:]切片操作依然是shallow copy。

a=[1,2,3]
b=a[:] # [1,2,3]
a is b # False

a=[[42,43],2,3]
b=a[:] # [[42,43],2,3]
a is b # False
a[0] is b[0] # True
a[0].append(44)
b #[[42,43,44],2,3]

因为这种情况的存在,Python中的赋值,我个人分成了三层:
1 只建立新变量和新对象的关联 (可变变量之间的赋值)
2 浅拷贝 (不可变变量之间的赋值,含有可变变量的可变变量的切片等操作)
3 深拷贝 (只含有不可变变量的可变变量切片等操作,显式调用deep_copy等函数)

#情况1
a=[1,2,3]
b=a
a is b # True
b.append(4)
a # [1,2,3,4]

#情况2-1
a="ccccc"
b=a
a is b # True 当然这里也有 interning 的问题
b="ddddd"
a is b # False

#情况2-2
a=[[1,2,3],42,43]
b=a[:]
a is b # False
b[0].append(4)
a # [[1,2,3,4],42,43]

#情况3
a=[1,2,3,4]
b=a[:]
a[0]=42
b # [1,2,3,4

list comprehensions

这个功能就是用简单的方法来生成一个 list
例子:

squares = list(map(lambda x: x**2, range(10)))  # 这里不能用 [],因为那样就是在 list 里面存入一个 map 对象
squares = [x**2 for x in range(10)]

vec = [[1,2,3], [4,5,6], [7,8,9]]
[num for elem in vec for num in elem]

# 转置矩阵
matrix = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
newmatrix = [[row[i] for row in matrix] for i in range(4)]

tuple 中的对象引用不可更改,但是其中存入的 mutable object 本身可以更改,因此使用 tuple 作为 dict 的 key 时,里面不能包含 mutable object

如题

function object 和 method object

class Foo:
    def f(self):
        pass

val = Foo()
print(type(val.f)) # <method object>
print(type(Foo.f)) # <function object>

对某个 object 进行 method 调用其实相当于 Foo.f(val),实测也是可以操作的。

继承关系下的 class.__init__() 方法调用

当子类未定义 __init__ 方法时,会调用父类的 __init__ 方法。当子类定义时,则父类就不会被调用。因此可以在子类调用开始处显式调用。在看着一块的时候,有一个感受:把class的 __init__ 当成一个简单方法即可,只需要传入一个class指针作为self参数即可。

for ... in 循环时候的具体动作

1) 先判断对象是否为可迭代对象,不是的话直接报错,抛出TypeError异常,是的话,调用 __iter__方法,返回一个迭代器
2) 不断地调用迭代器的__next__方法,每次按序返回迭代器中的一个值
3) 迭代到最后,没有更多元素了,就抛出异常 StopIteration,这个异常 python 自己会处理,不会暴露给开发者

def func(n):
    yield n*2

g = func(2) #此时 g 是 func 返回值,g 类型是 generator。但是经过测试, `g.__iter__()` 返回的还是一个 generator,就是它自己。而 generator 是带有 `__next__() `的类,因此和传统的迭代器兼容了

posted on 2018-11-09 10:11  daghlny  阅读(223)  评论(0编辑  收藏  举报

导航