集合、文件读写、函数

集合

1 Set 方法

Python 拥有一套能够在集合(set)上使用的内建方法。

方法描述
add() 向集合添加元素。
clear() 删除集合中的所有元素。
copy() 返回集合的副本。
difference() 返回包含两个或更多集合之间差异的集合。
difference_update() 删除此集合中也包含在另一个指定集合中的项目。
discard() 删除指定项目。
intersection() 返回为两个其他集合的交集的集合。
intersection_update() 删除此集合中不存在于其他指定集合中的项目。
isdisjoint() 返回两个集合是否有交集。
issubset() 返回另一个集合是否包含此集合。
issuperset() 返回此集合是否包含另一个集合。
pop() 从集合中删除一个元素。
remove() 删除指定元素。
symmetric_difference() 返回具有两组集合的对称差集的集合。
symmetric_difference_update() 插入此集合和另一个集合的对称差集。
union() 返回包含集合并集的集合。
update() 用此集合和其他集合的并集来更新集合。

集合(Set)

集合是无序和无索引的集合。在 Python 中,集合用花括号编写。

intersection() 交集

union() 并集

difference() 差集

issubset() 子集

issuperset() 父集

symmetric_difference() 对称差集

isdisjoint() 判断是否有差集

2 关系操作

list_1 = [1,4,5,7,3,6,7,9]
list_1 = set(list_1)
​
list_2 = set([2,6,0,66,22,8,8,4])
# print(list_1,list_2)
​
# 交集
print(list_1.intersection(list_2))
​
# 并集
print(list_1.union(list_2))
​
# 差集
print(list_1.difference(list_2))
print(list_2.difference(list_1))
​
# 子集
# issubset(),返回另一个集合是否包含此集合。
# issuperset(),返回此集合是否包含另一个集合。
list_3 = set([1,3,7])
print(list_3.issubset(list_1)) # 此集合是否为另一个集合的子集合
print(list_1.issuperset(list_3)) # 此集合是否为另一个集合的父集合
​
# 对称差集(合并没有交集)
print(list_1.symmetric_difference(list_2))
​
​
print("---------------")
# isdisjoint()返回两个集合是否有交集。
list_4 = set([5,6,7,8])
print(list_3.isdisjoint(list_4))

  

3 关系运算符:

# 交集
print(list_1 & list_2)
​
# union
print(list_2 | list_1)
​
#difference
print(list_1 - list_2) # in list_1 not in list_2
​
#对称差集
print(list_1 ^ list_2)

  

4 基本操作

list_1 = [1,4,5,7,3,6,7,9]
list_1 = set(list_1)
​
#添加
list_1.add("hello") #添加一项
list_1.update(["hi","word"]) #添加多项,不加中括号变成'w','i', 'o', 'd', 'h', 'r'
​
#获取长度
long = len(list_1)
print(list_1,"\t",long)
​
#judge判断
print("hello" in list_1)    #判断是否存在集合里
print("hello" not in list_1) #判断是否不在集合里
​
#copy
list_1_copy = list_1.copy()
print(list_1,list_1_copy)
​
#delete
print(list_1.pop())
list_1.remove("haha")   # 删除不存在元素会报错
list_1.discard("haha")  #删除不存在元素不会报错
print(list_1)
​
#clear
list_1.clear()

  

文件方法

Python 有一组可用于文件对象的方法。

方法描述
close() 关闭文件。
detach() 从缓冲区返回分离的原始流(raw stream)。
fileno() 从操作系统的角度返回表示流的数字。
flush() 刷新内部缓冲区。
isatty() 返回文件流是否是交互式的。
read() 返回文件内容。
readable() 返回是否能够读取文件流。
readline() 返回文件中的一行。
readlines() 返回文件中的行列表。
seek() 更改文件位置。
seekable() 返回文件是否允许我们更改文件位置。
tell() 返回当前的文件位置。
truncate() 把文件调整为指定的大小。
writeable() 返回是否能够写入文件。
write() 把指定的字符串写入文件。
writelines() 把字符串列表写入文件。

read()、readline()、readlines()

我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。

 

.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:

Python .readlines() 示例

