# 本課主題

• Set 集合和操作实战
• 函数介紹和操作实战
• 参数的深入介绍和操作实战
• format 函数操作实战
• lambda 表达式介绍
• 文件操作函数介紹和操作实战
• 本周作业

## Set 集合和操作实战

Set 是一个无序不容许重复的序列

1. 第一种是通过直接创建、例如：s = {11,22}
1 >>> se = {11,222,11,222}
2 >>> print(se)
3 {11, 222}
4 >>> type(se)
5 <class 'set'>
创建集合 方法一
2. 第二种是通过转换。从一个可迭代类型的数组、元组转换成集合 Set。例如：s = Set(list)
1 >>> li = [11,22,11,33,11,44,55]
2 >>> se = set(li) #把列表转换成集合
3 >>> se
4 {33, 11, 44, 22, 55}
5 >>> type(se)
6 <class 'set'>
创建集合 方法二

原理：在调用 Set 函数时，它会自动调用 __intit__ 方法，这叫构造方法 ，其实内部会执行一个 For 循环，循环这个"可迭代对象"里的所有元素，一个一个添加到集合里(什么是构造方法会在后期学到面向对象后再分享)

### Set 集合的功能

class set(object):
"""
set() -> new empty set object
set(iterable) -> new set object

Build an unordered collection of unique elements.
"""
def add(self, *args, **kwargs): # real signature unknown
"""
Add an element to a set.

This has no effect if the element is already present.
"""
pass

def clear(self, *args, **kwargs): # real signature unknown
""" Remove all elements from this set. """
pass

def copy(self, *args, **kwargs): # real signature unknown
""" Return a shallow copy of a set. """
pass

def difference(self, *args, **kwargs): # real signature unknown
"""
Return the difference of two or more sets as a new set.

(i.e. all elements that are in this set but not the others.)
"""
pass

def difference_update(self, *args, **kwargs): # real signature unknown
""" Remove all elements of another set from this set. """
pass

def discard(self, *args, **kwargs): # real signature unknown
"""
Remove an element from a set if it is a member.

If the element is not a member, do nothing.
"""
pass

def intersection(self, *args, **kwargs): # real signature unknown
"""
Return the intersection of two sets as a new set.

(i.e. all elements that are in both sets.)
"""
pass

def intersection_update(self, *args, **kwargs): # real signature unknown
""" Update a set with the intersection of itself and another. """
pass

def isdisjoint(self, *args, **kwargs): # real signature unknown
""" Return True if two sets have a null intersection. """
pass

def issubset(self, *args, **kwargs): # real signature unknown
""" Report whether another set contains this set. """
pass

def issuperset(self, *args, **kwargs): # real signature unknown
""" Report whether this set contains another set. """
pass

def pop(self, *args, **kwargs): # real signature unknown
"""
Remove and return an arbitrary set element.
Raises KeyError if the set is empty.
"""
pass

def remove(self, *args, **kwargs): # real signature unknown
"""
Remove an element from a set; it must be a member.

If the element is not a member, raise a KeyError.
"""
pass

__hash__ = None
def symmetric_difference(self, *args, **kwargs): # real signature unknown
"""
Return the symmetric difference of two sets as a new set.

(i.e. all elements that are in exactly one of the sets.)
"""
pass

def symmetric_difference_update(self, *args, **kwargs): # real signature unknown
""" Update a set with the symmetric difference of itself and another. """
pass

def union(self, *args, **kwargs): # real signature unknown
"""
Return the union of sets as a new set.

(i.e. all elements that are in either set.)
"""
pass

def update(self, *args, **kwargs): # real signature unknown
""" Update a set with the union of itself and others. """
pass

def __and__(self, *args, **kwargs): # real signature unknown
""" Return self&value. """
pass

def __contains__(self, y): # real signature unknown; restored from __doc__
""" x.__contains__(y) <==> y in x. """
pass

def __eq__(self, *args, **kwargs): # real signature unknown
""" Return self==value. """
pass

def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __ge__(self, *args, **kwargs): # real signature unknown
""" Return self>=value. """
pass

def __gt__(self, *args, **kwargs): # real signature unknown
""" Return self>value. """
pass

