Python之路day4

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python之路day4相关的知识,希望对你有一定的参考价值。

坚持就是胜利。今天零下14度,从教室出来的路上真的很冷很冷,希望这个冬天自己不会白过,春暖花开的时候一定要给世界一个更好的自己。

原本以为day3的作业自己做得挺好的,没想到只得了B+。必须要加油了,比自己牛逼的人那么多,没有理由不再努力一些。

==>the start

1.迭代器(iterator)&生成器(generator)

迭代器可以被next()函数调用并返回下一个值,节省内存空间。注:Python3.0中使用__next__()

tmp = iter([alex, jack, rain])

print(tmp.__next__())
print(tmp.__next__())
print(tmp.__next__())
print(tmp.__next__())  # 再取值就会报错

list_tmp = [1, 22, 333, 4444, 55555]
for i in iter(list_tmp):
    print(i)

能被for直接循环的都是可迭代对象,如列表,字典等。判断一个对象是不是可迭代对象,可以使用isinstance(*, Iterable)来判断。

生成器在被调用的时候返回一个迭代器。生成器有个标志性的语法yield。

当生成器被调用时,yield返回一个值,并记住当前位置,下一次调用时,从yield下一句语句运行返回下一个值。

def catch_mony(amount):
    while amount > 0:
        amount -= 100
        print("又来取钱了!")
        yield "给你100吧,剩余:{}".format(amount)

atm = catch_mony(500)
print(type(atm))
print(atm.__next__())
print(atm.__next__())
print("去看电影!。。。")
print(atm.__next__())

======================================
运行结果:

<class generator>
又来取钱了!
给你100吧,剩余:400
又来取钱了!
给你100吧,剩余:300
去看电影!。。。
又来取钱了!
给你100吧,剩余:200

此外,yield还有实现在单线程模式下实现并发运算的效果。如下例:

技术分享
import time


def consumer(name):
    print("{}准备吃包子啦!".format(name))
    while True:
        baozi = yield   # yield也可以用于接收值
        print("第{}次的包子来了,被{}吃掉了!".format(baozi, name))


def producer(name):
    c1 = consumer(A)
    c2 = consumer(B)
    c1.__next__()
    c2.__next__()
    print("{}准备开始做包子了!".format(name))
    for i in range(1, 11):
        time.sleep(1)
        print("{}第{}次做了两个包子。".format(name, i))
        c1.send(i)  # 将i的值传给yield
        c2.send(i)  # 将i的值传给yield

producer("老板")
View Code

2.装饰器(decorator)

类似于一种动态增加函数功能的方法,使用@语法,放在它要装饰的函数定义处(函数定义的上面),实现为已经存在的函数增加新的功能。

Python通过使用装饰器来达到代码的开放与封闭。

@d1
def func():
    pass

相当于d1(func),把func函数当成是参数传进d1。
def login(func):
    print("这是验证功能。。。")
    return func


def home():
    print("This is the Home page.")


def tv():
    print("This is the TV page")

# 需求是在访问tv页面之前加上验证功能。
tv = login(tv)
tv()

上述方法虽然可以实现需求,但是把tv函数改变了,而且当login函数需要传入参数的时候,就不好处理了。下面是使用装饰器来实现:

def login(func):
    def inner():
        print("正在验证!。。。")
        func()
        print("welcome to the tv page!")
    return inner


@login
def tv():
    print("This is  the tv page!")

tv()

当代码运行到@login时,会把它下面装饰的tv函数作为自己的参数,此时即:func = tv

当tv()执行时,实际上执行inner()。

当被装饰的函数需要多个参数时:

技术分享
def login(func):
    def inner(*args):
        print("正在验证!。。。")
        func(*args)
        print("Have a nice time!")
    return inner


@login
def movie(*args):
    print("welcome {} to the {} page of movie!".format(*args))

movie("Alex", 3rd)
View Code

当被装饰的函数有返回值时,怎么处理呢?