fh = open( 'c:\autoexec.bat') for line in fh.readlines(): print line.readline() 和 .readlines()之间的差异是后者一次读取整个文件,象 .read()一样。.readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理。另一方面,.readline()每次只读取一行,通常比 .readlines()慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用.readline()。

写:

writeline()是输出后换行,下次写会在下一行写。write()是输出后光标在行末不会换行,下次写会接着这行写

 

通过readline输出,对于比较大的文件,这种占用内存比较小。
#coding:utf-8
f = open('poem.txt','r')
result = list()
for line in open('poem.txt'):
    line = f.readline()
    print line
    result.append(line)
print result
f.close()                
open('result-readline.txt', 'w').write('%s' % '\n'.join(result))

 

#coding:utf-8
'''cdays-4-exercise-6.py 文件基本操作
    @note: 文件读取写入, 列表排序, 字符串操作
    @see: 字符串各方法可参考hekp(str)或Python在线文档http://docs.python.org/lib/string-methods.html
'''
f = open('cdays-4-test.txt', 'r')                #以读方式打开文件
result = list()
for line in f.readlines():                       #依次读取每行
    line = line.strip()                          #去掉每行头尾空白
    if not len(line) or line.startswith('#'):    #判断是否是空行或注释行
        continue                                 #是的话,跳过不处理
    result.append(line)                          #保存
result.sort()                                    #排序结果
print result
open('cdays-4-result.txt', 'w').write('%s' % '\n'.join(result)) #保存入结果文件

  

文件读与写

#data = open("yesterday",'r',encoding="utf-8").read()
#r 只读,如果连续读两次文件,第二次就不能读到内容(因为第一次读完,光标在最后)
"""
f = open("yesterday2",'r',encoding="utf-8")
data = f.read()
data2 = f.read()
print(data)
print("-------data2----------%s---" %data2)
"""
#w 创建覆盖(原有)文件
#a = append 追加
# w,a 不能读
​
​
f = open("yesterday2",'a',encoding="utf-8") #文件句柄
f.write("\nwhen i was young i listen to the radio\n")
data = f.read()
print('----read--------',data)
​
f.close()

  

文件读与写二

f = open("yesterday",'r',encoding="utf-8")
​
count =0
for line in f:
    if count == 9:
        print('-------分割线-------')
        count += 1
    print(line)
    count += 1
​
​
"""
for index,line in enumerate(f.readlnes()):
    if index == 9:
        print('------分割线-------')
        continue
    print(line.strip())
"""
​
# for i in range(5):
#     print(f.readline())

  

文件读与写三

1 方法

f = open("yesterday",'r',encoding="utf-8") # 文件句柄
print(f.tell()) #返回当前的文件位置。
print(f.readline())
print(f.tell())
print(f.seek(0)) #更改文件位置。
print(f.seekable()) #返回文件是否允许我们更改文件位置。
print(f.encoding)       #打印文件编码
print(f.fileno())       #从操作系统的角度返回表示流的数字。
#detach()        #编辑过程中修改字符编码
print(f.name)
print(f.isatty())       #返回文件流是否是交互式的。检查文件是否已连接到终端设备:
print(f.readable())     # 是否可读
print(f.writable())     # 是否可写
print(f.closed)  # 判断文件是否关闭
# print(f.newlines)

  

f = open("yesterday",'a',encoding="utf-8") # 文件句柄
# print(f.seek(0))
f.seek(10)      # 使用seek()无效
f.truncate(30)
f.close()

read()读取剩下的所有内容,文件大时不要用

2 打开文件模式

打开文件的模式有:

  • r,只读模式(默认)。

  • w,只写模式。【不可读;不存在则创建;存在则删除内容;】

  • a,追加模式。【可读; 不存在则创建;存在则只追加内容;】

"+" 表示可以同时读写某个文件

  • r+,可读写文件。【可读;可写;可追加】

  • w+,写读

  • a+,同a

"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)

  • rU

  • r+U

"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)

  • rb

  • wb

  • ab

3 flush()

刷新内部缓冲区。

一:

cmd执行:
>d:
>python
>>> f = open("test.text","w")
>>> f.write("hello1\n")
7
>>> f.flush()	# 刷新缓存区后再打开文件显示一行内容
>>> f.write("hello2\n")
7
>>> f.flush()	# 再刷新显示一行

二:

import sys,time

for i in range(20):
    sys.stdout.write("#")
    sys.stdout.flush()
    time.sleep(0.1)

  

 

4 r+、w+、a+

# f = open("yesterday2",'r+',encoding="utf-8") # 文件句柄 读写
# print(f.readline())
# print(f.tell())
# num = f.tell()
# f.write("--------你好------------")  #会写在最后
# print(f.seek(num))                  #写入后光标会跳到最后
# print(f.readline())

f = open("yesterday",'w+',encoding="utf-8") # 文件句柄  写读(覆盖原文件)
# f = open("yesterday",'a+',encoding="utf-8") # 文件句柄  追加读写

f.write("----------hello--------\n")
f.write("----------hello--------\n")
print(f.tell())
f.seek(10)
print(f.tell())
print(f.readline())
f.write("-------------hi--------")
f.close()

  

5 二进制rb、wb、ab

f = open("yesterday",'rb') # 文件句柄 二进制文件
# 网络传输用到
print(f.readline())
print(f.readline())

f = open("yesterday",'wb')
#f = open("yesterday",'ab')
f.write("--hello word--\n".encode())
f.write("--hello word--\n".encode())

文件修改

1

f = open("yesterday2","r",encoding="utf-8")
f_new = open("yesterday2.bak","w",encoding="utf-8")

print(f.tell(),f_new.tell())
for line in f:
    if "昨日当我年少轻狂" in line:
        line = line.replace("昨日当我年少轻狂","昨日当阿福年少轻狂")
    f_new.write(line)
    print(line.strip())
f.close()
f_new.close()

with

为了避免打开文件后忘记关闭,可以通过管理上下文,

如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。

在Python 2.7 后,with又支持同时对多个文件的上下文进行管理

# f = open("yesterday2","r",encoding="utf-8")

with open("yesterday2","r",encoding="utf-8") as f,\
open("yesterday2","r",encoding="utf-8") as f2:
    for line in f:
        print(line.strip())
    print("-------------")
    for line2 in f2:
        print(line2.strip())

  

程序练习

1 实现简单的shell sed替换功能

import sys
find_str = sys.argv[1]
replace_str = sys.argv[2]
f = open("yesterday2","r",encoding="utf-8")
f_new = open("yesterday2.bak","w",encoding="utf-8")

print(f.tell(),f_new.tell())
for line in f:
    if find_str in line:
        line = line.replace(find_str,replace_str)
    f_new.write(line)
f.close()
f_new.close()

  

2 修改haproxy配置文件

用到函数:

arg = """{
    'bakend': 'www.oldboy.org',
    'record': {
        'server': '100.1.7.9',
        'weight': 20,
        'maxconn': 30
    }
}"""
arg = eval(arg)
print(arg,type(arg))

  

需求:

1、查
    输入:www.oldboy.org
    获取当前backend下的所有记录

2、新建
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

3、删除
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

  

原配置文件:

eval()

global       
        log 127.0.0.1 local2
        daemon
        maxconn 256
        log 127.0.0.1 local2 info
defaults
        log global
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
        option  dontlognull

listen stats :8888
        stats enable
        stats uri       /admin
        stats auth      admin:1234

frontend oldboy.org
        bind 0.0.0.0:80
        option httplog
        option httpclose
        option  forwardfor
        log global
        acl www hdr_reg(host) -i www.oldboy.org
        use_backend www.oldboy.org if www

backend www.oldboy.org
        server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000

  

字符编码与转码

ASSCI英文及符号占1个字节;unicode占2个字节;utf-8英文字符按ASCII码形式存储,中文占3个字节。

1 python2.x下:

#-*- coding:utf-8 -*-
import sys
print(sys.getdefaultencoding())

s = "你好"
# utf-8 --> gbk 编码成(需指定编码)unicode再解码成gbk
s_to_unicode = s.decode("utf-8")
print(s_to_unicode)
s_to_gbk = s_to_unicode.encode("gbk")
print(s_to_gbk)

