坚持就是胜利。今天零下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("老板")

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')

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

# 当被装饰的函数有返回值时:
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)

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

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()

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

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')

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)

汉诺塔:

# 汉诺塔游戏
# 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')

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]

冒泡排序:

data = [10, 4, 33, 21, 54, 3, 8, 11, 5, 22, 2, 1, 17, 13, 6]
count = 0
for i in range(len(data)-1):
    count += 1
    for j in range(i, len(data)):
        count += 1
        if data[i] > data[j]:
            data[j], data[i] = data[i], data[j]

print(data)
print(count)
==============================================
结果:
[1, 2, 3, 4, 5, 6, 8, 10, 11, 13, 17, 21, 22, 33, 54]
133

5.正则表达式

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

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

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

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

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

p = re.compile(r'^[0-9]')   # 生成正则对象,提前解析匹配规则
m = p.match("1234Abc")  # match匹配到时返回一个Match对象,否则返回None
n = p.match("Abc1234")  # match只匹配字符串的开头
print("m:{}".format(m))
print("n:{}".format(n))
t = re.match(r'[0-9]+', "234abc234")
print("t:{}".format(t))
===============================================
结果:
m:<_sre.SRE_Match object; span=(0, 1), match='>
n:None
t:<_sre.SRE_Match object; span=(0, 3), match='>
# re匹配中文,中文Unicode中中文编码为\u4e00-\u9fa5
contact = "我是中文"
result = re.match(r'[\u4e00-\u9fa5]{2}', contact)
if result:
    print(result.group())
==============================================
结果:
我是

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

p = re.compile(r'[0-9]+')   # 生成正则对象,提前解析匹配规则
m = p.search("1234Abc5678Abc")  # search匹配整个字符串并返回第一个匹配到的对象,否则返回None
n = p.search("Abc1234Abc5678")  # search匹配整个字符串
print("m:{}".format(m))
print("n:{}".format(n))
==============================================
结果:
m:<_sre.SRE_Match object; span=(0, 4), match='>
n:<_sre.SRE_Match object; span=(3, 7), match='>

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

content = "Abc123.aBc456.abC789"
result = re.split(r'\.', content)
result2 = re.split(r'\.', content, 1)
result3 = re.split(r'[\.\d]+', content)
print("result:{}".format(result))
print("result2:{}".format(result2))
print("result3:{}".format(result3))
==============================================
结果:
result:['Abc123', 'aBc456', 'abC789']
result2:['Abc123', 'aBc456.abC789']
result3:['Abc', 'aBc', 'abC', '']

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

content = "Abc123.aBc456.abC789"
result = re.findall(r'\d+', content)    # 找到所有的匹配,并以列表形式返回
print("result:{}".format(result))
==============================================
结果:
result:[']

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

content = "1234Abc5678Abc"
result = re.sub(r'\d+', "哈哈", content)
result2 = re.sub(r'\d+', "哈哈", content, 1)
print("result:{}".format(result))
print("result2:{}".format(result2))
==============================================
结果:
result:哈哈Abc哈哈Abc
result2:哈哈Abc5678Abc 
字符
. 匹配除换行符以外的任意字符
\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")

命名的分组匹配:

contactInfo = "Oldboy School, Beijing Changping Shahe: 010-8343245"
match = re.search(r'(?P<name>.+), (?P<addr>.+): (?P<tel>\S+)', contactInfo)
if match:
    print(match.group('name'))
    print(match.group('addr'))
    print(match.group('tel'))
else:
    print("error")
==============================================
结果:
Oldboy School
Beijing Changping Shahe
010-8343245

email地址匹配:

# 字符串中查找email
email_info = "Hey guy, my email address is master@liwenzhou.com, 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!")

编译标志

编译标志让你可以修改正则表达式的一些运行方式。在 re 模块中标志可以使用两个名字,一个是全名如 IGNORECASE,一个是缩写,一字母形式如 I。(如果你熟悉 Perl 的模式修改,一字母形式使用同样的字母;例如 re.VERBOSE的缩写形式是 re.X。)多个标志可以通过按位 OR-ing 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

这有个可用标志表,对每个标志後面都有详细的说明。

标志 含义
DOTALL, S 使 . 匹配包括换行在内的所有字符
IGNORECASE, I 使匹配对大小写不敏感
LOCALE, L 做本地化识别(locale-aware)匹配
MULTILINE, M 多行匹配,影响 ^ 和 $
VERBOSE, X 能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂

I
IGNORECASE

使匹配对大小写不敏感;字符类和字符串匹配字母时忽略大小写。举个例子,[A-Z]也可以匹配小写字母,Spam 可以匹配 "Spam", "spam", 或 "spAM"。这个小写字母并不考虑当前位置。

L
LOCALE

影响 "w, "W, "b, 和 "B,这取决于当前的本地化设置。

locales 是 C 语言库中的一项功能,是用来为需要考虑不同语言的编程提供帮助的。举个例子,如果你正在处理法文文本,你想用 "w+ 来匹配文字,但 "w 只匹配字符类 [A-Za-z];它并不能匹配 "é" 或 "ç"。如果你的系统配置适当且本地化设置为法语,那么内部的 C 函数将告诉程序 "é" 也应该被认为是一个字母。当在编译正则表达式时使用 LOCALE 标志会得到用这些 C 函数来处理 "w 後的编译对象;这会更慢,但也会象你希望的那样可以用 "w+ 来匹配法文文本。

