• python第四节


    1.1Python函数

    面向对象
    面向过程
    1.可读性差
    2.重用性差
    函数式编程

    1.1.1自定义函数

    看一个函数的例子:db文件内容为xuliangwei|123

    def login(username,password):
    '''
    用于用户登陆
    :param username: 用户输入用户名
    :param password: 用户输入密码
    :return: true,登陆成功 false,登陆失败
    '''
    file_name = open("db",'r')
    for line in file_name:
    line_list = line.split("|")
    if line_list[0] == username and line_list[1] == password:
    return True
    return False
    解释:

    1.def:表示函数的关键字
    2.函数名:函数的名称,日后根据函数名调用函数
    3.函数体:函数中进行一系列的逻辑计算,如:发送邮件
    4.返回值:当函数执行完毕后,可以给调用者返回数据。
    5.参数:为函数体提供数据(Python函数传递参数是传递一个引用。而不是重新赋值.)
    1.普通参数(严格按照顺序,将实际参数赋值给形式参数)
    2.默认参数(必须放置在参数列表的最后)
    3.指定参数(将实际参数复制给指定的形式参数)
    4.动态参数:
    *args 默认将位置参数,全部放置在元组中
    **kwargs 默认将关键字参数(字典),全部放置在字典中
    5.万能参数
    1.1.2 局部变量

    1.在程序中定义的变量成为局部变量。
    2.局部变量作用域是定义该变量的子程序。
    3.当全局变量与局部变量冲突时,在定义局部变量的子程序内,局部变量起作用,在其他地方全局变量起作用。

    #!/usr/bin/env python
    # Author:xuliangwei
    name = "XuLiangWei"
    def change_name(name):
    print("before change:", name)
    name = "我是有Tesla的男人" #定义局部变量
    print("after chage:", name)
    change_name(name)
    print("在外面看name改了么?",name)
    执行结果:

    before change: XuLiangWei
    after chage: 我是有Tesla的男人
    在外面看name改了么? XuLiangWei
    1.1.3 全局变量

    1.在程序一开始定义的变量称为全局变量。

    1.全局变量定义变量,必须都是大写(潜规则)。比如:NAME="xuliangwei"
    2.函数优先读当前环境变量,如果没有则会读全局变量,全局变量在所有的作用域都可读。
    3.修改全局变量需要先global name,表示name是全局变量(重新赋值)。
    4.特殊:列表,字典,元组嵌套列表,可修改,不可重新赋值。
    1.1.4内置函数

    # all #非0即真
    # any #
    # bool #0和,空字典空列表都是假
    # callable #表示是否可执行,或是否可调用
    # dir #快速查看对象提供了哪些功能
    # divmod #文章分页使用
    # isinstance #用于判断,对象是否是某个类的实例
    # globals #列出全局变量
    # locals #列出所有局部变量
    # hash #
    #enumerate
    #float
    #format
    #frozenset
    # max #最大
    # min #最小
    # sum #求和
    # int #整数
    # hex #十进制转换十六进制
    # bin #十进制转二进制
    # oct #十进制转十进制
    # filter #内部循环,参数比较
    # map #将函数返回值添加到结果中
    # compile #将字符串,编译成Python代码
    # eval #执行表达式,并且获取结果
    # exec #执行Python代码,接收:代码或者字符串
    #id #查看内存地址
    #input #等待用户输入
    # isinstance #查看某个对象是不是某个类的实例
    # issubclass #
    # len #查看长度
    # list #
    # memoryview #查看内存地址相关类
    # next #
    # iter #创建迭代器
    # object #所有类的复类
    # open #
    # ord #
    # pow #
    # print #
    # property #
    # range #
    # repr #
    # reversed #反转
    # round #
    # set #集合
    # slice #
    # sorted #
    # staticmethod #
    # str #字符串
    # super #面向对象
    # tuple #元祖
    # type #类型
    # vars #当前模块有哪些变量
    # zip #压缩
    # __import__ #导入模块
    # delattr()
    # getattr()
    # setattr()
    1.1.5函数返回值

    想要获取函数的执行结果,就可以用return语句把结果返回。

    1.函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为return语句代表着函数的结果。
    2.如果未在函数中指定return,那这个函数的返回值为None。
    1.1.6递归函数

    在函数内部,可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。

    #!/usr/bin/env python
    # Author:xuliangwei
    def calc(n):
    print(n)
    if int(n/2) ==0:
    return n
    return calc (int(n/2))
    calc(10)
    递归特征:
    1.必须有一个明确的结束条件。
    2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少。
    3.递归效率不高,递归层次过多会导致栈益处(在计算机中,函数调用是通过栈(stack)这种数据结果实现的,每当进入一个函数调用,栈就会加一层栈帧,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈益处。)

    1.1.7匿名函数

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

    #!/usr/bin/env python
    # Author:xuliangwei
    def calc(n):
    return n**n
    print(calc(10))
    #换成匿名函数
    calc = lambda n:n**n
    print(calc(10))
    #从上看来好像并无卵用,如果是这么用确实没毛改进,不过匿名函数主要是和其他函数搭配使用,如下:
    res = map(lambda x:x**2,[1,5,7])
    for i in res:
    print(i)
    #结果:
    1
    25
    49
    1.1.8高阶函数

    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

    #!/usr/bin/env python
    # Author:xuliangwei
    def add (x,y,f):
    return f(x) + f(y)
    res = add(3,-6,abs)
    print(res)
    1.1.9函数式编程

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

    而函数式编程,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
    我们首先要搞明白计算机(Computer)和计算(Compute)的概念。
    在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。
    而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。

    函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
    函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
    Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

    (1 + 2) * 3 - 4
    #传统的过程式编程,可能这样写:
      var a = 1 + 2;
      var b = a * 3;
      var c = b - 4;
    #函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,如下:
      var result = subtract(multiply(add(1,2), 3), 4);
    #这就是函数式编程(就会这么多)
    1.2装饰器

    1.自动执行xx函数并且将其下面的函数名f1当作参数传递
    2.将xx函数的返回值,重新赋值
    定义:本质是函数,(装饰其他函数)就是为其他函数添加附件功能。

    1.不能修改被装饰的函数的源代码
    2.不能修改被装饰的函数的调用方式
    实现装饰器知识储备:

    1.函数即"变量"
    2.高阶函数
    3.嵌套函数
    高级函数+嵌套函数=>装饰器
    无参数和无嵌套函数装饰器
    def foo(func):
    print
    'decorator foo'
    return func
    @foo
    def bar():
    print
    'bar'
    bar()
    # 没有嵌套函数,增加了打印"decorator foo"功能,并且没有改变函数的调用方式。
    无参数装饰器(没有参数)
    #!/usr/bin/env python
    # Author:xuliangwei
    import time
    def decorator(func):
    def wrapper(*args, **kwargs):
    start = time.time()
    func(*args, **kwargs)
    stop = time.time()
    print ('run time is %s ' % (stop - start))
    print ("timeout")
    return wrapper
    @decorator # 装饰器
    def test(list_test):
    for i in list_test:
    time.sleep(0.1)
    print ('-' * 20, i)
    # decorator(test)(range(10))
    test(range(10))
    # 可以看出装饰器decorator并没有参数
    有参数装饰器(没有参数)
    import time
    def timer(timeout=0):
    def decorator(func):
    def wrapper(*args, **kwargs): # 会给装饰器传递参数,因为无法确定装饰器有多少参数,所以使用这个。
    start = time.time()
    func(*args, **kwargs)
    stop = time.time()
    print ('run time is %s ' % (stop - start))
    print (timeout)
    return wrapper
    return decorator
    @timer(2) # 装饰器的参数为2
    def test(list_test):
    for i in list_test:
    time.sleep(0.1)
    print ('-' * 20, i)
    # timer(timeout=10)(test)(range(10))
    test(range(10))
    # 装饰器timer的参数为2,@timer(2)相当于test=timer(2)(test)
    1.3迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:
    一类是集合数据类型,如list、tuple、dict、set、str等;
    一类是generator,包括生成器和带yield的generator function。
    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
    可以使用isinstance()判断一个对象是否是Iterable对象:

    xuliangwei:~ xuliangwei$ Python3
    >>>
    >>> 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对象:

    xuliangwei:~ xuliangwei$ Python3
    >>>
    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False
    你可能会问,为什么list、dict、str等数据类型不是Iterator?

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

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

    小结
    凡是可作用于for循环的对象都是Iterable类型;
    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
    集合数据类型如list、dict、str等是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.4生成器

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

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

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

    l = [x * x for x in range(10)]
    print(l)
    g = (x * x for x in range(10))
    print(g)
    #执行结果:
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    <generator object <genexpr> at 0x101380938>
    1.只有在调用时才会生成相应的数据。
    只记录当前位置。
    只有一个next()方法。next()

  • 相关阅读:
    jQuery
    基于Js实现的UrlEncode和UrlDecode函数代码
    利用缓存、Timer间隔时间发送微信的实例,很有用的例子
    VisualStudio 自动排版等 快捷键
    正则表达式判断手机号码属于哪个运营商
    .Net常用方法汇总
    .NET中的三种Timer的区别和用法
    C# List和String互相转换
    Tempdb--TempDB Basic
    Tempdb--查看tempdb使用的脚本
  • 原文地址:https://www.cnblogs.com/xgblog/p/5808519.html
Copyright © 2020-2023  润新知