# gbk --> utf-8
gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8")
print(gbk_to_utf8)

#输出内容
# assci
# 你好
# (乱码)
# 你好
#-------------------------------------
s2 = u"你好"		# 现在是unicode
print(s)		# unicode 与 utf-8 之间可以直接打印

s_to_gbk = s.encode("gbk")
print(s_to_gbk)

# gbk --> utf-8
gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8")
print(gbk_to_utf8)

  

2 python3.x:

decode:编码成字符串

encode:解码成对应字符编码的二进制

#-*- coding:gbk -*-		#这里为文件字符编码,变量s还是unicode
s = "你好"
print(s)
s_gbk = s.encode("gbk")
print(s_gbk)      #默认就是unicode,不用decode
print(s.encode())

gbk_to_utf8 = s_gbk.decode("gbk").encode("utf-8")
print("utf-8",gbk_to_utf8)

utf8_to_gbk = gbk_to_utf8.decode("utf-8").encode("gbk")
print("gbk",utf8_to_gbk)


#--------------
print(s)
print(s.encode("gbk"))
print(s.encode("ut"))
print(s.encode("utf-8").decode("utf-8").encode("gbk2312").decode("gbk2312"))

  

函数与函数式编程

函数

  • 面向对象:——————》 类——————》 class

  • 面向过程:——————》 过程————》 def

  • 函数式编程:————》 函数————》 def

初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域。如:y=2x 编程语言中函数定义:函数是逻辑结构化和过程过得一种编程方法。

#python中函数的定义方法:

def test(x):
    "The function definitions"
    x += 1
    return x

# def:定义函数的关键字
# test:函数名
# ():内可定义形参
# "":文件描述(非必要,但是强烈建议为你的函数添加描述信息)
# x += 1:泛指代码块或程序处理逻辑
# return:定义返回值

ps:函数式编程就是:先定义一个数学函数,然后按照这个数字模型用编程语言去实现它。

# 函数
def func1():
    "testing1"
    print('in the func1')
    return 0

# 过程
def func2():
    "testing2"
    print('in the func2')

x=func1()
y=func2()

print(x,y)

  

return返回值

def test1():
    print("this is test1")

def test2():
    print("this is test2")
    return 0

def test3():
    print("this is test3")
    return 1,["zhangsan,lisi"],{"ar fu":"ar gui"}

t1 = test1()
t2 = test2()
t3 = test3()

print(t1)
print(t2)
print(t3)

# this is test1
# this is test2
# this is test3
# None
# 0
# (1, ['zhangsan,lisi'], {'ar fu': 'ar gui'})

 

1 日志加上时间

import time
def logger():
    time_format = '%Y-%m-%d %X'
    time_current = time.strftime(time_format)
    with open("yesterday","a+",encoding="utf-8") as f:
        f.write("%s end action\n" %time_current)

def test1():
    print("this is test1")
    logger()

def test2():
    print("this is test2")
    logger()

test1()
test2()

  

概括使用函数的三大优点

  • 代码复用

  • 保持一致性

  • 可扩展性

2 函数调用

调用方法:test()执行,()表示调用函数test,()内可以有函数也可以没有

参数:

1.形参和实参

形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用参数,目的是在函数调用时接收实参。

形参排放顺序:普通形参 -->*args --> 默认参数 -->***kwargs

ps:若默认参数放在*args前,会发生默认参数有多个值而报错

 

实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给参数

区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才可分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参。

2.位置参数和关键字

(标准调用:实参与形参位置一一对应;关键字调用:位置无固定)且关键字一定要在位置参数后面。

 

# 位置参数与关键字
def test(x,y,z):      #形参
    print(x)
    print(y)
    print(z)

# test(y=2,x=1)   #关键字,与形参顺序无关
# test(1,2)       #位置参数,实参与形参一一对应
test(5,y=2,z=4)     # 先位置参数,再接关键字(到最后且不使用前面的形参)

  

3.默认参数(给形参赋予一个初始值)

# 默认参数
def test(x,y=2):
    print(x,y)
    # print(y)

def conn(host,port=3306):
    # print(host)
    pass

