首页 > 代码库 > 第四天 内置函数2 随机码 装饰器 迭代器、生成器 递归 冒泡算法 JSON

第四天 内置函数2 随机码 装饰器 迭代器、生成器 递归 冒泡算法 JSON

 

关于函数的return

 

li = [11,22,33,44]

 

def f1(arg):

    arg.append(55)

 

li = f1(li)

 

print(li)

 

因为li = f1(li) 实际赋值的是f1的return,那么在这种情况下函数f1并未定义return,所以默认返回None

 

因此li的值应该是none

 

 

 

如果是

 

li = [11,22,33,44]

 

def f1(arg):

    arg.append(55)

 

f1(li)

 

print(li)

 

因为函数传递的参数实际是参数的引用,因此在函数中对参数坐的变更会影响原来的参数,因此返回的是11,22,33,44,55

 

 

 

 

将字符串转换为特定编码的字节类型

 

s = "刘博"

bytes(s,encoding="utf-8")

 

 

 

内置函数补充

 

callable() 判断对象是否可以被执行,函数可以被执行

 

 

 

chr()  将编码表中的序列转化为对应的字符,2.7内特指ASCII码

ord()  将编码表中的字符转化为对应的序号,2.7内特制ASCII码

 

 

 

随机验证码

 

import random #这个函数用来随机生成数字

 

tem = random.randrange(65,91) #指定随机生成数字的范围

 

c = chr(tem) #然后我们可以使用chr(i)的方式将i转换为对应的字符

 

在ASCII码表中65 - 91代表的是26个字母的大小写

 

如果一次生成多位的随机码,则可以按如下写法

li = []

for i in range(6):

    tem = random.randrange(65,91)

    c = chr(tem)

    li.append(c)

"".join(li)   #将生成的列表形成字符串

 

 

如果需要有数字则

 

li = []

for i in range(6):

    if  i == 2 or i == 4:

        tem = random.randrange(0,10)

        li.append(str(tem))        #因为在向列表中添加元素时,需要使用字符串类型,因此ASCII中0-10是数字因此需要将其转为字符串类型

    else:

        tem = random.randrange(65,91)

        c = chr(tem)

        li.append(c)

result = "".join(li)   #将生成的列表形成字符串

print(result)

 

 

上面的例子中数字的位置是固定的,如果希望将随机数做的跟彻底即数字的位置都是随机的

 

li = []

for i in range(6):

    r = random.randrange(0,6)

    if  r == 3 or r == 2:

        tem = random.randrange(0,10)

        li.append(str(tem))        #因为在向列表中添加元素时,需要使用字符串类型,因此ASCII中0-10是数字因此需要将其转为字符串类型

    else:

        tem = random.randrange(65,91)

        c = chr(tem)

        li.append(c)

result = "".join(li)   #将生成的列表形成字符串

print(result)

 

 

 

 

 

 

complie() 

eval()

exec()

 

任何一个python文件,计算机都要经过读取成字符串,编译,执行三个阶段。

 

complie()就是用来编译这个字符串的动作

s = "print(123)"         #s的值是字符串

