目录
1.变量总结
1.1 变量定义
在 Python 中,「变量」更准确叫法是「名字」,赋值操作 = 就是把一个名字绑定到一个对象上。就像给对象添加一个标签。
把变量 a 赋值给另外一个变量 b,相当于在对象 2 上贴了 a,b 两个标签,通过这两个变量都可以对对象 2 进行操作。
关于深浅拷贝具体看https://blog.csdn.net/zangba9624/article/details/86584513
变量本身没有类型信息,类型信息存储在对象中,这和C/C++中的变量有非常大的出入(C中的变量是一段内存区域)
1.2 id()
id方法的返回值就是对象的内存地址。python中会为每个出现的对象分配内存。
1.3 变量作用域
- L (Local) 局部作用域
- E (Enclosing) 闭包函数外的函数中
- G (Global) 全局作用域
- B (Built-in) 内建作用域
以 L --> E --> G -->B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
代码规范:全局变量字母全部大写,局部变量变量名小写。
1.3.1 如果函数内部无global关键字
global用于声明全局变量
优先读取局部变量,如果没有局部变量则读取全局变量,此时无法对全局变量进行赋值。
但是对于可变对象可以对内部元素进行操作(如append()pop()),这些操作会改变全局变量.
1.3.2 函数内部有global关键字
如果函数中有global关键字,变量本质上就是全局变量,可读取可赋值。
1.3.3 nonlocal关键词
nonlocal适用于嵌套函数中内部函数修改外部变量的值,用来声明外层的局部变量
如果没有使用以上关键字,对全局变量或者外部变量进行修改,python会默认将全局变量隐藏起来
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
输出结果
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
1.3.4 闭包Closure
闭包的定义:如果在一个内部函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)
set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
要创建一个set,需要提供一个list作为输入集合:
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
重复元素在set中自动被过滤,并且不一定是有序的
frozenset() 不能追加,不能修改的集合,不能删除。
s.add(key)
方法可以添加元素到set中,可以重复添加,但不会有效果
s.remove(key)
方法可以删除指定元素,如果指定的参数原集合没有则会报错
s.discard(key
) 方法可以删除指定元素,指定参数在原集合里没有,但是这里不会报错
s.clear() 清空集合 字典的清空结果是{},集合的清空结果是set()
s.copy()
s.pop() 随机删除
s1.intersection(s2) 交集 s1&s2
s1.union(s2) 并集s1|s2
s1.difference(s2) 差集 s1-s2
s1.symmetric_difference(s2) 交叉补集 s1^s2
s1.isdisjoint(s2) 两个集合取交集是空集,那么返回True,不是空集返回False.
s1.issubset(s2) 判断s1是不是s2的子集
s1.issuperset(s2) 判断s1是不是包含s2,superset:父集,超集
后续操作将修改s1
s1.difference_update(s2) 将s1更新为s1和s2的差集
s1.intersection_update(s2) s1 = s1 & s2
s1.symmetric_difference_update(s2) s1 = s1 ^ s2
s1.update(s2) 将集合s2结果添加集合s1,
与s1.union(s2)的区别在于 修改了s1
add()只能增加单个值, update()可以传可迭代对象,更新多个值
两个set可以做数学意义上的交集、并集等操作
交集:
li1 = ["nicholas","pony","robin","jack"]
li2 = ["nicholas","charles","Richard "]
s1 = set(li1)
s2 = set(li2)
v = s1.intersection(s2)
#这里也可以这样写
#v = s1&s2
并集
v = s1.union(s2)
差集
v = s1.difference(s2)
或者
v=s1 - s2
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
交叉补集
li1 = ["nicholas","pony","robin","jack"]
li2 = ["nicholas","charles","Richard ","jack"]
s1 = set(li1)
s2 = set(li2)
v = s1.symmetric_difference(s2)
print(v)
print(s1 ^ s2)
输出
{'robin', 'Richard ', 'charles', 'pony'}
{'robin', 'Richard ', 'charles', 'pony'}
set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。
不可变对象
str是不变对象,而list是可变对象
上面我们讲了,str是不变对象,而list是可变对象。
对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:
>>> a = ['c', 'b', 'a']
>>> a.sort()
>>> a
['a', 'b', 'c']
对于不可变对象,比如str,对str进行操作:
>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'
对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的
集合的元素必须是不可变类型
例子
set1= {"hello",[1,2]}
print(set1)
输出
TypeError: unhashable type: 'list'
输出结果报错,无法对列表进行哈希化,但在创建集合的时候可以使用列表