def __iand__(self, *args, **kwargs): # real signature unknown
""" Return self&=value. """
pass

def __init__(self, seq=()): # known special case of set.__init__
"""
set() -> new empty set object
set(iterable) -> new set object

Build an unordered collection of unique elements.
# (copied from class doc)
"""
pass

def __ior__(self, *args, **kwargs): # real signature unknown
""" Return self|=value. """
pass

def __isub__(self, *args, **kwargs): # real signature unknown
""" Return self-=value. """
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

def __ixor__(self, *args, **kwargs): # real signature unknown
""" Return self^=value. """
pass

def __len__(self, *args, **kwargs): # real signature unknown
""" Return len(self). """
pass

def __le__(self, *args, **kwargs): # real signature unknown
""" Return self<=value. """
pass

def __lt__(self, *args, **kwargs): # real signature unknown
""" Return self<value. """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __ne__(self, *args, **kwargs): # real signature unknown
""" Return self!=value. """
pass

def __or__(self, *args, **kwargs): # real signature unknown
""" Return self|value. """
pass

def __rand__(self, *args, **kwargs): # real signature unknown
""" Return value&self. """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass

def __ror__(self, *args, **kwargs): # real signature unknown
""" Return value|self. """
pass

def __rsub__(self, *args, **kwargs): # real signature unknown
""" Return value-self. """
pass

def __rxor__(self, *args, **kwargs): # real signature unknown
""" Return value^self. """
pass

def __sizeof__(self): # real signature unknown; restored from __doc__
""" S.__sizeof__() -> size of S in memory, in bytes """
pass

def __sub__(self, *args, **kwargs): # real signature unknown
""" Return self-value. """
pass

def __xor__(self, *args, **kwargs): # real signature unknown
""" Return self^value. """
pass

__hash__ = None
Set集合的源码

更新: difference_update( ), symmeteric_difference_update( ), intersection_update( ), update( )

找不同: difference( ), symmeteric_difference( ),

找相同: intersection( )

删除: discard( ), remove( ), clear( ), pop( )

返回Boolean值: isdisjoint( ), issuperset( )

1 >>> se = set() #创建空集合
2 >>> se
3 set()
5 >>> se
6 {123}
集合功能:添加
2. 清除所有在集合里的内容: clear()
1 >>> se = set() #创建一个空集合
5 >>> print(se)
6 {333, 222, 111}
7 >>> se.clear() #清除集合里的所有元素
8 >>> se
9 set()
集合功能:删除
3. 对比两个集合，找其中一方的不同，相当于 database 里的 left outer join: difference()