M
MULTILINE

(此时 ^ 和 $ 不会被解释; 它们将在 4.1 节被介绍.)

使用 "^" 只匹配字符串的开始,而 $ 则只匹配字符串的结尾和直接在换行前(如果有的话)的字符串结尾。当本标志指定後, "^" 匹配字符串的开始和字符串中每行的开始。同样的, $ 元字符匹配字符串结尾和字符串中每行的结尾(直接在每个换行之前)。

S
DOTALL

使 "." 特殊字符完全匹配任何字符,包括换行;没有这个标志, "." 匹配除了换行外的任何字符。

X
VERBOSE

该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。当该标志被指定时,在 RE 字符串中的空白符被忽略,除非该空白符在字符类中或在反斜杠之後;这可以让你更清晰地组织和缩进 RE。它也可以允许你将注释写入 RE,这些注释会被引擎忽略;注释用 "#"号 来标识,不过该符号不能在字符串或反斜杠之後。

<==the end

Python之路day4的更多相关文章

  1. Python之路,Day4 - Python基础4 (new版)

    Python之路,Day4 - Python基础4 (new版)   本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ...

  2. 小白的Python之路 day4 装饰器前奏

    装饰器前奏: 一.定义: 1.装饰器本质是函数,语法都是用def去定义的 (函数的目的:他需要完成特定的功能) 2.装饰器的功能:就是装饰其他函数(就是为其他函数添加附加功能) 二.原则: 1. 不能 ...

  3. Python之路,Day4 - Python基础4

    一.函数 (一)背景提要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码 1 2 3 4 ...

  4. python之路-Day4

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 函数是什么? 函数一词来源于数学,但编程中的「 ...

  5. 小白的Python之路 day4 装饰器高潮

    首先装饰器实现的条件: 高阶函数+嵌套函数 =>装饰器 1.首先,我们先定义一个高级函数,去装饰test1函数,得不到我们想要的操作方式 import time #定义高阶函数 def deco ...

  6. 小白的Python之路 day4 生成器

    一.列表生成式  看下面例子: 列表生成式的作用:主要是让代码更简洁(还有装X的效果) 二.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包 ...

  7. 小白的Python之路 day4 迭代器

    迭代器 学习前,我们回想一下可以直接作用于for循环的数据类型有以下几种: 1.集合数据类型,如list.tuple.dict.set.str等: 2.是generator,包括生成器和带yield的 ...

  8. 小白的Python之路 day4 json and pickle数据标准序列化

    一.简述 我们在写入文件中的数据,只能是字符串或者二进制,但是要传入文件的数据不一定全是字符串或者二进制,那还要进行繁琐的转换,然后再读取的时候,还要再转回去,显得很麻烦,今天就来学习标准的序列化:j ...

  9. 小白的Python之路 day4 软件目录结构规范

    软件目录结构规范 为什么要设计好目录结构? "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 一类同 ...

随机推荐

  1. UVA - 12230 Crossing Rivers (期望)

    Description You live in a village but work in another village. You decided to follow the straight pa ...

  2. 各浏览器对 window.open() 的窗口特征 sFeatures 参数支持程度存在差异

    标准参考 无. 问题描述 使用 window.open 方法可以弹出一个新窗口,其中 open 方法的 sFeatures 参数选项在各浏览器中支持程度不一,这有可能导致同样的代码使各浏览器中弹出窗口 ...

  3. JavaScript基础知识----六道有趣的Js基础题以及解答

    题目: 1.找出数字数组中最大的元素(使用Math.max函数)2.转化一个数字数组为function数组(每个function都弹出相应的数字)3.给object数组进行排序(排序条件是每个元素对象 ...

  4. [转载]MySql常用命令总结

    原文:http://www.php100.com/html/webkaifa/database/Mysql/2009/0910/3288.html1:使用SHOW语句找出在服务器上当前存在什么数据库: ...

  5. JAVA Metrics 度量工具使用介绍

    转载: http://blog.csdn.net/scutshuxue/article/details/8350135 http://koven2049.iteye.com/blog/968143 h ...

  6. Qt 学习 之 二进制文件读写

    在上一章中,我们介绍了有关QFile和QFileInfo两个类的使用.我们提到,QIODevice提供了read().readLine()等基本的操作.同时,Qt 还提供了更高一级的操作:用于二进制的 ...

  7. uvalive 2322 Wooden Sticks(贪心)

    题目连接:2322 Wooden Sticks 题目大意:给出要求切的n个小木棍 , 每个小木棍有长度和重量,因为当要切的长度和重量分别大于前面一个的长度和重量的时候可以不用调整大木棍直接切割, 否则 ...

  8. linux 命令之sar——监视系统状态

    摘要:在进行系统或者内核测试的时候,我们经常需要观察cpu利用率,缓冲区使用情况,文件读写情况等等.在linux系统下,我们可以用sar命令来达到这个要求. sar 命令行的常用格式: sar [op ...

  9. git 使用过程(一、准备工作)

    没有多余的废话,只是纯粹的捞干的记录下一自己使用Git的过程.(正在学习中,也是刚接触,记录过程可能有点乱.等熟悉之后在重新整理一下) 一.先下载git客户端 网址:http://msysgit.gi ...

  10. SQL常用语句集合(不断更新)

    1.多条件 查询 上下级 所有数据 select * from OrgUnit where (ParentId = '3' or OrgId='3' or ParentId in (select Or ...