zoukankan      html  css  js  c++  java
  • Python Day4

    一、上节补充  

    匿名函数

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

    1 f = lambda x:x*x
    2 print(f(9))

    X就是形参

    1 res = map(lambda x:x**2,[1,5,7,4,8])
    2 for i in res:
    3     print(i)
    4 #输出
    5 # 1
    6 # 25
    7 # 49
    8 # 16
    9 # 64

    就是将列表[1,5,7,4,8]中每一个元素进行平方运算再返回

    内置参数

    内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii

     1 __author__ = "Alex Li"
     2 
     3 print( all([1,-5,3]) )
     4 print( any([]) )
     5 a= ascii([1,2,"开外挂开外挂"])
     6 print(type(a),[a])
     7 a = bytes("abcde",encoding="utf-8")
     8 b = bytearray("abcde",encoding="utf-8")
     9 print( b[1] )
    10 b[1]= 50
    11 print(b)
    12 
    13 
    14 print(a.capitalize(),a)
    15 def sayhi():pass
    16 print( callable(sayhi) )
    17 
    18 code = '''
    19 def fib(max): 10
    20  n, a, b = 0, 0, 1
    21  while n < max: n<10
    22      print(b)
    23      yield b
    24      a, b = b, a + b
    25      a = b     a =1, b=2, a=b , a=2,
    26       b = a +b b = 2+2 = 4
    27      n = n + 1
    28  return '---done---'
    29 
    30 f= fib(10)
    31 g = fib(6)
    32 while True:
    33  try:
    34      x = next(g)
    35      print('g:', x)
    36  except StopIteration as e:
    37      print('Generator return value:', e.value)
    38      break
    39 
    40 '''
    41 
    42 py_obj = compile(code,"err.log","exec")
    43 exec(py_obj)
    44 
    45 exec(code)
    46 
    47 
    48 def sayhi(n):
    49   print(n)
    50   for i in range(n):
    51       print(i)
    52 sayhi(3)
    53 
    54 (lambda n:print(n))(5)
    55 calc = lambda n:3 if n<4 else n
    56 print(calc(2))
    57 
    58 res = filter(lambda n:n>5,range(10))
    59 res = map(lambda n:n*2,range(10))
    60 res = [ lambda i:i*2 for i in range(10)]
    61 import functools
    62 res = functools.reduce( lambda x,y:x*y,range(1,10 ))
    63 print(res )
    64 
    65 a = frozenset([1,4,333,212,33,33,12,4])
    66 print(globals())
    67 
    68 def test():
    69  local_var =333
    70  print(locals())
    71  print(globals())
    72 test()
    73 print(globals())
    74 print(globals().get('local_var'))
    75 
    76 
    77 a = {6:2,8:0,1:4,-5:6,99:11,4:22}
    78 
    79 print(  sorted(a.items()) )
    80 print(  sorted(a.items(),key=lambda x:x[1]) )
    81 print(a )
    82 
    83 a = [1,2,3,4,5,6]
    84 b = ['a','b','c','d']
    85 
    86 for i in zip(a,b):
    87  print(i)
    88 
    89 #import 'decorator'
    90 __import__('decorator')
    测试代码

    二、本节内容  

    列表生成式,迭代器&生成器

    列表生成式

    1 >>> a = [i+1 for i in range(10)]
    2 >>> a
    3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    生成器

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

    所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

    要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

    1 >>> L = [x * x for x in range(10)]
    2 >>> L
    3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    4 >>> g = (x * x for x in range(10))
    5 >>> g
    6 <generator object <genexpr> at 0x1022ef630>

    创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

    我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

    如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

    1 >>> next(g)
    2 0
    3 >>> next(g)
    4 1
    5 。。。。。
    6 >>> next(g)
    7 Traceback (most recent call last):
    8   File "<stdin>", line 1, in <module>
    9 StopIteration

    我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

    当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

    1 >>> g = (x * x for x in range(10))
    2 >>> for n in g:
    3 ...     print(n)
    4 ... 
    5 0
    6 。。。
    7 81

    所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

    generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

    比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

    1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

    1 def fib(max): #10
    2     n, a, b = 0, 0, 1
    3     while n < max: #n<10
    4         print(b)
    5         a, b = b, a + b
    6         n = n + 1
    7     return '---done---'

    注意,赋值语句:

    a, b = b, a + b

    相当于:

    t = (b, a + b) # t是一个tuple
    a = t[0]
    b = t[1]

    但不必显式写出临时变量t就可以赋值。

    上面的函数可以输出斐波那契数列的前N个数:

    >>> fib(6)
    1
    1
    2
    3
    5
    8
    'done'

    仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

    也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

    1 def fib(max):
    2     n, a, b = 0, 0, 1
    3     while n < max:
    4         yield b
    5         a, b = b, a + b
    6         n = n + 1
    7     return 'done'

    这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

    >>> f = fib(6)
    >>> f
    <generator object fib at 0x104feaaa0>

    这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

     1 #!/usr/bin/env python3
     2 # -*- coding: utf-8 -*-
     3 def quqian(money):
     4     while money > 0:
     5         money -=100
     6         yield 100
     7         print("又来取钱了,傻Ⅹ")
     8 a=quqian(1000)
     9 print(a.__next__())
    10 print(a.__next__())
    11 print("买东西")
    12 print(a.__next__())
    13 print(a.__next__())
    14 print(a.__next__())
    15 print(a.__next__())
    16 print(a.__next__())
    17 print(a.__next__())
    18 print(a.__next__())
    19 print(a.__next__())

    异步并发

     1 #!/usr/bin/env python3
     2 # -*- coding: utf-8 -*-
     3 import time
     4 def chihuo(name):
     5     print("开始吃烧饼了!")
     6     while True:
     7         sb=yield
     8         print("{0}吃烧饼{1}了".format(name,sb))
     9         print("{}吃完了".format(name))
    10 def zuo(name2):
    11     a=chihuo("小明")
    12     b=chihuo("小聪")
    13     a.__next__()
    14     b.__next__()
    15     print("{}开始做烧饼了".format(name2))
    16     for i in range(1,11):
    17         time.sleep(2)
    18         print("做了两个烧饼")
    19         a.send(i)
    20         b.send(i)
    21 zuo("厨子")

    练习

    杨辉三角定义如下:

    1           1
    2         1   1
    3       1   2   1
    4     1   3   3   1
    5   1   4   6   4   1
    6 1   5   10  10  5   1

    把每一行看做一个list,试写一个generator,不断输出下一行的list:

     1 #!/usr/bin/env python3
     2 # -*- coding: utf-8 -*-
     3 # Author:Breakering
     4 #           1
     5 #         1   1
     6 #       1   2   1
     7 #     1   3   3   1
     8 #   1   4   6   4   1
     9 # 1   5   10  10  5   1
    10 
    11 def triangle():
    12     l = [1]
    13     while True:
    14         yield l
    15         l.append(0)
    16         l = [l[i]+l[i-1] for i in range(len(l))]
    17 
    18 count = 0
    19 for i in triangle():
    20     if count < 10:print(i)
    21     else:break
    22     count+=1

    结果如下:

     1 [1]
     2 [1, 1]
     3 [1, 2, 1]
     4 [1, 3, 3, 1]
     5 [1, 4, 6, 4, 1]
     6 [1, 5, 10, 10, 5, 1]
     7 [1, 6, 15, 20, 15, 6, 1]
     8 [1, 7, 21, 35, 35, 21, 7, 1]
     9 [1, 8, 28, 56, 70, 56, 28, 8, 1]
    10 [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

    小结

    generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。

    要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。

    请注意区分普通函数和generator函数,普通函数调用直接返回结果:

    1 >>> r = abs(6)
    2 >>> r
    3 6

    generator函数的“调用”实际返回一个generator对象:

    1 >>> g = fib(6)
    2 >>> g
    3 <generator object fib at 0x1022ef948>

    生成器笔记:

    1. 只有在调用时才会生成相应的数据
    2. 只记录当前位置
    3. 只有一个__next__()方法

    迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如listtupledictsetstr等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    可以使用isinstance()判断一个对象是否是Iterable对象:

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False

    而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

    可以使用isinstance()判断一个对象是否是Iterator对象:

    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True

    你可能会问,为什么listdictstr等数据类型不是Iterator

    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

    小结

    凡是可作用于for循环的对象都是Iterable类型;

    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

    集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

    Python的for循环本质上就是通过不断调用next()函数实现的,例如:

    for x in [1, 2, 3, 4, 5]:
        pass

    实际上完全等价于:

    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    # 循环:
    while True:
        try:
            # 获得下一个值:
            x = next(it)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break

    装饰器

    装饰器:

    定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能
    原则:1.不能修改被装饰的函数的源代码
       2.不能修改被装饰的函数的调用方式

    实现装饰器知识储备:
         1.函数即“变量”
         2.高阶函数
         a:把一个函数名当做实参传给另外一个函数
        (在不修改被装饰函数源代码的情况下为其添加功能)
         b:返回值中包含函数名
        (不修改函数的调用方式)
         3.嵌套函数

    高阶函数 + 嵌套函数 ===》 装饰器

     1 import time
     2 def timmer(func):
     3     def warpper(*args,**kwargs):
     4         start_time=time.time()
     5         func()
     6         stop_time=time.time()
     7         print('the func run time is %s' %(stop_time-start_time))
     8     return warpper
     9 
    10 @timmer
    11 def test1():
    12     time.sleep(3)
    13     print('in the test1')
    14 
    15 test1()
    装饰器预览

    函数即变量理解:

    前奏1

     1 #函数即变量
     2 
     3 #示范一:
     4 # def foo():
     5 #     print('in the foo')
     6 # foo()
     7 
     8 #示范二:
     9 def bar():
    10     print('in the bar')
    11 def foo():
    12     print('in the foo')
    13     bar()
    14 foo()
    15 
    16 #示范三:
    17 def foo():
    18     print('in the foo')
    19     bar()
    20 def bar():
    21     print('in the bar')
    22 foo()
    23 
    24 #示范四:
    25 # def foo():
    26 #     print('in the foo')
    27 #     bar()
    28 #foo()
    29 # def bar():
    30 #     print('in the bar')
    View Code

    前奏2

     1 # import time
     2 # def bar():
     3 #     time.sleep(3)
     4 #     print('in the bar')
     5 #
     6 # def test1(func):
     7 #     start_time=time.time()
     8 #     func()    #run bar
     9 #     stop_time=time.time()
    10 #     print("the func run time is %s" %(stop_time-start_time))
    11 #
    12 # test1(bar)
    13 # bar()
    14 
    15 
    16 # x=1
    17 # y=x
    18 #
    19 # func=bar
    20 # func()
    21 
    22 import time
    23 def bar():
    24     time.sleep(3)
    25     print('in the bar')
    26 def test2(func):
    27     print(func)
    28     return func
    29 
    30 # print(test2(bar))
    31 bar=test2(bar)
    32 bar()  #run bar
    View Code

    前奏3

    1 def foo():
    2     print('in the foo')
    3     def bar():
    4         print('in the bar')
    5 
    6     bar()
    7 foo()
    View Code

    正题

     1 import time
     2 def timer(func): #timer(test1)  func=test1
     3     def deco(*args,**kwargs):
     4         start_time=time.time()
     5         func(*args,**kwargs)   #run test1()
     6         stop_time = time.time()
     7         print("the func run time  is %s" %(stop_time-start_time))
     8     return deco
     9 @timer  #test1=timer(test1)
    10 def test1():
    11     time.sleep(1)
    12     print('in the test1')
    13 
    14 @timer # test2 = timer(test2)  = deco  test2(name) =deco(name)
    15 def test2(name,age):
    16     print("test2:",name,age)
    17 
    18 test1()
    19 test2("alex",22)

    带参数的装饰器

     1 user,passwd = 'alex','abc123'
     2 def auth(auth_type):
     3     print("auth func:",auth_type)
     4     def outer_wrapper(func):
     5         def wrapper(*args, **kwargs):
     6             print("wrapper func args:", *args, **kwargs)
     7             if auth_type == "local":
     8                 username = input("Username:").strip()
     9                 password = input("Password:").strip()
    10                 if user == username and passwd == password:
    11                     print("33[32;1mUser has passed authentication33[0m")
    12                     res = func(*args, **kwargs)  # from home
    13                     print("---after authenticaion ")
    14                     return res
    15                 else:
    16                     exit("33[31;1mInvalid username or password33[0m")
    17             elif auth_type == "ldap":
    18                 print("搞毛线ldap,不会。。。。")
    19 
    20         return wrapper
    21     return outer_wrapper
    22 
    23 def index():
    24     print("welcome to index page")
    25 @auth(auth_type="local") # home = wrapper()
    26 def home():
    27     print("welcome to home  page")
    28     return "from home"
    29 
    30 @auth(auth_type="ldap")
    31 def bbs():
    32     print("welcome to bbs  page")
    33 
    34 index()
    35 print(home()) #wrapper()
    36 bbs()

    另附本人对装饰器的一些特殊理解:http://www.cnblogs.com/breakering/p/6100973.html

    软件目录结构规范:

    参考大王博客:http://www.cnblogs.com/alex3714/articles/5765046.html

    三、作业  

    有以下员工信息表

     

    当然此表你在文件存储时可以这样表示

    1,Alex Li,22,13651054608,IT,2013-04-01

    现需要对这个员工信息文件,实现增删改查操作

    1. 可进行模糊查询,语法至少支持下面3种:
      1.   select name,age from staff_table where age > 22
      2.   select  * from staff_table where dept = "IT"
      3.       select  * from staff_table where enroll_date like "2013"
      4. 查到的信息,打印后,最后面还要显示查到的条数 
    2. 可创建新员工纪录,以phone做唯一键,staff_id需自增
    3. 可删除指定员工信息纪录,输入员工id,即可删除
    4. 可修改员工信息,语法如下:
      1.   UPDATE staff_table SET dept="Market" WHERE where dept = "IT"

     注意:以上需求,要充分使用函数,请尽你的最大限度来减少重复代码!

  • 相关阅读:
    Linus大神Win 7发布当天踢馆恶搞
    使用OpenSSL生成CSR文件,并申请全球通用SSL证书
    看Google的1000万.不是美元..是1000万台服务器!
    常见病毒 木马进程速查表
    GeoServer 2.0 正式版发布
    linux LiveCD 制作笔记
    开源WEB服务器lighttpd 1.4.24发布
    Nginx 的 server_names_hash_bucket_size 问题
    商业开源厂商最爱GPL,GPL并不能保证软件自由
    MySQL update回滚 mysqlbinlog回复数据
  • 原文地址:https://www.cnblogs.com/breakering/p/6718049.html
Copyright © 2011-2022 走看看