1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s3 = s1.difference(s2) # 在s1中存在, s2中不存在
4 >>> s1
5 {33, 11, 22}
6 >>> s3
7 {11}
8 >>> s3 = s2.difference(s1) #在s2中存在, s1中不存在
9 >>> s3
10 {44}
集合功能:找不同
4. 对比两个集合，取出双方不同的元素: symmetric_difference()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s3 = s1.symmetric_difference(s2) #找出双方都不存在的元素
4 >>> s1
5 {33, 11, 22}
6 >>> s3
7 {11, 44}
集合功能:找不同
更新: 对比两个集合，找其中一方的不同，然后直接把结果更新到原来的集合：difference_update()
1 >>> a = {11,22,33}
2 >>> b = {22,33,44}
3 >>> a.difference_update(b) #对比两个集合，找其中一方的不同，然后直接把结果更新到原来的集合
4 >>> a
5 {11}
集合功能:更新
5. 更新: 对比两个集合，取出双方不同的元素，然后直接把结果更新到原来的集合：symmetric_difference_update()
1 >>> a = {11,22,33}
2 >>> b = {22,33,44}
3 >>> a.symmetric_difference_update(b)
4 >>> a
5 {11, 44}
集合功能:更新
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
4 >>> s1
5 {33, 22}
集合功能:删除
7. 刪除指定元素，不存在，報錯!!!remove()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s1.remove(11)
4 >>> s1
5 {33, 22}
6 >>> s1.remove(1111)
7 Traceback (most recent call last):
8   File "<stdin>", line 1, in <module>
9 KeyError: 1111
集合功能:删除
8. 随机移取某个元素并获取这个元素: pop()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> ret = s1.pop()
4 >>> ret
5 33
集合功能:删除
9. 对比两个集合，找双方交集部份，相当于 database 里的 inner join: intersection()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s3 = s1.intersection(s2) #找s1和s2相同的元素
4 >>> s3
5 {33, 22}
6 >>> s1
7 {33, 11, 22}
集合功能:找相同
10. 对比两个集合，找双方交集部份，相当于 database 里的 inner join，然后直接把结果更新到原来的集合：intersection_update()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s1.intersection_update(s2) #找相同然后直接更新 s1
4 >>> s1
5 {33, 22}
集合功能:找相同然后更新
11. 判断两个集合有没有交集部份，如果有便返回 False ；如果没有，则返回 True: isdisjoint()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s1.isdisjoint(s2) #有交集部分
4 False
5
6 >>> s1 = {11,55,66}
7 >>> s2 = {22,33,44}
8 >>> s1.isdisjoint(s2) #没有交集部分
9 True
集合功能:返回Boolean值
12. 判断两个集合有没有父子关系，有是 True, 沒有則 False: issuperset()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s1.issuperset(s2) #s1 不是 s2 的父序列
4 False
5 >>>
6 >>> s1 = {11,22,33}
7 >>> s2 = {22,33}
8 >>> s1.issuperset(s2) #s1 是 s2 的父序列
9 True
集合功能:返回Boolean值
13. 把两个集合连合然后去掉重覆的就是并集（这功能相当于 database, union 然后拿distinct value)：union()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s3 = s1.union(s2)
4 >>> s3
5 {33, 22, 11, 44}
集合功能:添加
14. 批量地把一托集合增加到目标集合，update()接收一个可以被迭代的对象 e.g. List、Tuple、String：update()
1 >>> s1 = {11,22,33}
2 >>> s2 = {22,33,44}
3 >>> s1.update({77,88,99})
4 >>> s1
5 {33, 99, 22, 88, 11, 77}
6 >>> s1.update(s2)
7 >>> s1
8 {33, 99, 22, 88, 11, 44, 77}
9 >>>
集合功能:更新

difference( ) 和 difference_update( ) 的应用：

• s1 集合和 s2 集合的结果会保持不变，两个方法 difference() 和 symmetric_difference() 都会产生一个新的集合，所以在实际情景中如果需要重用 s1 和 s2 集合的时候，就不要用 differernce_updates() 和 symmetric_difference_update() 了。因为这两个函数会覆盖本來在 s1 里的结果。
• 如果以后不需要基於 s1 來操作，只需要拿最新结果的话，就可以用 differernce_updates() 和 symmetric_difference_update()，这里的好处是变量声明减少了就可以​​节省内存空间！ ！ ！

[更新中...]

## 函数介紹和操作实战

1. 如果代码量多的话，不断的复制和粘贴，会导致代码缺乏了可阅读性;
2. 不断使用重覆代码，代码量多，程序员也会很累，会导致代码缺乏了重用性

**总结：基于以上两点的解决方安案是运用函数式编程！！函数是用来封装某些功能的，它的出现是为了增加代码的重用性，令代码更简洁，而且可以增加其可读性，以后如果要使用的话就直接调用这个函数就行啦！ ！

### 创建函数的步骤如下：

1. def 关键字来声明这是一个函数；
2. 在 def 後面加一個空格，然后寫上一個名字代表函数名稱，以后就可以在内存里调用它;
3. 名字加上后再加一个括号 ( );
4. 然后在函数体里写上函数的内容：就是具体需要实现的功能;
5. 然后加上返回值，如果沒有返回值的話 Python 会有一个默应的返回值 (None)
>>> def func():
...     print("123")
...
>>> f1 = func()
123
>>> print("f1:",f1)
f1: None
沒有返回值

有返回值的意思是：函数可以被調用然後賦值到另外一個參數，也就是說一個函数可以像參數一樣被传递。

>>> def func():
...     return "123"
...
>>> f1 = func()
>>> print("f1:",f1)
f1: 123
有返回值
6. 函数可以在括号里面输入参数。

