学习笔记五 函数和常用模块

一.列表生成式:

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

运用列表生成式,可以快速生成list,可以通过一个list推导出另一个list,而代码却十分简洁。

[表达式 for循环]

s =[1,2,3,4,5,6,7,8]

res1 = [ i+1 for i in s]
res2 = [str(i) for i in s]
print(res1)
print(res2)

运行结果:

[2, 3, 4, 5, 6, 7, 8, 9]
['1', '2', '3', '4', '5', '6', '7', '8']

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

res=[x * x for x in range(1, 11) if x % 2 == 0]
print(res)

运行结果:

[4, 16, 36, 64, 100]

还可以使用两层循环,可以生成全排列:

res=[m + n for m in 'ABC' for n in 'XYZ']
print(res)

运行结果:

['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

for循环其实可以同时使用两个甚至多个变量,比如dictiteritems()可以同时迭代key和value:

d = {'x': 'A', 'y': 'B', 'z': 'C' }
res=[k + '=' + v for k, v in d.items()]
print(res)

运行结果:

['x=A', 'y=B', 'z=C']

二.函数:

1.函数返回return的作用有两点:

    1、把函数处理的结果返回

    2、结束函数,函数里面遇到return,函数立即结束

2.全局变量:

  python里分两种数据类型:可变类型和不可变类型

  如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

  可变类型(值可以修改):

    列表list

    字典dict

  不可变类型(值不允许修改):

    数值类型int,long,bool,float

    字符串str

    元组tuple 

  可变类型表示修改值后id不会发生变化,都是一个标签,一改都改;不可变类型则修改值后id也变了,换了一个引用,是不同的标签不同的变量函数里如果对可变类型修改,则在函数外面这个变量值也会变化,不可变类型则在函数外面不会发生变化(类似内部变量不影响外部变量)
 

  全局变量
  #list、字典、集合,不需要声明global
  #字符串、数值类型、元组 需要声明global

def test():
    global a
    a = 5
    print(id(a))
    a = 6
    print(id(a))

def test1():
    c= a + 5
    return c
test()
res = test1()
print(res)

运行结果:

1523215552
1523215584
11

因为是不可变类型,所以定义了全局变量后,当a值重新赋值6的时候,id也发生了变化,不是对同一个id的变量进行修改

a=5
def test():
    global a
    print(id(a))
    a=a+5
    print(id(a))
    return a


res = test()
print(res)
print(a,id(a))

运行结果:

1523215552
1523215712
10
10 1523215712

a是不可变类型的全局变量,当test声明引用全局时,之后a=a+5,右边的a是id 1523215552,左边由于不可变原因,所以新生成了一个全局的引用id 1523215712,值为11,此时有两个全局变量a(id不同),值也不同,一个为5,一个为11。注意的是gloable不声明的话,a会当成一个未定义的局部变量报错!

同理:

 1 def test():
 2     global a
 3     a = 5
 4     print(id(a))
 5     a = 6
 6     print(id(a))
 7 
 8 def test1():
 9     global a
10     print(id(a))
11     a= a + 5
12     print(id(a))
13     return a
14 
15 test()
16 res = test1()
17 print(res)
18 print(a,id(a))
1523215552
1523215584
1523215584
1523215744
11
11 1523215744

3.浅拷贝与深拷贝:

  浅拷贝:两个变量指向的是同一块内存地址(id)

  深拷贝:是会开辟一个新的内存,存放数据,就是两块不同内存(id)。

比较两段代码及结果:

1 import copy
     #0 1 2
2 num1 = [1,1,2,3,4,5,6,7,7,8] 3 num2 = num1 #浅拷贝 4 print(id(num1)) 5 print(id(num2)) 6 for i in num2: 7 if i%2!=0: 8 num1.remove(i) 9 print(num1)
2412905492616
2412905492616
[1, 2, 4, 6, 7, 8]

----------------------------------------------

1 import copy
     #0 1 2
2 num1 = [1,1,2,3,4,5,6,7,7,8] 3 num2 = copy.deepcopy(num1)#深拷贝 num2=num1[:]也属于深拷贝 4 print(id(num1)) 5 print(id(num2)) 6 for i in num2: 7 if i%2!=0: 8 num1.remove(i) 9 print(num1)
1872643092616
1872643092744
[2, 4, 6, 8]

循环删除一个列表会有一个错位问题:因为在循环num1,并删除num1的元素时,列表的位置发生了移位,当删除“1”后,第二个元素“1”补位,这样第二个“1”就躲过了被删除的命运被留了下来,列表是通过下标循环,读过的下标就不会再读,轮到“2”了,“2”被删除之后,“3”来补位,以此类推!!

4.函数可变参数

当函数定义的时候有多个参数,则在函数调用的时候要注意传入参数的顺序

1 def mysql(host,user,password,port,charset,sql,db):
2     print('连接mysql')

例如上述代码的参数有7个,则以下传入的顺序都是正确的

1 mysql('ip','user','sdfsdf',3306,'sdfsdf','select','db')
2 mysql(user='root',password='123456',host='192.168.1.3',port=3306,sql='sdfsdf',db='sdfsdf',charset='sdfsdf')
3 mysql('192.168.1.1','root',port=3306,password='sdfsdf')

但是下述方式不正确,因为在函数定义的时候,参数的顺序是固定好的,如果传值得时候严格按照顺序传入而不带形参,python是可以识别的,如果打乱顺序指定形参传值,之后的形参就不能省略了

mysql(password='123456','root',...,) 

5.可变参数:*args  **args

如果一个函数定义时发现需要传入的参数的个数是不确定的,则应该使用可变参数*arg,在函数调动的时候,python会将入参打包成元组的形式传给被调函数

def mysql2(ip,*info):
    print(info)

*info前可以带指定的参数,但是ip不能定义在*info后,因为如果是*info ip则python不知道传入的参数哪些是打包在*info内

1 def send_mail(*args):
2     print(args)
3 
4 send_mail('[email protected]')
5 send_mail('[email protected]','[email protected]','[email protected]')

除了以上的元组形式,python还支持dict形式的参数传入,需要用**args

 1 def mysql(**mysql_info):
 2     print(mysql_info)
 3 
 4 dic = {
 5     'host':'192.168.1.1',
 6     'user':'root',
 7     'password':123456,
 8     'port':3306,
 9     'charset':'utf-8',
10     'sql':'sql',
11     'db':'db'
12 }
13 mysql(**dic)
{'host': '192.168.1.1', 'user': 'root', 'password': 123456, 'port': 3306, 'charset': 'utf-8', 'sql': 'sql', 'db': 'db'}

三.常用模块

json模块:特定是用且必须用"""括起来的一个字典形式,本质上是一个字符串

json是网络传输的一种格式,所以他是一个字符串,在python里使用里面的元素时对字符串操作非常不方便,所以需要用json模块将这个字符串转成容易操作的dict形式,在写入文本对数据持久性存储的时候再将他转换成字符串写入文本。

 1 import json
 2 #解析json的
 3 
 4 # json_str = '''
 5 # {"name":"xiaohei","age":18,"sex":"男","age":18}
 6 # '''
 7 # res = json.loads(json_str) #把字符串(json串)转成字典
 8 # print(res)
 9 # print(type(json_str))
10 # print(type(res))
11 
12 dic = {
13     "xiaohei":{
14         "age":18,
15         "password":12345,
16         "sex":"",
17         "addr":"北京"
18     },
19     "马春波":{
20         "age":18,
21         "password":12345,
22         "sex":"",
23         "addr":"北京"
24     },
25     "王东泽":{
26         "age":18,
27         "password":12345,
28         "sex":"",
29         "addr":"北京"
30     },
31 }
32 # res = json.dumps(dic,ensure_ascii=False,indent=4)#把字典变成字符串
33 # print(res)
34 # f = open('user.json','w',encoding='utf-8')
35 # f.write(res)
36 
37 #load 自己读
38 # f = open('user.json',encoding='utf-8')
39 # res = json.loads(f.read())
40 # print(res)
41 # res = json.load(f)
42 # print(res)
43 
44 #dump 自己写的
45 fw = open('newuser.json','w')
46 json.dump(dic,fw,indent=4,ensure_ascii=False)#indent表示缩进,一般4即可,ensure_ascii表示转码,false可以避免中文输入到文件中变成ascii码可读性差

一共四个方法:

loads/dumps对字符串的操作

load/dump对文件的操作

time模块:

时间戳和格式化好的时间不能直接互转,必须经过时间元组!

 1 import time
 2 
 3 #格式化好的时间 20181202
 4 #时间戳    2343242
 5 
 6 #时间元组
 7 
 8 # print(int(time.time()))#时间戳
 9 # res = time.strftime('%Y-%m-%d %H:%M:%S')#取当前格式化好的时间
10 # print(res)
11 
12 #时间戳转换成时间元组,时间戳转格式化好的时间
13 #time1 = time.gmtime(int(time.time()))#把时间戳转成时间元组,以标准时间的时间转换的
14 # time1 = time.localtime(int(time.time()))#把时间戳转成时间元组,以标准时间的时间转换的
15 # res = time.strftime('%Y-%m-%d %H:%M:%S',time1)
16 # print(res)
17 
18 
19 #格式化好的时间转时间戳
20 
21 timep = time.strptime('2018-10-23 15:38:59','%Y-%m-%d %H:%M:%S')
22 print(timep)
23 res = time.mktime(timep)#把时间元组转成时间戳
24 print(res)
25 #20181023 2323
26 def timestampToStr(timestamp=None,format='%Y-%m-%d %H:%M:%S'):
27     #时间戳转格式化好的时间
28     if timestamp:
29         time1 = time.localtime(timestamp)
30         res = time.strftime(format, time1)
31     else:
32         res = time.strftime(format)
33     return res
34 #20180304153958
35 def strTotimestamp(str=None,format='%Y%m%d%H%M%S'):
36     #格式化的时间转时间戳
37     if str:
38         timep = time.strptime(str, format)
39         res = time.mktime(timep)
40     else:
41         res = time.time()
42     return int(res)

os模块:

 1 import os
 2 res = os.listdir('/Users/nhy/Desktop') #列出某个目录下的所有文件
 3 # os.remove()#用于删除指定路径下的文件
 4 # os.rename()#方法用于命名文件或目录,从 src 到 dst,如果dst是一个存在的目录, 将抛出OSError。
 5 # os.mkdir(r'test/niuhy/haha')#创建文件夹
 6 # os.makedirs(r'test1/lyl/aaa')#会创建父目录
 7 # res = os.path.exists(r'/Users/nhy/Desktop/stu.txt')
 8 # os.path.isfile() #判断是否为文件
 9 # os.path.isdir()#判断是否为文件
10 # res = os.path.split(r'/Users/nhy/Desktop/stu.txt')#判断括号里的文件是否存在的意思,括号内的可以是文件路径。
11 # res = os.path.dirname(r'/Users/nhy/Desktop/stu.txt')#取父目录
12 # res = os.getcwd() #获取当前的目录
13 # os.chdir(r'/Users/nhy/Desktop/')#更改当前目录
14 # res = os.getcwd()
15 # print(res)
16 # open('a.txt','w')
17 # print(os.environ)#看你电脑的环境变量
18 #
19 # res = os.path.join('test','hhh','abc','a.txt')#拼接路径
20 # print(res)
21 # res= os.path.abspath('..')#根据相对路径取绝对路径
22 # print(res)
23 
24 # res = os.system('hhhsdf')#执行操作系统命令
25 # # print(res)
26 # res = os.popen('ifconfig').read()
27 # print('res',res)

猜你喜欢

转载自www.cnblogs.com/eichar/p/10080761.html