技术分享
# 当被装饰的函数有返回值时:
def login(func):
    def inner(*args):
        print("正在验证!。。。")
        tmp = func(*args)
        print("Have a nice time!")
        return tmp  # 注意:此处应该将被装饰函数的返回值return
    return inner


@login
def movie(*args):
    print("welcome {} to the {} page of movie!".format(*args))
    return 666  # 被装饰的函数有返回值

num = movie("Alex", 3rd)
print(num)
View Code

装饰器也可以有自己的参数

技术分享
def login():
    print("开始进行验证。。。")


def errorhandle():
    print("出错啦。。。")


# 给装饰器加参数 复杂的装饰器
def f(arg):
    def outer(main_func):
        def inner():
            arg()
            main_func()
        return inner
    return outer


@f(errorhandle)
# @f(login)   # 给装饰器传入不同的函数,被装饰的函数就扩展了不同的功能。
def index():
    print("这是主程序。")


index()
View Code

其实这就相当于写了一个装饰器的框架,以后有新的需求就只需把新写的函数当成参数传到装饰器框架中就可以了。

技术分享
def login():
    print("开始进行验证。。。")


def errorhandle():
    print("出错啦。。。")


# 复杂的装饰器(装饰器框架)
def f(before_func, after_func):    # 第一层传入装饰器的参数
    def outer(main_func):   # 第二层传入被装饰的函数名
        def inner(*args):    # 第三层传入被装饰函数的参数
            before_func()
            main_func(*args)
            after_func()
        return inner
    return outer


@f(login, errorhandle)
def index(name):
    print("{}:这是主程序。".format(name))


index(alex)
View Code

3.递归

递归其实就是函数自己调用自己的过程。使用递归时应该避免栈溢出。(使用尾递归防止栈溢出)

def calc(n):
    print(n)
    if n / 2 > 1:
        res = calc(n/2)  # 在函数内部调用自己   
        print("res:{}".format(res))
    print("n:{}".format(n))
    return n

斐波那契数列:

# 斐波那契数列练习
def func(arg1, arg2, stop):
    if arg1 == 0:
        print(arg1)
        print(arg2)
    arg3 = arg1 + arg2
    if arg3 < stop:
        print(arg3)
        func(arg2, arg3, stop)

二分法:

技术分享
# 二分法查找find_num在不在data_base中:
def binary_search(data_base, find_num):
    mid = int(len(data_base)/2)
    if len(data_base) > 1:
        if data_base[mid] > find_num:
            binary_search(data_base[:mid], find_num)
        elif data_base[mid] < find_num:
            binary_search(data_base[mid:], find_num)
        else:
            print("找到了!")
    elif len(data_base) == 1:
        if data_base[0] == find_num:
            print("找到了!")
        else:
            print("没找到!")
    else:
        print("没找到!")

data_base = list(range(0, 10000000, 4))
binary_search(data_base, 2)
View Code

汉诺塔:

技术分享
# 汉诺塔游戏
# n:A柱上有多少个盘子,a:左边的柱子,b:中间的柱子,c:右边的柱子
# 把左边柱子上的n个盘子移动到右边的柱子的详细步骤,盘子分大小,小盘子只能放在比他大的盘子上。
def mov_h(n, a, b, c):
    if n == 1:
        print("{}==>{}".format(a, c))
    elif n > 1:
        mov_h(n-1, a, c, b)
        mov_h(1, a, b, c)
        mov_h(n-1, b, a, c)
    else:
        print("参数错误!")

mov_h(5, A, B, C)
View Code

4.算法基础(二维数组转换)

打印一个4*4的二维数组:

# 打印一个二维数组:
list_demo = [[i for i in range(4)] for i in range(4)]
for i in list_demo:
    print(i)

=================================
显示:

[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 2, 3]

现在想让这个二维数组顺时针旋转90度打印出来:

for i in range(len(list_demo)):
    for j in range(i, len(list_demo)):
        list_demo[i][j], list_demo[j][i] = list_demo[j][i], list_demo[i][j]

===================================
结果:

[0, 0, 0, 0]
[1, 1, 1, 1]
[2, 2, 2, 2]
[3, 3, 3, 3]