test(1,3)
conn(1)

  

#默认参数特点:调用函数的时候,默认参数非必须传递 #用途:1.默认安装值 2.默认值

4.参数组

def test(x,y,z=2):      # 默认参数外,实参处必须写够位置参数个数
    print(x,y,z)
test(1,4)

  

*args

def test(*args,age=18):         #接收N个参数且转换成元组的形式
    print(args)
    print(age)

test(age=12,*[1,2,3,4])
test(*[1,2,4,5,5]) #args=tuple([1,2,4,5,5])


# *args:接收N个位置参数,转换成元组形式,或*[234,234]
def test(x,*args):
    print(x)
    print(args)

test(1,234,234,123)
test(1,*[234,234,123])
test(1)       #输出的args为空元组

  

**kwargs

def test2(**kwargs):      # **kwargs:把N个关键字参数装换成字典方式,或**{'name':'zhangsan','age':8}
    print(kwargs)
    print(kwargs['name'])
    print(kwargs['age'])

test2(name='zhangsan',age=8,sex='N')
test2(**{'name':'zhangsan','age':8})

  

*args和**kwargs

形参排放顺序:普通形参 --> *args --> 默认参数 -->**kwargs

def test4(name,*args,age=18,**kwargs): #**kwargs(为关键字参数)必须放最后
    print(name)
    print(age)
    print(args)
    print(kwargs)

test4('zhangsan','hello','hi',sex='m',hobby='tesla')

  

局部变量

函数内的变量为局部变量。global声明可以变成全局(不建议用)

musci = "最炫民族风"

def change_name(name):
    global music				#函数内声明全局变量
    music = "荷塘月色"
    print("before change: ",name,music)
    name = "ar fu"              #这个函数就是这个变量的作用域
    print("after change: ",name,music)

name = "zhang san"
change_name(name)
print(name)
print(music)

# before change:  zhang san 荷塘月色
# after change:  ar fu 荷塘月色
# zhang san
# 荷塘月色

  

函数内可以修改的外部的数据类型

#函数内可以修改外面全局的列表、字典、集合、类。不能改字符串和数字
school = "hello"
names = ["zhangsan","lisi","wangwu"]
def change_name():
    names[0] = "赵六"
    school = "hi"
    print("inside func",names,school)

change_name()
print(names,school)

  

全局与局部变量

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

当全局变量与局部变量同名时:

在定义局部变量的子程序内,局部变量起作用,在其他地方全局变量起作用。

递归

在函数内部,可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。

递归特性:

  1. 必须有一个明确的结束条件

  2. 每次进入更深一次递归是,问题规模相比上次递归都应有所减少

  3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈会加一层栈帧,每当函数返回,栈帧就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

def calc(n):
    print(n)
    if int(n/2) > 0:
        return calc(int(n/2))
    print("--> ",n)

calc(10)

  

匿名函数 lambda

匿名函数就是不需要显式的指定函数

def calc(n):
	return n**n
print(calc(10))

# 换成匿名函数
calc = lambda n:n**n
print(calc(10))

  

匿名函数主要是和其他函数搭配使用

res = map(lambda x:x**2,[1,5,7,4,8])
print(type(res))
for i in res:
    print(i)

  

<class 'map'>

1

25

49

16

64

函数式编程介绍

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

 

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

一、定义

简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。

主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:

  (1 + 2) * 3 - 4

传统的过程式编程,可能这样写:

  var a = 1 + 2;

  var b = a * 3;

  var c = b - 4;

函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:

  var result = subtract(multiply(add(1,2), 3), 4);

这段代码再演进以下,可以变成这样

add(1,2).multiply(3).subtract(4)

这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:

merge([1,2],[3,4]).sort().search("2")

因此,函数式编程的代码更容易理解。

要想学好函数式编程,不要玩py,玩Erlang,Haskell, 好了,我只会这么多了。。。

高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数称为高阶函数。

def add(x,y,f):
    return f(x)+f(y)

res = add(5,-10,abs)        #abs:绝对值
print(res)

  

posted @ 2021-03-09 00:48  破碎的屋檐  阅读(66)  评论(0编辑  收藏  举报