内容:
5.python中set和frozenset方法和区别
6.python函数基础以及函数参数简解
7.python的文件操作方法
8.python常用内置函数
python基础知识
5.python中set和frozenset方法和区别
set(可变集合)与frozenset(不可变集合)的区别:
set无序排序且不重复,是可变的,有add(),remove()等方法。既然是可变的,所以它不存在哈希值。
基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交集), difference(差集)和sysmmetric difference(对称差集)等数学运算.
sets 支持 x in set, len(set),和 for x in set。作为一个无序的集合,sets不记录元素位置或者插入点。
因此,sets不支持 indexing, 或其它类序列的操作。
frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。
一、集合的创建
set()和 frozenset()工厂函数分别用来生成可变和不可变的集合。如果不提供任何参数,默认会生成空集合。
如果提供一个参数,则该参数必须是可迭代的,即,一个序列,或迭代器,或支持迭代的一个对象,例如:一个列表或一个字典。
s=set('cheeseshop') 使用工厂方法创建
s
{'h', 'c', 'o', 's', 'e', 'p'}
type(s)
<type 'set'>
s={'chessseshop','bookshop'}直接创建,类似于list的[]和dict的{},不同于dict的是其中的值,set会将其中的元素转换为元组
s
{'bookshop', 'chessseshop'}
type(s)
<type 'set'>
不可变集合创建:
t=frozenset('bookshop')
t
frozenset({'h', 'o', 's', 'b', 'p', 'k'})
二、更新可变集合
用各种集合内建的方法和操作符添加和删除集合的成员:
s.add('z') #添加
s
set(['c', 'e', 'h', 'o', 'p', 's', 'z'])
s.update('pypi') #添加
s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y', 'z'])
s.remove('z') #删除
s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
s -= set('pypi')#删除
s
set(['c', 'e', 'h', 'o', 's'])
del s #删除集合
只有可变集合能被修改。试图修改不可变集合会引发异常。
t.add('z')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'frozenset' object has no attribute 'add'
三、成员关系 (in, not in)
'k' in s
False
'k' in t
True
'c' not in t
True
四、集合等价/不等价
s == t
False
s != t
True
u = frozenset(s)
s == u
True
set('posh') == set('shop')
True
五、子集/超集
set('shop') < set('cheeseshop')
True
set('bookshop') >= set('shop')
True
六、遍历访问集合中的值(可变集合和非可变都支持)
s=set('cheeseshop')
s
{'h', 'c', 'o', 's', 'e', 'p'}
for i in s:
print(i)
h
c
o
s
e
p
t=frozenset('bookshop')
t
frozenset({'h', 'o', 's', 'b', 'p', 'k'})
for i in t:
print(i)
h
o
s
b
p
k
七、集合类型操作符(所有的集合类型)
1.联合( | )
1 两个集合的联合是一个新集合,该集合中的每个元素都至少是其中一个集合的成员,即,
属于两个集合其中之一的成员。联合符号有一个等价的方法,union().
2 >>> s | t
3 set(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's'])
2.交集( & )
1 你可以把交集操作比做集合的 AND(或合取)操作。两个集合的交集是一个新集合,
该集合中的每个元素同时是两个集合中的成员,即,属于两个集合的成员。交集符号有一个等价的方法,intersection()
2 >>> s & t
3 set(['h', 's', 'o', 'p']
3.差补/相对补集( – )
1 两个集合(s 和 t)的差补或相对补集是指一个集合 C,该集合中的元素,只属于集合 s,
而不属于集合 t。差符号有一个等价的方法,difference().
2 >>> s - t
3 set(['c', 'e'])
4.对称差分( ^ )
1 和其他的布尔集合操作相似, 对称差分是集合的 XOR(又称"异或 ").
2 两个集合(s 和 t)的对称差分是指另外一个集合 C,该集合中的元素,只能是属于集合 s 或者集合 t 的成员,
不能同时属于两个集合。对称差分有一个等价的方法,symmetric_difference().
3 >>> s ^ t
4 set(['k', 'b', 'e', 'c'])
5.混合集合类型操作
1 上面的示例中,左边的 s 是可变集合,而右边的 t 是一个不可变集合.
注意上面使用集合操作运算符所产生的仍然是可变集合,但是如果左右操作数的顺序反过来,结果就不一样了
2 >>> t | s
3 frozenset(['c', 'b', 'e', 'h', 'k', 'o', 'p', 's'])
4 >>> t ^ s
5 frozenset(['c', 'b', 'e', 'k'])
6 >>> t - s frozenset(['k', 'b'])
如果左右两个操作数的类型相同, 既都是可变集合或不可变集合, 则所产生的结果类型是相同的,
但如果左右两个操作数的类型不相同(左操作数是 set,右操作数是 frozenset,或相反情况),
则所产生的结果类型与左操作数的类型相同。
八、可变集合类型的方法
1 s.update(t) 用 t 中的元素修改 s, 即,s 现在包含 s 或 t 的成员
2 s.intersection_update(t) s 中的成员是共同属于 s 和 t 的元素。
3 s.difference_update(t) s 中的成员是属于 s 但不包含在 t 中的元素
4 s.symmetric_difference_update(t) s 中的成员更新为那些包含在 s 或 t 中,但不 是 s
5 和 t 共有的元素
6 s.add(obj) 在集合 s 中添加对象 obj
7 s.remove(obj) 从集合 s 中删除对象 obj;如果 obj 不是集合 s 中的元素(obj not in s),将引发 KeyError 错误
8 s.discard(obj) 如果 obj 是集合 s 中的元素,从集合 s 中删除对象 obj;
9 s.pop() 删除集合 s 中的任意一个对象,并返回它
10 s.clear() 删除集合 s 中的所有元素
九、集合类型操作符、函数和方法
函数/方法名 等价运算符 说明
所有集合类型:
1 len(s) 集合基数: 集合 s 中元素的个数
2 set([obj]) 可变集合工厂函数; obj 必须是支持迭代的,由 obj 中
3 的元素创建集合,否则创建一个空集合
4 frozenset([obj]) 不可变集合工厂函数; 执行方式和 set()方法相同,
5 但它返回的是不可变集合
6 obj in s 成员测试:obj 是 s 中的一个元素吗?
7 obj not in s 非成员测试:obj 不是 s 中的一个元素吗?
8 s == t 等价测试: 测试 s 和 t 是否具有相同的元素?
9 s != t 不等价测试: 与==相反
10 s < t (严格意义上)子集测试; s != t 而且 s 中 所 有
11 的元素都是 t 的成员
12 s.issubset(t) s <= t 子集测试(允许不严格意义上的子集): s 中所有的元素
13 都是 t 的成员
14 s > t (严格意义上)超集测试: s != t 而且 t 中所有的元素
15 都是 s 的成员
16 s.issuperset(t) s >= t 超集测试(允许不严格意义上的超集): t 中所有的元素
17 都是 s 的成员
18 s.union(t) s | t 合并操作: s 或 t 中的元素
19 s.intersec- tion(t) s & t 交集操作: s 和 t 中的元素
20 s.difference(t) s - t 差分操作: s 中的元素,而不是 t 中的元素
21 s.symmetric_difference(t)s ^ t 对称差分操作:s 或 t 中的元素,但不是 s 和 t 共有
22 的元素
23 s.copy() 复制操作:返回 s 的(浅复制)副本
仅用于可变集合:
1 s.update(t) s |= t (Union) 修改操作: 将 t 中的成员添加 s
2 s.intersection_update(t) s &= t 交集修改操作: s 中仅包括 s 和 t 中共有的成员
3 s.difference_update(t) s -= t 差修改操作: s 中包括仅属于 s 但不属于 t 的成员
4 s.symmetric_
5 difference_
6 update(t) s ^= t 对称差分修改操作: s 中包括仅属于 s 或仅属于 t 的成员
7 s.add(obj) 加操作: 将 obj 添加到 s
8 s.remove(obj) 删除操作: 将 obj 从 s 中删除;如果 s 中不存在obj,将引发 KeyError
9 s.discard(obj) 丢弃操作: remove() 的 友 好 版 本 - 如果 s 中存在 obj,从 s 中删除它
10 s.pop() Pop 操作: 移除并返回 s 中的任意一个元素
11 s.clear() 清除操作: 移除 s 中的所有元素
6.python函数基础以及函数参数简解
python中函数分为函数、内置函数
Python所有的内置函数
自定义函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。调用函数,使用函数名+()
def 关键字+函数名():
函数体
return 可以终止函数,默认返回None
下面 hello()函数,没有返回值。如果保存了返回值,该值为 None:
>>> def hello():
... print 'hello world'
>>>
>>> res = hello()
hello world
>>> res
>>> print res
None
>>> type(res)
<type 'None'>
python里的函数可以返回一个值或者对象。只是在返回一个容器对象的时候有点不同,看起来像是能返回多个对象。
def foo():
return ['xyz', 1000000, -98.6]
def bar():
return 'abc', [42, 'python'], "Guido"
foo()函数返回一个列表, bar()函数返回一个元组。 由于元组语法上不需要一定带上圆括号, 所以让人真的以为可以返回多个对象。
定义函数文档
文档的以贯例是多行字符串,第一行以大写字母开头以句点(.)结束(注:中文在V3.3中也可以),第二行是空行,从第三行开始是详细描述。
强烈建议,为你重要的函数写文档字符串要遵循此贯例
def foo():
'''
foo() -- properly created doc string
'''
函数体
函数的形参和实参
形参,只是一个形式,表示占据一个参数位置。
实参,是一个具体的参数,有它的实际意义。
Python中函数的实参有4种形式,分别是:
位置或关键字参数、仅位置的参数、任意数量的位置参数、任意数量的关键字参数
第一种:位置或关键字参数
这种参数是Python中默认的参数类型,定义这种参数后,可以通过位置参数,或者关键字参数的形式传递参数,这个是Python的默认参数类型
>>> def func(arg1, arg2="World!"):
print (arg1, arg2)
## func可以通过位置参数形式调用
>>>func("Hello", "MitchellChu")
Hello MitchellChu
## 也可以通过关键字参数的形式来调用func
>>>func(arg1="Hello", arg2="World!")
Hello World!
## 当然,混合的方式也是完全没有问题的
>>>func("Hello", arg2="World!")
Hello World!
## 不过如果你不能将关键字参数优先于位置参数传递给函数(方法)
## 这个调用方法是不能接受的,因为优先级不一样.后面会说
>>> func(arg1="Hello", "World!")
SyntaxError: positional argument follows keyword argument
第二种方式:仅适用位置参数的形式
这种形式在需要将参数传递给函数(方法)时,仅能通过位置参数的传递方式。这种形式对于Python的开发者来说,暂时并没有办法使用。这种形式现在仅存在Python的很多内建的函数上:
>>> abs(-3)
abs(a=3)
## Traceback (most recent call last):
## File "<stdin>", line 1, in <module>
## TypeError: abs() takes no keyword arguments
>>> pow(x=2,y=3)
## Traceback (most recent call last):
## File "<stdin>", line 1, in <module>
## TypeError: pow() takes no keyword arguments
>>> pow(2,3)
## 8
第三种:任意数量的位置参数(带单个星号参数)
任意数量的位置参数在定义的时候是需要一个星号前缀来表示,在传递参数的时候,可以在原有参数的后面添加任意多个参数,这些参数将会被放在元组内提供给函数(方法):
定义的时候,我们需要添加单个星号作为前缀
def func(arg1, arg2, *args):
print (arg1, arg2, args)
##调用的时候,前面两个必须在前面,前两个参数是位置或关键字参数的形式,所以你可以使用这种参数的任一合法的传递方法
>>> func("hello", "Tuple, values is:", 2, 3, 3, 4)
hello Tuple, values is: (2, 3, 3, 4)
##多余的参数将自动被放入元组中提供给函数使用.如果你需要传递元组给函数,你需要在传递的过程中添加*号
## 请看下面例子中的输出差异:
>>> func("hello", "Tuple, values is:", (2, 3, 3, 4))
hello Tuple, values is: ((2, 3, 3, 4),)
>>> func("hello", "Tuple, values is:", *(2, 3, 3, 4))
hello Tuple, values is: (2, 3, 3, 4)
第四种:任意数量的关键字参数(带两个星号参数)
任意数量的关键字参数在定义的时候,参数名称前面需要有两个星号(**)作为前缀,这样定义出来的参数,在传递参数的时候,可以在原有的参数后面添加任意多个关键字参数,关键字参数是使用[参数名称=参数值]的形式进行传递:
>>> func("hello", "Dict, values is:", x=2, y=3, z=3)
hello Dict, values is: {'z': 3, 'x': 2, 'y': 3}
>>> func("hello", "Dict., values is:", **{'x':2, 'y':3, 'z':3,})
hello Dict., values is: {'z': 3, 'x': 2, 'y': 3}
>>> func("hello", "Dict., values is:", s=3, **{'x':2, 'y':3, 'z':3,})
hello Dict., values is: {'z': 3, 's': 3, 'x': 2, 'y': 3}
错误方法:
#提供多了参数
>>> func("hello", "Dict., values is:", {'x':2, 'y':3, 'z':3})
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <module>
func("hello", "Dict., values is:", {'x':2, 'y':3, 'z':3})
TypeError: func() takes 2 positional arguments but 3 were given
## 提供了重复的参数
>>> func("hello", "Dict., values is:", y=3, **{'x':2, 'y':3, 'z':3,})
Traceback (most recent call last):
File "<pyshell#59>", line 1, in <module>
func("hello", "Dict., values is:", y=3, **{'x':2, 'y':3, 'z':3,})
TypeError: func() got multiple values for keyword argument 'y'
总结:四种参数形式中仅有第二种Python没有提供定义的方法,其他三种在定义的时候也需要注意,定义的时候应该根据Python的解析规律进行定义,其中:
位置或关键字参数应该在最前面,其中,没有默认值的应该在有默认值的参数前面
任意数量位置参数应该放在所有位置或关键字参数的后面
任意数量关键字参数应该放在任意数量位置参数的后面
注意:任意数量位置参数和任意数量关键字参数只能在定义中定义一次。
各种参数的混合使用例子
def func(arg1, arg2='default', *args, **kwargs):
print ("arg1=%s, arg2=%s, args=%s, kwargs=%s" % (arg1, arg2, args, kwargs))
func(1)
func(1,2)
func(1,2,3,4)
func(1,2,3,4,x=1,y=2)
func(1,2,x=1)
func(arg1=1)
func(1,x=1)
思考:函数接受变量作为参数时,接受的是变量的值还是变量的引用?
函数局部变量和全局变量:
在局部中调用全局变量(读取全局变量默认不用写。修改时需要),当全局变量为列表和字典,局部引用区域引用时不使用global时也是可以修改,不能重新赋值。全局变量与局部变量名称冲突时,在函数体内部优先使用局部变量
>>> li=[11,22,33]
>>> def name(li):
li=li.append(44) #全局变量在函数体内由于是引用,所以可以别修改,但是不能被赋值
>>> name(li)
>>> print(li)
[11, 22, 33, 44]
>>> li=[11,22,33]
>>> def name(li):
li='hello' #函数体内对全局变量赋值,结果没有改变
>>> name(li)
>>> print(li)
[11, 22, 33, 44]
>>> li=[11,22,33]
>>> def name(arg):
global li #使用global,可以对全局变量进行修改,不建议使用
li='hello world'
>>> name(li)
>>> print(li)
hello world
lambda表达式
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的定义。
>>> f2 = lambda a1: a1+100
# f2函数名称 关键字 函数参数 函数体
>>> f2(18)
118