5.正则表达式

正则表达式就是代码界的瑞士军刀!

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

Python中的re模块,包含了正则表达式的所有功能。

 正则表达式的五种常用模式:

1.re.match(pattern, string, flags=0)  # 只匹配字符串的开头

2.re.search(pattern, string, flags=0)  # 匹配整个字符串,直到找到第一个匹配对象

3.re.split(pattern, string, maxsplit=0, flags=0)  # 用匹配到的对象将字符串分割成列表并返回

4.re.findall(pattern, string, flags=0)  # 找到所有的匹配对象,以列表形式返回

5.re.sub(pattern, repl, string, count=0,flag=0)  # 替换匹配到的对象

字符
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

 

实例描述
[Pp]ython 匹配 "Python" 或 "python"
rub[ye] 匹配 "ruby" 或 "rube"
[aeiou] 匹配中括号内的任意一个字母
[0-9] 匹配任何数字。类似于 [0123456789]
[a-z] 匹配任何小写字母
[A-Z] 匹配任何大写字母
[a-zA-Z0-9] 匹配任何字母及数字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了数字外的字符

 

次数
* 重复零次或更多次
+ 重复一次或更多次
重复零次或一次
{n} 重复n次
{n+} 重复n次或更多次
{n,m} 重复n到m次

 

实例描述
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 ‘\n‘ 在内的任何字符,请使用象 ‘[.\n]‘ 的模式。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w 匹配包括下划线的任何单词字符。等价于‘[A-Za-z0-9_]‘。
\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]‘。

匹配手机号码:

# 从字符串中查找手机号码
info = "hey my name is alex, and my phone number is 18651054604, please call me if you are pretty!"
result = re.search(r(1)[3578]\d{9}, info)
if result:
    print(result.group())
# 匹配输入的是否为正确的手机号格式
phone_num = input("Please input your phone number:")
result2 = re.match(r^1[3578]\d{8}[0-9]$, phone_num)
if result2:
    print("Your phone number is {}.".format(result2.group()))
else:
    print("Invalid number.")

IP:

# 字符串中查找IP
ip_addr = "inet 192.168.60.223 netmask 0xffffff00 broadcast 192.168.60.255"
p = re.compile(r\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
result = p.search(ip_addr)
if result:
    print(result.group())

# 判断输入是否为合法IP
ip_info = input("Please input the IP:").strip()
result2 = re.search(r^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$, ip_info)
if result2:
    print("Your IP is: {}".format(result2.group()))
else:
    print("Invalid input")

分组匹配:

contactInfo = "Oldboy School, Beijing Changping Shahe: 010-8343245"
match = re.search(r(.+), (.+): (\S+), contactInfo)
if match:
    print("get it!")
    print(match.group(0))   # group(0)指的是原始字符串
    print(match.group(1))   # group(1)指的是第1个子串
    print(match.group(2))   # group(2)指的是第2个子串
    print(match.group(3))   # group(3)指的是第3个子串
else:
    print("error")

email地址匹配:

# 字符串中查找email
email_info = "Hey guy, my email address is [email protected], send mail to me!"
match = re.search(r([a-z0-9])[a-z.0-9]{0,25}@[a-z.0-9]{1,20}.[a-z0-9]{1,8}, email_info)
if match:
    print(match.group())

# 匹配输入是否为有效email地址
email = input("Please input your email:").strip()
result = re.match(r^([a-z.0-9]{1,26})@([a-z.0-9]{1,20})(.[a-z0-9]{1,8})$, email)
if result:
    print("Your email is: {}".format(result.group()))
else:
    print("Invalid input!")

 

 

 

<==the end

以上是关于Python之路day4的主要内容,如果未能解决你的问题,请参考以下文章

Python之路,Day4

第四周 day4 python学习笔记

Day4 闭包装饰器decorator迭代器与生成器面向过程编程三元表达式列表解析与生成器表达式序列化与反序列化

python学习之路-day4.1

《Python运维开发之路》 装饰器&生成器&迭代器

Python学习之路-装饰器&生成器&正则表达式