int string dict list tuple
dict list 是可变的
int string tuple是不可变的
本质 可以作为字典的key,就是不可变的
3.==和is 的区别
is比较的是id 而‘==’比较的是值
import copy
a = [1,['m']]
b = a b采用赋值的方式
c = copy.copy(a) c采用浅拷贝
d = copy.deepcopy(a) d采用深拷贝
e = copy.copy(a) e采用浅拷贝
f = copy.deepcopy(a) f采用深拷贝
#
#
无论是赋值,深浅拷贝,可以得到相同的值
print("a===", a)
print("b====",b)
print("c====", c)
print("d===", d)
print("e===", e)
print("f=====", f)
#
a.append(2) 对父级对象修改,增加一个值
print("a===", a)
print("b====",b)
print("c====", c)
print("d===", d)
print("e===", e)
print("f=====", f)
#
a[1].append('n') 对内部对象进行修改
从结果看出赋值的,以及浅拷贝的收到了影响
print("a===", a) [1,['m', 'n'], 2]
print("b====",b) [1,['m', 'n'], 2]
print("c====", c) [1,['m', 'n']]
print("d===", d) [1,['m']]
print("e===", e) [1,['m', 'n']]
print("f=====", f) [1,['m']]
dict 中的 key 和set 中的元素值都是 可hash的。字典是通过哈希表实现的。也就是说,字典是一个数组,而数组的索引是经过哈希函数处理后得到的。哈希函数的目的是使键均匀地分布在数组
Python 2.2 及其之前经典类,没有基类,例如:
class lei:
pass
Python新式类,需要显式继承自object,即使不显式继承也会默认继承自object,例如:
class lei(object):
pass
经典类在类多重继承的时候是采用从左到右深度优先原则匹配方法的
而新式类是采用C3算法
经典类没有MRO和instance.mro()调用的
(1)子类的初始化的时候,用传统的调用直接用父类调用__init__()
(2)新式类(就是父类继承object类),子类的初始化的时候
(3)除了直接用父类调用__init__(),还可以用super这个关键字
子类名称和父类名称相同 重写
静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互,即在静态方法中,不会涉及到类中的方法和属性的操作。
类方法是将类本身作为对象进行操作的方法。它和静态方法的区别在于:不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来
进程就是一个程序在一个数据集上的一次动态执行过程。线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同 一内存空间,
当进程退出时该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其它线程共享进程所拥有的全部资源,但是其本身基本上不拥
有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。
线程:共享变量 queue
进程:queue pipe实现进程间通信
async 用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,await 用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。
await 后面只能跟异步程序或有__await__属性的对象,因为异步程序与一般程序不同。
假设有两个异步函数async a,async b,a中的某一步有await,当程序碰到关键字await b()后,异步程序挂起后去执行另一个异步b程序,
就是从函数内部跳出去执行其他函数,当挂起条件消失后,不管b是否执行完,要马上从b程序中跳出来,回到原程序执行原来的操作。
如果await后面跟的b函数不是异步函数,那么操作就只能等b执行完再返回,无法在b执行的过程中返回。
如果要在b执行完才返回,也就不需要用await关键字了,直接调用b函数就行。所以这就需要await后面跟的是异步函数了。
在一个异步函数中,可以不止一次挂起,也就是可以用多个await。
在运行时替换方法、属性
在不修改源代码的情况下对程序本身添加之前没有的功能
在运行时对象中添加补丁,而不是在磁盘中的源代码上
#使用 type() 函数创建类
CLanguage = type("CLanguage",(object,),dict(say = say, name = "C语言中文网"))
#创建一个 CLanguage 实例对象
clangs = CLanguage()
#调用 say() 方法和 name 属性
clangs.say()
print(clangs.name)
此程序中通过 type() 创建了类,其类名为 CLanguage,继承自 objects 类,且该类中还包含一个 say() 方法和一个 name 属性
def multi():
return [lambda x: i * x for i in range(4)]
print([m(3) for m in multi()])
# 正确答案是[9,9,9,9],而不是[0,3,6,9]产生的原因是Python的闭包的后期绑定导致的,这意味着在闭包中的变量是在内部函数被调用的时候被查找的,
# 因为,最后函数被调用的时候,for循环已经完成, i 的值最后是3,因此每一个返回值的i都是3,所以最后的结果是[9,9,9,9]
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x
>>
1 1 1
1 2 1
3 2 3
使你困惑或是惊奇的是关于最后一行的输出是 3 2 3 而不是 3 2 1。
为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变?
这个答案的关键是,在 Python中,类变量在内部是作为字典处理的。
如果一个变量的名字没有在当前类的字典中发现,将搜索祖先类(比如父类)直到被引用的变量名被找到.
首先,在父类中设置 x = 1 会使得类变量 x 在引用该类和其任何子类中的值为 1。
这就是因为第一个 print 语句的输出是 1 1 1
然后,如果任何它的子类重写了该值(例如,我们执行语句 Child1.x = 2)该值仅仅在子类中被改变
。这就是为什么第二个 print 语句的输出是 1 2 1
最后,如果该值在父类中被改变(例如,我们执行语句 Parent.x = 3),这个改变会影响
到任何未重写该值的子类当中的值(在这个示例中被影响的子类是 Child2)。
这就是为什么第三个 print 输出是 3 2 3
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
>>
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
许多人会错误的认为 list1 应该等于 [10] 以及 list3 应该等于 ['a']。认为 list 的参数会在 extendList 每次被调用的时候会被设置成它的默认值 []。
尽管如此,实际发生的事情是,新的默认列表仅仅只在函数被定义时创建一次。随后当 extendList 没有被指定的列表参数调用的时候,其使用的是同一个列表。这就是为什么当函数被定义的时候,表达式是用默认参数被计算,而不是它被调用的时候。
因此,list1 和 list3 是操作的相同的列表。而list2是操作的它创建的独立的列表(通过传递它自己的空列表作为list参数的值)
所以这一点一定要切记切记.下面我们把list置为None就可以避免一些麻烦了