### 案例实战

def sendMail():

import smtplib
from email.mime.text import MIMEText

msg = MIMEText("Python Email testing",'plain','utf-8')
msg['Subject']='主題'

server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.sendmail("janicecheng.python@gmail.com",["janicecheng.python@gmail.com",], msg.as_string())

print("Mail Send Successfully")
server.quit()

sendMail()

• def sendMail( ): 这叫声明函数
• sendMail( ): 这叫执行函数
1 def sendMail():
2
3     import smtplib
4     from email.mime.text import MIMEText
6
7     msg = MIMEText("Python Email testing",'plain','utf-8')
10     msg['Subject']='主題'
11
12     server = smtplib.SMTP("smtp.gmail.com", 587)
13     server.starttls()
15     server.sendmail("janicecheng.python@gmail.com",["janicecheng.python@gmail.com",], msg.as_string())
16
17     print("Mail Send Successfully")
18     server.quit()
19
20 sendMail()
sendMail函数

1. 当你在声明变量和函数之后，函数体在声明的时倏不会被执行的，它们分别会放在内存里，等待被调用！
2. 在函数中一旦执行了 return, 函数的执行过程立即终止

### 返回值的补充说明

1. 第一步：Python 运行程序的时候是从上而下执行的，在 f1 声明函数放在内存的时候，它把1+2 声明后，然后放在内存里
2. 第二步：当程序运行时碰到第2个 f1函数时，它再次在内存中把1x 2 放在内存中，并且 f1 指向 (1 x 2)
• Python 有自己的垃圾回收机制，会定时把没有的变量或者函数删除掉。
3. 第三步：声明一个变量把f1函数的返回值存储在里面
4. 第四步：当调用 f1函数时，它实际上是运行 a1 * a2
5. 第五步：然后实际运行 f1函数
6. 第六步：打印出 ret 变量中的值

## 参数的深入介绍和操作实战

1. 把参数传入然后在函数体里的内码块可以把这个参数当成变量的去使用，这种参数叫形式参数。当我们在调用程序的时候把参数传入然后执行，这种参数叫实际参数。在這個例子中，参数 target_email 叫形式参数;下面执行程序传入的 “Alex” 叫实际参数。
2. 如果从内存的角度去看这两种参数的话，在调用sendmail( ) 然后传入“alex” 的时候，这个“alex” 的字符串就已经在内存中，这就相当于把“xxoo” 这个形式参数指向内存中的实际参数“alex”; 同样地；对于“eric” 这个实际参数，它在被调用的时候，”eric” 已经在内存中等待着，然后函数本身的形式参数就会指向“ eric ”，然后执行程序，这就是形式参数和实际参数的关系。
3. 还有就是形式参数和实际参数的位置默认情况下是一一对应的

