读书笔记-ethan-funny/explore-python

Python2 的默认编码是 ascii,Python3 的默认编码是 utf-8

python2的input 本质上是使用 raw_input 实现的,如下:

def input(prompt):
    return (eval(raw_input(prompt)))

列表负索引是 numbers[4:0:-1]
当使用一个负数作为步长时,必须让左边索引大于右边索引;
对正数步长,从左向右取元素;对负数步长,从右向左取元素;

sort
sort 方法用于对列表进行排序,注意该方法会改变原来的列表,而不是返回新的排序列表,另外,sort 方法的返回值是空。
如果我们不想改变原列表,而是希望返回一个排序后的列表,可以使用 sorted 函数

a = (12,) # 在值后面再加一个逗号
a = (12) # int

字符串和元组一样,也是不可变的
字符串是不可变对象,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回。

d = {'name': 'ethan', 'age': 20}
    for i in d:
        if i == 'name':
            del d[i]

报错,RuntimeError: dictionary changed size during iteration
应该用for i in list(d.keys())

d1 = {1:2}
d2 = d1
d2 = {}
此时d1 d2的修改互不影响
除非用clear(),或者修改字典
原因: 当你将一个字典赋值给另一个变量时,你实际上是创建了一个新的引用指向同一个字典对象、

copy 方法实现的是浅复制(shallow copy)。它具有以下特点:
对可变对象的修改保持同步;
对不可变对象的修改保持独立;

和浅复制对应的是深复制(deep copy),它会创造出一个副本,跟原来的对象没有关系,可以通过 copy 模块的 deepcopy 函数来实现

多返回值的函数返回的result是个元组

默认参数应该使用不可变对象。下面的L会每次调用时候改变

>>> def add_to_list(L=[]):
...     L.append('END')
...     return L

它们在使用的时候是有顺序的,依次是必选参数、默认参数、可变参数*和关键字参数**。

reduce 函数的使用形式如下:
reduce(function, sequence[, initial])
如果有 initial,则作为初始值调用

注意在 python2 和 python3 中,map/reduce/filter 的返回值类型有所不同,python2 返回的是基本数据类型,而 python3 则返回了迭代器;

像上面这种情况,一个函数返回了一个内部函数,该内部函数引用了外部函数的相关参数和变量,我们把该返回的内部函数称为闭包(Closure)。
闭包的最大特点就是引用了自由变量,即使生成闭包的环境已经释放,闭包仍然存在。
我们应尽量避免在闭包中引用循环变量,或者后续会发生变化的变量。

函数 hello 被 makeitalic 装饰后,它的函数名称已经改变了
为了消除这样的副作用,Python 中的 functools 包提供了一个 wraps 的装饰器:

partial 的功能:固定函数参数,返回一个新的函数。

注意到,我们在上面定义的两个方法有一个共同点,就是它们的第一个参数都是 self,指向实例本身,也就是说它们是和实例绑定的函数,这也是我们称它们为方法而不是函数的原因。

type(obj):来获取对象的相应类型;
isinstance(obj, type):判断对象是否为指定的 type 类型的实例;
hasattr(obj, attr):判断对象是否具有指定属性/方法;
getattr(obj, attr[, default]) 获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;
setattr(obj, attr, value):设定该属性/方法的值,类似于 obj.attr=value;
dir(obj):可以获取相应对象的所有属性和方法名的列表:

classmethod 类方法,cls参数
在类中往往有一些方法跟类有关系,但是又不会改变类和实例状态的方法,这种方法是静态方法,我们使用 staticmethod 来装饰
staticmethod 静态方法,没有self,cls参数

静态方法使用 @staticmethod 装饰器,它是跟类有关系但在运行时又不需要实例和类参与的方法,可以使用类和实例来调用。

__new__方法

在 Python 中,当我们创建一个类的实例时,类会先调用 new(cls[, ...]) 来创建实例,然后 init 方法再对该实例(self)进行初始化。
关于 newinit 有几点需要注意:
new 是在 init 之前被调用的;
new 是类方法,init 是实例方法;
重载 new 方法,需要返回类的实例;

newinit 之前被调用,用来创建实例。
str 是用 print 和 str 显示的结果,repr 是直接显示的结果。
getitem 用类似 obj[key] 的方式对对象进行取值
getattr 用于获取不存在的属性 obj.attr
call 使得可以对实例进行调用
slots 魔法:限定允许绑定的属性.

上下文管理器

Point(3, 4) 生成了一个上下文管理器;
调用上下文管理器的 enter() 方法,并将 enter() 方法的返回值赋给 as 字句中的变量 pt;
执行语句体(指 with 语句包裹起来的代码块)内容,输出 distance;
不管执行过程中是否发生异常,都执行上下文管理器的 exit() 方法。exit() 方法负责执行『清理』工作,如释放资源,关闭文件等。如果执行过程没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用 exit(None, None, None);如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 exit(exc_type, exc_value, exc_traceback);
出现异常时,如果 exit(type, value, traceback) 返回 False 或 None,则会重新抛出异常,让 with 之外的语句逻辑来处理异常;如果返回 True,则忽略异常,不再对异常进行处理;

进程是正在运行的程序的实例。
由于每个进程都有各自的内存空间,数据栈等,所以只能使用进程间通讯(Inter-Process Communication, IPC),而不能直接共享信息。
Python 的 multiprocessing 模块封装了底层的实现机制,让我们可以更简单地编写多进程程序。

进程和线程的区别主要有:
进程之间是相互独立的,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,但互不影响;而同一个进程的多个线程是内存共享的,所有变量都由所有线程共享;
由于进程间是独立的,因此一个进程的崩溃不会影响到其他进程;而线程是包含在进程之内的,线程的崩溃就会引发进程的崩溃,继而导致同一进程内的其他线程也奔溃;

posted @ 2024-01-16 22:53  种树人  阅读(5)  评论(0编辑  收藏  举报