r = complie(s,"<string>","exec)"   #r的值就是s编译后的结果,其中complie中s的位置也可以是一个文件名,如果是文件名就不需要后面的string参数,exec参数有3种值:single eval exec。其中如果选择single模式,则拿到的字符串会编译成单行的程序,如果是eval则会编译成表达式,如果是exec则按照原来的python代码编译

 

exec() 用来执行编译后的代码,和complie何用,先用complie编译,然后用exec执行。exec可以执行所有的python的命令,exec只是执行没有返回值,因此用exec运行一个表达式,是拿不到结果的,例如exec(“7+8+9”),只是执行但是结果是拿不到的。在执行代码的时候exec可以接受代码或者字符串。

 

eval()用来将字符串编译为表达式,例如  s = "8*8"  r = eval(s) , print(r)的时候会返回为64,eval只能执行表达式,eval有返回值,如果用eval(“7+8+9”),是能返回结果的,这点比exec强,对比exec。

 

 

 

dir() 快速获取一个对象 一个类中的功能   print(dir(dict)),查看字典这个函数中提供的功能

 

help() 获取一个对象提供的功能的详细解释,dir仅介绍功能名,help有解释。

 

divmod()  用来以元组的形式获取一个数除以另一个数的整数和余数,r = divmod(97,10) ,print(r) 返回(9,7),因为默认返回永远都是2个数,因此可以使用n1,n2 = divmod(97,10) 会自动给n1 = 9 ,n2 = 7

 

enumerate() 序列化

 

instance()  对象是类的实例,即 s = “alex” 那么alex是基于str这个类创建的对象,因此alex就是类str的一个实例,类是一个模板,而对象是对这个模板的实例。s = "alex"  r = isinstance(s,str)判断s是否是str这个类的实例,print(r)会返回True

 

filter() filter(函数,可迭代对象) 在执行filter的时候,首先会循环可迭代对象,在每次循环的内部会执行第一个参数所填写的函数,并拿到函数的结果,如果结果为真,则会把这次循环的元素添加到一个列表中

li = [11,22,33,44]

def f1(a)

    if a > 22

        return True

 

ret = filter(f1,li)

print(list(ret))

 

会返回[33,44],因此filter是基于提供的函数对可迭代对象进行筛选。

上面的filter而已用lambda表达式来实现

 

li = [11,22,33,44]

ret = filter(lambda a : a>22,li)

print(list(ret))

 

 

 

map() map(函数,可迭代对象),在执行map的时候,首先会循环可迭代函数,然后再每次循环的结果代入之前传递的函数中,并运行函数中定义的返回结果,将其追加到一个新的列表中

 

 

li = [11,22,33,44]

def f1(a):

    return a + 100

ret = map(f1,li)

 

print(list(ret))

 

结果就是[111,122.133.144]

 

同样可以使用lambda表达式

 

li = [11,22,33,44]

ret = map(lambda a : a+100 ,li]

print(list(ret))

 

 

 

filter() 函数的返回为True,则将结果加入列表

map() 将函数的结果加入列表

 

 

 

 

globals() 代表所有的全局变量,输出类型为字典,print(globals())打印当前代码中所有的全局变量以字典类型输出

locals() 代表所有的局部变量,输出类型为字典,print(local())打印当前代码中所有的局部变量以字典类型输出

 

hash() 生成对应内容的hash值   s=123 print(hash(s)),在python存储字典key的时候都是现将key进行hash算法之后再存储,因为hash算法算出的值是一个固定长度的,因此无论key有多长实际在存储时是同样长度的值。所有的语言都是这么操作的。这样有利于存储,也有利于查找。

 

len() 查看变量的长度,在python3中按照字符计算,在python2.7中按字节计算,因此在python3中如果想要按字节算长,应先将变量变为字节。

s = “李杰”

print(len(s))  结果为2按字符,

 

s = “李杰”

b = bytes(s,encoding=“utf-8”)

print(b)         结果为6按字节

 

max() 查找序列中的最大值

min() 查找序列中的最小值

sum() 序列求和

 

 

memoryview() 和内存地址相关的一个类

 

object() 是所有类的父类

 

pow() 求平方,一般写法为2**10代表2的10次方,同时也看而已写为pow(2,10)

 

range() 指定一个范围

 

reversed() 翻转

 

round()  将一个小数四舍五入

 

slice() 切片

 

sort() 排序 sort(列表) 等于 列表.sort

 

zip()  传入多个列表,zip会将所有列表的第一个元素拼为一个元组,第二个元素拼为一个元组以此类推。当元素长度不一样的时候,只会拼接到列表 元素最少的那个位置

 

l1=["liubo",23,19]

l2=[33,55]

l3=["aa","cc",22,55]

l4=zip(l1,l2,l3)

print(list(l4))

输出结果为

[(‘liubo‘, 33, ‘aa‘), (23, 55, ‘cc‘)]  # 只到了拼接到第二个元素,因为l2只有2个元素

 

 

 

 

深色框是要会的,打勾的是用的比较常用的

 

 

JSON 可以将可以将字符串根据其形式转换为对应的类型,也可以将对应类型的数据按照原格式转换为字符串

 

s = "[11,22,33,44]"   # 这是一个字符串而不是列表

n = json.loads(s)  # 通过这种方法,就将s的字符串转换成了列表,字典也可以,可以将文件中对应的格式写入python成为特定的数据类型

 

s = [11,22,33]  # 这是一个列表

n = json.dumps(s) # 通过这个就可以将其转化为字符串,但是格式仍然是列表的格式就像上例中的s ,比如可以用他来讲内容写入文件,写入文件必须要字符串 

 

转换通常元组是不行的,因为转化是跨语言的,但是元组的()是python独有的

使用转换时,如果想要通过loads将字符串转换成字典或列表,那么里面的字符串内部的字符串元素必须用双引号

 

 

 

装饰器

 

函数开发有开放封闭规则,即对函数本身是封闭的不能被随便改写,但是在外部是可以开放调用这个函数的。但是如果要批量修改多个函数,就需要用到装饰器。即在不改变原有函数的情况下,增加函数的功能

 

定义一个s1.py,代码如下

def outer(func):

    def inner():

        print("log")

        return func()

    return inner

 

@outer

def f1():

    print("F1")

 

@outer

def f2():

    print("F2")

 

 

@outer

def f3():

    print("F3")

 

这样当别人在通过调用f1函数时会首先执行outer函数中的功能。outer函数就是装饰器,在不改变f1函数功能的情况下,通过装饰器增加了f1函数的功能。

 

调用方法:

新建一个py文件

import s1       # 将之前创建的s1导入到代码中

s1.f1() # 调用s1代码中的f1函数

 

结果是

log # outer装饰器的输出

F1 # f1函数的输出

 

 

装饰器必备知识点:

 

1、

def f1():

    print(123)

 

def f1():

    print(456)
 

f1()

此时执行f1会打印456,因为python是一行一行加载代码,因此第二次f1会将f1指向print(456)的方法

 

 

2、

def f1():

    print(123)

 

def f2(xxx):

    xxx()

 

 

f2(f1)

 

函数的参数可以是另一个函数,因此输出123

 

 

@ + 函数名 就是装饰器

@outer的功能

1、自动执行outer函数并且将它下面的函数名f1当做参数传递(函数名代指整个函数,函数名()才是执行函数)

2、将outer函数的返回值重新赋值给f1

 

因此:

 

def outer(func):

    def inner():

        print("before")

    return inner

 

@outer

def f1():
    print("F1")

 

执行上面的函数的过程是

1、首先系统会自动执行outer函数,并将f1作为参数传递给outer函数

2、outer函数内部定义了一个新的函数inner,该函数打印before

3、outer函数返回了inner函数

4、outer函数将返回值inner函数重新赋值给f1

5、此时f1()的函数内容被替换为了inner的内容

6、因此执行f1()函数时打印before而不是F1

 

 

 

因此实际上装饰器就是讲@下一行的函数f1替换为outer返回的函数。那么我们执行之前的操作通过装饰器在某个函数之前或之后增加功能的操作实际上就是outer的内层函数的作用

 

def outer(func):

    def inner():

        print("before")

        func()

   print("after")

    return inner

 

@outer

def f1():

    print(123)

 

在上面outer函数内层函数中的func实际就是f1的原函数体,因为@outer将f1的原函数体传递给了func参数。因此在内层函数的操作就是在执行f1之前先执行before然后执行f1最后执行after

 

 

 

定义函数,未调用,函数内部不执行

 

函数名代指整个函数,函数名()才是执行函数

 

def outer(func):

    def inner():

        print("before")

        func()

   print("after")

    return inner

 

@outer

def f1():

    print(123)

因此这个例子中,outer函数的返回值必须是inner而不是inner(),因为这样做的目的时要将inner这个函数的函数体返回给f1,否则如果return inner(),则是返回的inner函数定义的返回值,而这个函数我们并未指定返回,默认返回为None。这样函数f1也就被替换为none。即便inner定义了返回值,也不是我们所要的。我们要的是inner函数体而不是返回值

 

 

 

如果原函数定义了返回值

那么在装饰器中的函数inner就会没有返回值,因为inner中只执行了func()而没有获取他的返回值。因此需要我们将这个返回值获取到

所以完整的装饰器写法应该入下

 

 

def outer(func):

    def inner():

        print("before")

        r = func() # 执行原函数,并获取原函数返回值

   print("after")

   return r  # 将原函数的返回值返回    

    return inner

 

 

 

如果原函数定义了参数

 

装饰器的函数应该使用万能参数来解决原函数带参数的问题。

 

def outer(func):

    def inner(*args,**kwargs):

        print("before")

        r = func(*args,**kwargs) # 此处python会直接将inner中的参数传递到func中。

   print("after")

   return r  # 将原函数的返回值返回    

    return inner

 

 

 

 

 

 

递归

 

一个函数在内部调用自己,就是递归。

递归特性的要求:

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

 

 

 

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

 

 

 

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

第四天 内置函数2 随机码 装饰器 迭代器、生成器 递归 冒泡算法 JSON