4. 在Python中也可以定义默认参数，意思是在声明函数的时候，其中一些形式参数已经定义了一些默认值，注意：如果想要定义默认参数，必需把默认参数放在参数列表的最后位置！ ！ ！
1 #content="This is a testing email" 是默认参数
2 def send(receipent,content="This is a testing email"):
3     print("Email send to:",receipent,", Content:",content)
4     print("Mail sent successfully")
5     return True
6
7 send("janice@abc-company.com") # 默认 content 用了 "This is a testing email"
8 send("janice@abc-company.com", "Company Notice") # content 用了 "Company Notice"
9
10 #Results:
11 #Email send to: janice@abc-company.com , Content: This is a testing email
12 #Mail sent successfully
13 #Email send to: janice@abc-company.com , Content: Company Notice
14 #Mail sent successfully
默认参数
5. 也可以声明指定参数，在调用的时候输入 “”形式参数=实际参数” e.g. content=“alex"，这样就可以在函数被調用時忽略参数顺序。
6. 对于动态参数有两种类： * 和 ** (分别是一个星号和两个星号)
* 一个星号: 默认将传入的参数，全部放在一个元组中。 f1(*[11,22,33,44])
** 两个星号: 默认将传入的参数，全部放在一个字典中。 f1(**{"k1":"v1","k2":"v2”})

动态参数 (*) 会返回一个元组，如果函数的形式参数有* 号就有特殊的功能 e.g. def f1(*args)，就是按照顺序接受传入什么的值都会转换到元组里面，并且当做元组的一个元素；如果在传实际参数的时候加一個星 * 号 e.g. f1(*li)，它的特殊的功能是将这个列表里的每一个元素都转化到元组的元素里，其实就相当于在内部​​做了一个 For 循环，把列表里的一个一个添加到元组里(Tuple)。
1 def f3(*args):
2     print(args) #返回一個元組
3
4 li = [11,22,"Janice","dfghjk"]
5 name = "Janice"
6
7 f3(li)
8 f3(*li)
9 f3(*"Janice")
10 f3(*name)
11
12 #Results:
13 #([11, 22, 'Janice', 'dfghjk'],)
14 #(11, 22, 'Janice', 'dfghjk')
15 #('J', 'a', 'n', 'i', 'c', 'e')
16 #('J', 'a', 'n', 'i', 'c', 'e')
动态参数*

动态参数 (**) 会返回一個字典，如果函数的形式参数有** 号就有特殊的功能 e.g. def f1(**args)，就是传入什么的值都会转换到字典里面，并且当做字典value；如果在传实际参数的时候加上两个星** 号e.g. f1(**dic)，它的特殊的功能是将这个字典里的每一个key, value 都给转化成字典的key, value，其实就相当于直接赋值到字典里。

1 def f4(**args):
2     print(args) #返回一個字典
3
4 li = [11,22,"Janice","dfghjk"]
5 name = "Janice"
6
7 f4(n1="Janice")
8 f4(n1="Janice", n2=20)
9
10 dic = {"k1":"v1","k2":"v2"}
11 f4(kk = dic)
12 f4(**dic)
13
14 #Results
15 #{'n1': 'Janice'}
16 #{'n1': 'Janice', 'n2': 20}
17 #{'kk': {'k1': 'v1', 'k2': 'v2'}}
18 #{'k1': 'v1', 'k2': 'v2'}
动态参数**
7. 万能参数，def f5(*args, **kwargs) (注意:* 一个星号必须在前面, ** 两个星号必须在后面!)

1 def f5(*args, **kwargs):
2     print(args)
3     print(kwargs)
4
5 f5(11,22,33,44,k1="v1",k2="v2")
6
7 #Results:
8 #(11, 22, 33, 44)
9 #{'k2': 'v2', 'k1': 'v1'}
万能参数*args, **kwargs
8. 全局变量和局部变量
没有写到函数体里的变量叫全局变量，它在所有文件中都是可读；在f1函数里写的变量是 f1函数私有的，叫局部变量；变量会先找自己的局部变量，然后才找全局变量，如果你想修改全局变量(重新赋值)，这时需要加入一个global 的关键字+ 它的变量名。如果以后要读一个全局变量的时候，直接打印 e.g. print() 一下就可以啦!

• 重点一、[列表, 字典, 元组] 如果在函数体里进行修改/新增, 这是在修改全区列表,但列表不容许在函数体里重新赋值。

• 重点二、如果是全局变量，命名时都需要大写！ ！ ！
9. 补充：函数的参数在传入的时候，到底是传入引用还是再传入一份列表，現在来分析一下两种结果：

1. 如果传入的是一份列表，Python 在传入参数的时候是重新赋值的话，打印的时候就不应该出现 999
2. 如果传入的是一个引用, li 和 a1 便会指向同一个列表
3. 從运行后的结果可以总结：Python 在传参数的时候，其实是传入一个引用！ ！ ！
1 def f7(a1):
2     a1.append(9999)
3
4 li = [11,22,33,44]
5 f7(li)
6 print(li)
7
8 #Results:
9 #[11, 22, 33, 44, 9999]
运行后结果

### 实战操作

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Janice Cheng

import os
import random
import sys

# make a list of words
words = [
'apple',
'banana',
'orange',
'coconuts',
'straweberry',
'lime',
'graphefruit',
'lemon',
'kumquat',
'blueberry',
'melon'
]

def clear():
if os.name == 'nt':
os.system('cls')
else:
os.system("clear")

clear()

print('')

print(letter, end=' ')

print('\n\n')

for letter in secret_word:
if letter in good_guess:
print(letter, end='')
else:
print('_', end='')

print('')

while True:
guess = input("Guess a letter: ").lower()

if len(guess) != 1:
print("You can only guess a single letter!")
elif guess in bad_guess or guess in good_guess:
elif not guess.isalpha():
print("You can only guess letters!")
else:
return guess

def play(done):
clear()
secret_word = random.choice(words)
good_guess = []

while True:

if guess in secret_word:
good_guess.append(guess)
found = True

for letter in secret_word:
if letter not in good_guess:
found = False

if found:
print("You win!")
print("The word was {}".format(secret_word))
done = True
else:
print("You lost!")
print("The word was {}".format(secret_word))
done = True

if done:
play_again = input("Play again? y/n ").lower()
if play_again != 'n':
return play(done=False)
else:
sys.exit()

def welcome():
print("Welcome to Letter Guess!!")
start = input("Press enter/return to start or Q to quit >> ").lower()
if start == 'q':
print('Bye!')
sys.exit()
else:
return True

if __name__ == "__main__":

done = False

while True:
clear()
welcome()
play(done)

## format 函数操作实战

ret = '{0} lives in Hong Kong for more than {1} years!!'.format('Janice',20)
ret = '{name} lives in Hong Kong for more than {year} years!!'.format(name='Janice', year=20)
# Janice lives in Hong Kong for more than 20 years!!

def format(self, *args, **kwargs): # known special case of str.format
"""
S.format(*args, **kwargs) -> str

Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
"""
pass
1. 一个 *星号的函数例子
>>> s = "My name is {} and I am {} years old".format("Janice",20)
>>> s
'My name is Janice and I am 20 years old'

# 在参数里加入*便可以接受列表类型
>>> s = "My name is {} and I am {} years old".format(*["Janice",20])
>>> s
'My name is Janice and I am 20 years old'

# 这里不受列表类型
>>> s = "My name is {} and I am {} years old".format(["Janice",20])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

# 在括号里定义{0}和{1}，就不需要在format()函数里重覆定义传递的内容
>>> s = "My name is {0} and {0} and {0} I am {1} years old".format("Janice",20)
>>> s
'My name is Janice and Janice and Janice I am 20 years old'

>>> s = "My name is {} and {} and {} I am {} years old".format("Janice",21)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
一个*星号的函数
2. 两个** 星号的函数例子
1 >>> s = "My name is {name} and I am {age} years old".format(name="Janice",age=20)
2 >>> s
3
4 >>> s = "My name is {name} and I am {age} years old".format(**{"name":"Janice","age":20}) # 在参数里加入**便可以接受字典类型
5 >>> s
6 'My name is Janice and I am 20 years old'
两个**星号的函数

[更新中...]

## lambda 表达式介绍

>>> def f1(a):
...     return a + 100
...
>>> ret = f1(10)
>>> print(ret)
110

lambda a: a + 100
# a + 100 是函数体，a 是变量，整句意思是输入参数 a，然后对a进行操作：a + 100

>>> f2 = lambda a: a + 100 #自动返回
>>> ret2 = f2(10)
>>> print(ret2)
100
lambda 表达式例子一
>>> add = lambda a1,a2: a1 + a2 #可以传两个参数
20
lambda 表达式例子二

lambda 中的 filter 例子

>>> lst = [11,22,33,44]

#Option1
>>> def f(x):
...     return x > 22

>>> list(filter(f, lst))
[33, 44]

#Option2
>>> list(filter(lambda a: a > 22, lst))
[33, 44]
lambda 表达式例子三

lambda 中的 map 例子

>>> lst1 = [1,3,5,6,9]
>>> lst2 = [2,4,6,8,10]
>>> ret = map(lambda x,y: x+y, lst1, lst2)
>>> list(ret)
[3, 7, 11, 14, 19]
lambda 表达式例子四

wordCounts = textFile.flatMap(lambda line: line.split())\
.map(lambda word: (word, 1))\
.reduceByKey(lambda a, b: a+b)

## 文件操作函数介紹和操作实战

### 打開文件

##Operation
output = open(r'C:\spam', 'w') #Create output file ('w' means write)
input = open('data', 'r') #Create input file ('r' means read)
input = open('data') #Same as prior line ('r' is the default)
open('f.txt', encoding='latin-1') #Python 3.X Unicode text files (str strings)
open('f.bin', 'rb') #Python 3.X bytes files (bytes strings)
open('f.bin', 'rb') #Python 2.X bytes files (str strings)
for line in open('data'): #File iterators read line by line

### 操作文件

##Method
aString = input.read(N) #Read up to nextNcharacters (or bytes) into a string
aList = input.readlines() #Read entire file into list of line strings (with \n)
output.write(aString) #Write a string of characters (or bytes) into file
output.writelines(aList) #Write all line strings in a list into file
output.close() #Manual close (done for you when file is collected)
output.flush() #Flush output buffer to disk without closing
anyFile.seek(N) #Change file position to offsetNfor next operation

# Remember to close the file after every file modification
f = open("readme.txt",'w') #open a file for writing
f.write("this is the first line\n") #write a line to the file
f.write("this is the second line\n") #write one more line to the file
f.close() #close a file

f.seek(1) # 调整指针到第一个位置
f.tell()
f.close() #close a file

f = open("readme.txt",'a') #append data to the original file
f.write("this is the third line\n") #write a line to the file
f.close() #close a file

1. Append: "a" - 以追加的方式打开文件，(打开文件后的文件指针会自动移到文件末尾) 如果文件不存在则创建
f = open("db","a")
f.write("Python")
f.close()

Append:a
1 >>> f2 = open("db","r")
3 >>> print(data2)
5 Alex|alex3417
6 >>> print(type(data2))
7 <class 'str'>
3. Write: "w" - 以写的方式打开文件，如果文件存在，则清空该文件，再重新写入新内容
1 >>> import csv
2 >>> f2 = open("db","w")
4 >>> f2.write(data)
5 9
6 >>> f2.close()
Write:w
4. Extend: "x" - 如果这个文件存在就报错，如果不存在就创建并写内容 (跟 w 是一样的，只增加多一个条件判断，判断一下当前文件是否已经存在)
1 >>> f2 = open("db","x") #如果文件已经存在，你会报错
2 Traceback (most recent call last):
3   File "<stdin>", line 1, in <module>
4 FileExistsError: [Errno 17] File exists: 'db'
5
6 >>> f2 = open("db_test","x")
8 >>> f2.write(data)
9 9
10 >>> f2.close()
Extend:x

1. Append: "a+" - 以读写方式打开文件，并把文件指针移到文件尾
2. Read: "r+" - 以读写方式打开文件，可以对文件进行读写操作，Python 在读完整个文件的时候，默认指针位置会在文件的末位​​，所以当 f.write("9999") 的时候，就会在文件最后的位置追加，所以如果用 "r" 打开时，可以配合 seek() 来指定写入的位置 (看下面seek()的例子)。
1 >>> f = open("db","r+", encoding='utf-8')
3 >>> print(data)
5 >>> f.write("9999")
6 11
7 >>> f.close()
8
9 #Results:
3. Write: "w+" - 清除文件内容、然后以读写方式打开文件。可读可写，但會先清空，後再寫。

1. Append: "ab" - 如果使用二进制的方式写，必需也得传入字节类型
1 >>> f = open("db","ab")
2 >>> f.write(bytes("Python", encoding='utf-8'))
3 6
4 >>> f.close()
5
6 #Results:
Append:ab
如果使用二进制的方式去写数据，但传入的是一个字符串，这时候程序就会报错！
1 >>> f3 = open("db","ab") #如果加b只能写入字节
2 >>> f3.write("hello")
3 Traceback (most recent call last):
4   File "<stdin>", line 1, in <module>
5 TypeError: a bytes-like object is required, not 'str'
Append:ab
2. Read: "rb" - 只读，在读文件时自己去跟Python 底层的二进制沟通，你读的时候是读二进制，所以写的时候也需要写上二进制(字节)，在硬盘上存储的是二进制格式，Python 在读的时候，默认把底层的二进制字节转转换成字符串，所以打印出来才会是字符串。
1 >>> f1 = open("db","rb")
3 >>> print(data1)
5 >>> print(type(data1))
6 <class 'bytes'>
**注意: encoding 这个参数，它是 Python 在把字节转化成字符串设定的一个编码，Python 会按照这个编码帮我们转换。意思就是说你用什么编码去存储文件(写)的同时，也应该用相同的编码去打开(读)文件。如果把 b 取掉读到的就是字符串类型，所以如果在打开文件的时候出现乱码，很大可能是这个 encoding 出现问题。
f=open("db","r",encoding="GBK")
3. Write: "wb"

1. seek( ): 主动调整指针的位置，指针跳到指定位置 (永远以字符的方式找位置)
1 >>> f = open("db","r+")
3 >>> print(data)
4 a
5 >>> f.seek(1) #调整指针到第一个位置
6 1
7 >>> f.write("999") #当前指针位置开始向后覆盖，写数据，打开方式有 b 、只能写字节；无b就是写字符
8 3
9 >>> f.close()
10
11 #Results:
13 #After: #a999n|123
seek()
1 >>> f = open("db","r+")
3 >>> print(data)
4 5 >>> print(f.tell())
6 3
7
8 #db: 金|123
tell()
1 >>> f = open("db","rb")
3 >>> print(data)
4 b'\xe9'
5 >>> f.close()
6 >>> f = open("db","r+")
8 >>> print(data)
9 10 >>> f.close()
4. write( ): 写数据，如果在打开文件的时候是"rb"，读取的时候会按字节；如果在打开文件的时候是"r"，读取的时候会按字符。
5. close( ):
6. fileno( ):
7. flush( ): 刷新，在文件还没有close()之前，f.write 的数据会存放在内存里而不直接写入文件，如果用了flush()的话，它就会在文件还没有调用close()的状况下强行把数据写入文件中。
1 >>> f = open("db","a")
2 >>> f.write("888")
3 3
4 >>>
5 >>> input("Please input a number: ") #等待着用户输入
flush()
1 >>> f2 = open("db_test","w")
3 False
4 >>> f1 = open("db_test","r")
6 True
9. seekable( ):
1 db.txt
3 janice|janice123
4 alex|alex123
5 kennith|ken123
6
7 >>> f1 = open("db","r")
11 'janice|janice123\n'
12 >>> f1.close()
11. truncate( ):截断数据，只把指针位置后的清空
1 f = open("db","r+",encoding='utf-8')
2 f.seek(3)
3 f.truncate()
4 f.close()
5
truncate()
12. for-loop:
1 f = open("db","r+",encoding='utf-8')
2 for line in f:
3     print(line)
4
5
6 f.close()
7
9 #alex|alex3417
10 #kennith|ken3344
for-loop

### 關閉文件

1. close( )
f = close()
2. with 文件操作
1 with open("db","r+", encoding='utf-8') as f:
2     for line in f:
3         print(line)
4
6 #alex|alex3417
7 #kennith|ken3344
with f1
3. with 同時操作兩個文件
1 #從db1文件一个以只读的方法打开，從db2文件一个以只写的方法打开
2 #从DB1读一行写一行到DB2
3 with open("db1","r", encoding='utf-8') as f1, open("db2","w", encoding='utf-8') as f2:
4     for line in f1:
5         new_line = line.replace("alex","eric")
6         f2.write(new_line)
with f1, f2

### gzip

>>> import gzip
>>> with gzip.open('score.csv.gz','rt') as f:
...
chinese,88
english,90
maths,85
computer science,90
chemistry,67
music,88
economics,75
gzip

## 本周作业

1 global
2         log 127.0.0.1 local2
3         daemon
4         maxconn 256
5         log 127.0.0.1 local2 info
6 defaults
7         log global
8         mode http
9         timeout connect 5000ms
10         timeout client 50000ms
11         timeout server 50000ms
12         option  dontlognull
13 listen stats :8888
14         stats enable
17 frontend oldboy.org
18         bind 0.0.0.0:80
19         option httplog
20         option httpclose
21         option  forwardfor
22         log global
23         acl www hdr_reg(host) -i www.oldboy.org
24         use_backend www.oldboy.org if www
25 backend www.oldboy.org
26         server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000