zoukankan      html  css  js  c++  java
  • day15,内置函数一

    1,复习,如何从生成器里面取值,next(每次取一个值),send(不可以用在第一个,取下一个的时候,给上一个地方传一个值),for(没有break会一直取,直到取完),强制转换(会一次性把数据加载到内存里面)调用之后,函数内的代码不会执行,不取不干活,返回生成器。所有的生成器都是迭代器。

    2,作业一,面向函数编程了,要抽象功能

    # 3,处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
    def find_content(filename,content):
        with open(filename,encoding='utf-8') as f:  # 文件句柄,handler,类似一个操作杆,拿到它就可以去操作文件了。以后还会经常遇到,文件操作符,以后可能会叫文件对象
            for line in f:
                if content in line:
                    yield line
    
    g_find_content = find_content("employ_list.txt","IT")
    for i in g_find_content:
        print(i.strip())

    3,作业二,

    # 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
    
    def find_content(filename,content):
        with open(filename,encoding='utf-8') as f:
            for line in f:
                if content in line:
                    yield '***'+line  # 只有这个地方不一样
    
    g_find_content = find_content("employ_list.txt","IT")
    for i in g_find_content:
        print(i.strip())

    4,面试题一,

    # 1,输出是什么? 原则就是只可以取一次
    def demo():
        for i in range(4):
            yield i
    
    g=demo()
    
    g1=(i for i in g)
    # def func():
    #     for i in g:
    #         yield i   # 上面的生成器等价于这个
    g2=(i for i in g1)
    # g2=(i for i in (i for i in g))  看到上面那样的,就把他写进来,不然容易绕蒙了
    #print(list(g))  # 如果我运行了这一句,那后面的两个打印就都为空了
    print(list(g1))  # 如果我运行了这一个强转,就代表者g1已经取过一次了,一个生成器只可以取一次的,所以下面的那一句就取不到g1了
    print(list(g2))  # 如果前面两个打印都没有执行,这里才会有[1,2,3,4]打印出来
    
    运行结果:
    [0, 1, 2, 3]
    []

    5,面试题二,但凡遇到表达式套生成器的这种就把他拆开,不拆就是晕

    # 2,输出是什么?
    def add(n,i):
        return n+i
    
    def test():
        for i in range(4):
            yield i
    
    g=test()
    
    for n in [1,10]:
        g=(add(n,i) for i in g)
    print(list(g))
     
    # 前面的生成器套生成器比较浮躁,首先给他拆成下面这样,再来分析   
    # n = 1
    # g=(add(n,i) for i in test())
    #
    # n = 10
    # g=(add(n,i) for i in (add(n,i) for i in test()))
    # 20,21,22,23         10,11,12,13     0,1,2,3
    # 生成器只能去一次,n=1 的时候并没有实际运行,是到了这里才实际运行的,而到了这儿n已经等于10了,不能拿1来算了
    
    
    运行结果:
    [20, 21, 22, 23]

    6,内置函数,就是Python解释器一启动就有的函数,一打开就可以用的函数,截止到3.6.2,一共有68个内置函数,能够直接加括号调用,并且不用提前定义的都是内置函数

    7,作用域相关的两个,globals(),locals()

    # 内置函数,用的不多
    print(locals())  #返回本地作用域中的所有名字
    print(globals())  # 返回全局作用域中的所有名字
    
    # 关键字,用于声明,和for is一样是关键字,用的多
    global  变量 # 声明变量
    nonlocal 变量 #内层函数用外层函数变量,用域函数内部,和变量的实际作用域相关

    8,和迭代器生成器相关的3个range,iter,next,python里面一切都是对象,双下的用起来比较麻烦,

    # 之前讲过迭代器里面有双下函数__next__和__iter__
    # 但是双下函数我们一般不会直接调用
    # 迭代器.__next__  我们不会这样调用
    # 怎么调用呢?
    # next(迭代器) 其实内部还是代用的双下方法
    
    # 注意一点:
    # __next__属于迭代器的方法
    # next()内置函数
    
    def next(迭代器):
        迭代器.__next__()
    
    [].__len__()
    len([])
    
    迭代器 = iter(可迭代的)
    迭代器 = 可迭代的.__iter__
    python里面一切都是对象,可迭代的就是可迭代对象

    9,再说range

    # 可切片,但是不是用冒号
    range(10)
    range(1,11)
    range(1,11,2)
    
    print('__next__' in dir(range(10)))   # False range结果是一个可迭代对象
    print('__next__' in dir(iter(range(10))))# True 被iter函数转化,也就是调用了双下iter方法之后就是迭代器了

    10,其他类型12个,首先看dir()函数,查看一个变量拥有的方法

    # 返回的是一个列表
    print(dir([]))
    print(dir(1))

    11,callable(),查看一个变量是否可以用括号调用,是否是可调用的,函数名,列表名,字典名,其实都是变量,只能查变量,看一下是值还是函数,一般就是检测是否是函数,还有其他可调用的,目前没学

    print(callable(print))  # True
    a = 1
    print(callable(a))  # false
    def func():pass
    print(callable(func)) # True
    
    print(callable(globals)) # True

    12,help() 查看帮助信息,没有返回值,help函数就是直接打印,返回所有方法,和dir 是差不多的,给的更详细一些,当对一个变量或者是数据类型不了解的时候,可以拿来查看一下,封闭开发的时候,看help很给用。

    help(str)  #返回所有有的帮助文档,函数介绍,怎么用等等
    help(func)

    13,import方法,其实也是调用的__import__方法,导入模块,某个方法属于某个数据类型的变量,就用点调用,如果某个方法不依赖于任何数据类型,就直接调用,这就是内置函数和自定义的函数

    import os   # import 是一个关键字,不依赖于任何数据类型
    __import__('os') # 这个双下方法是不依赖于任何的数据类型的,__iter__这个是依赖于可迭代对象的

    14,列表句柄,虽然我们一般不这样说,但是他确实就像是一个操作杆, 拿着他就可以操作列表了

    l = [1,2,3,4]
    l.append(5) # 列表句柄

    15,open 打开文件,之前用的比较多,这里不再多说了

    with open("file.txt",encoding='utf-8') as f:
        print(f.writable()) # 是否可读
        print(f.readable()) # 是否可写
    
    运行结果:
    False
    True

    16,id 函数 查看内存地址,代表一个变量他所在的内存地址,不再写例子,比较简单

    17,hash函数,计算哈希值,可哈希就是不可变数据类型,包括int,bool,float,str和tuple,对于相同可哈希数据类型的哈希值,在一次程序运行中的哈希值是不会变的,但是在下一次运行时的哈希值是会变的,只是在一次程序运行内的值是不会变的,哈希其实也是和内存相关的,可不可哈希其实就是能不能执行这个哈希函数,哈希和ID这两个函数其实用的都不多的。

    import time
    while True:
        time.sleep(1)
        print(hash(1))  # int类型的哈希值还是自己
        print(hash(1.23))
        print(hash(True)) # bool类型的哈希值还是自己
        print(hash('sss'))
        print(hash((1,)))
        print('***************************')
    
    运行结果:
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    1
    530343892119149569
    1
    8413743691931804847
    3430019387558
    ***************************
    print(hash([]))
    
    运行结果:
    Traceback (most recent call last):
      File "/Users/guolixiao/PycharmProjects/lisa's_practise/boys/part one/15.4_内置函数其他.py", line 50, in <module>
        print(hash([]))
    TypeError: unhashable type: 'list'
    print(hash('sss'))
    print(hash('sss'))
    print(hash('sss'))
    
    第一次运行结果:
    -4352255816779243253
    -4352255816779243253
    -4352255816779243253
    
    第二次运行结果:
    2236786100360963608
    2236786100360963608
    2236786100360963608
    
    第三次运行结果:
    8099329436765032024
    8099329436765032024
    8099329436765032024

    18,相对于字典的查找,非常的快速,只要一次查找就可以的,为何呢,因为字典的value直接存储在key所对应的哈希值代表的内存中,也就是哈希值就是他的内存地址,直接到这个内存地址去取值就可以。这也是key必须可哈希的原因了,我们一般都是循环key来找value,因为,value都比较大,比方说视频,循环起来很可怕的,包括后面的数据库也有很多快速的取值的方法,有些通过哈希,有些不通过哈希,这个会到后面再来讲

    19,print函数,end sep 都比较熟悉了,另外有一个file=None

    f = open("file.txt", 'r+',encoding='utf-8')
    print(hash('sss'),file=None)  # None得话代表输入到下面的屏幕
    print(hash('sss'),file=f) #代表输入到文件,这一句打印到了file.txt中
    f.close()

    20,一个简单的打印进度条的函数,其实Python有提供一个专门的打印进度条的模块,叫做progress bar,需要单独下载安装,有兴趣可以去研究一下。

    # 自己的版本
    import time
    for i in range(0,101,2):
        time.sleep(0.1)   # 不sleep的话,打印的太快看不到进度,直接就100了
        print('
    %s%%   ' % i,end='') #
    是回到行首不换行的意思
        print('*'*i,end='')
    print()  # 为了下一次输入时在新的一行,所以这儿多加了一行打印
    
    # 老师的版本
    import time
    for i in range(0,101,2):
         time.sleep(0.1)
         char_num = i//2
         per_str = '
    %s%% : %s
    ' % (i, '*' * char_num) 
             if i == 100 else '
    %s%% : %s' % (i,'*'*char_num)
         print(per_str,end='', flush=True) # flush立刻把文件输出到文件流,不做缓存
    运行结果:
    100%   ****************************************************************************************************

    21,input函数,返回都是字符串,交互用的,不再展开写

    22,exec,eval和compile,字符串类型代码的执行,先说exec吧:

    'print(123)' #这就是一个字符串,里面的代码不会去执行
    # 但是如果这样的话
    exec('print(123)') # 就可以正常输出123
    eval('print(123)') # 也可以输出123
    
    # 乍一看,貌似一样
    运行结果:
    123
    123
    
    其实呢?
    print(exec('1+2+3+4'))
    print(eval('1+2+3+4'))
    
    运行结果:
    None
    10

    23,结论:exec和eval都可以执行字符串类型的代码,但是eval有返回值,exec没有,eval只能用在你明确知道你要执行的代码是什么的并且用eval代码确实会变简单,但是不能因为简单就忽略了安全,exec是简单的流程控制,eval有结果的简单计算

    另外非常重要的是eval一般情况下不要用,但是eval也有用它会非常好的地方,为什么一般不让用呢,比方说文件里面写的,和用户输入的字符串。文件里面的代码很不安全的,比方说一个黑客攻击了你的电脑,改了这个文件,那么整个程序就都崩塌了。容易攻陷账号密码,公司里的代码不不能随便用eval去读的,用户输入更不安全了,因为不是所有的用户都是良性用户的,一定有一写用户在攻击你网站,想办法获取你的数据,那如果这个地方留了口子,这种不安全的代码,肯定会出问题的,所以不要执行用户输入的代码,或者从文件里面读,只能去执行写死了的,因为这样会简单很多

    code = '''
    for i in range(5):  
        print(i*'*')   
    '''
    exec(code)
    # eval(code)   # 不可以用eval,只可以用exec来运行
    
    运行结果:
    *
    **
    ***
    ****

    24,compile函数,当只是简单的表达式的时候,用eval,当为流程语句的时候用exec,当需要交互的时候,需要用到single,compile用的不多,将字符串代码进行编译,然后通过exec或者eval来执行,代码对象能够通过exec来执行或者eval来求值,好,问题是exec和eval自己就可以执行字符串,为何还需要提前编译呢?答案是,计算机其实不认识我们自己写的这些代码的,他要先经过一次翻译,把你写的这些代码翻译成字节码,再去执行,但是如果对于同一段code,比如说500行,我要运行5次,如果编译五次的话,很浪费时间的,如果有个方法可以编译一次,多次执行,那就好了,这个方法就是compile,他就是把我们自己写的代码,翻译成字节码保存。他只管翻译,具体执行还得exec和eval

    # 注意即使是字符串中的代码,也要注意缩进
    code = '''
    for i in range(5):  
        print(i*'*')   
    '''
    
    compile1 = compile(code,'','exec')
    # 这个空串代表不是从文件里面读,如果从文件里面写一个文件名,但是出于安全我们不从文件读
    # 'exec'必须传递字符串,
    # 编译成exec模式的方式
    print(type(compile1))
    print(compile1)
    exec(compile1)
    code = '1+2+3+4'
    compile1 = compile(code,'','eval')
    # 编译成eval模式的方式
    print(type(compile1))
    print(compile1)
    eval(compile1)

    25,single 方式,交互式的字符串,了解一下有这么一种神奇的功能就行了,用的不多

    code = 'name = input(">>>")'
    compile1 = compile(code,'','single')
    # 编译成eval模式的方式
    
    print(name)
    #pycharm 有时候会骗你的,这个地方pycharm感知不到字符串里面的name,会报错的,但实际上程序是没有问题的,会正常执行
    
    运行结果:
    >>>lisa
    lisa

    26,至此其他学完了,下面学习,基础数据类型的数字相关的14个,complex知道有这个数据类型就行了,不要深究

    27,数据类型,int,float,bool,浮点数float,这在数据类型强制转换的时候使用

    # 由于这个才叫浮点数的
    # 341.23 =3.4123 * 10**2
    # 341.23 = 34.123 *10
    # 当浮点数位数足够长的时候,计算机转化成二进制的时候会出现微若的偏差,也就是最后面几位的数字可能不准确
    # 就是没有办法完全转换准确,所有语言都一样,可以解决,但是我们一般不会用到这么长的小数的
    i = 1.2345674677677443230987
    print(i)

    28,进制转换,bin,oct,hex

    # 稍微了解下就行,用的也不多
    print(oct(10))  # 转换成八进制,0o
    print(hex(10))  # 转化成十六进制,0x
    print(bin(10))  # 转化成二进制,0b
    
    运行结果:
    0o12
    0xa
    0b1010

    29,数学运算

    print(abs(-3))  # 结果3
    print(divmod(8,3)) # 除余 (2, 2)
    print(divmod(9,2)) # 除余 (4, 1)  在做分页的时候这个方法是真有用
    print(round(3.1415926,3)) # 3.241 小数的精确,会四舍五入的
    print(pow(3,3))# 27 求幂运算的
    print(pow(2,3,3)) # 2 求幂运算,针对第三个数取余数,用的不多,幂运算和取余在一起
    print(pow(3,2,4)) # 1

    30,sum函数,这儿有问题,因为command+B进去以后,看到的是参数是*args,但是实际上是只可以接收两个参数的,老师说以前看到的参数是iterable,不晓得

    # sum 求和,接收两个参数,接收一个可迭代对象
    ret = sum([1,2,3,4,5])
    print(ret)
    # ret = sum(1,2,3,4,5)  # 
    # start参数,不允许按照关键字传参,只能按照位置传
    # 正产从零开始加,这个是从10开始加
    ret = sum([1,2,3,4,5],10)
    print(ret)
    
    运算结果:
    15
    25

    31,min,max 函数

    # min 比sum 好的地方因为它既可以接收iterable也可以接收*args
    # 我可以给一个key值,也就是一个方法名,先按照方法名来运算,再比较结果
    print(min([1,2,3,4]))
    print(min(1,2,-3,4,key=abs))
    print(min({1,2,3,-4}, key=abs))
    
    print(max([1,2,3,4]))
    print(max(1,2,-3,4,key=abs))
    print(max({1,2,3,-4}, key=abs))  #最终给出的还是列表中的数

    运算结果:
    1
    1
    1
    4
    4
    -4

    32,试题一

    print(3>2==2)
    print(3>2 and 2==2)
    # 这两句效果是一样的

    33,

    # 大写A的ASCII码是65
    # 小写a的ASCII码是97

    34,字符串比较以首字母为准,元祖不能比较大小

    35,5/2 python3结果2.5 python2 向下取整为2

    36,只要是for循环就不会无限循环

    37,删除一个列表里面重复的元素,转换为set是不完美的,因为变成无序了。所以我们可以建一个新的list来储存不重复的,保持原来顺序。

  • 相关阅读:
    (BFS 二叉树) leetcode 515. Find Largest Value in Each Tree Row
    (二叉树 BFS) leetcode513. Find Bottom Left Tree Value
    (二叉树 BFS DFS) leetcode 104. Maximum Depth of Binary Tree
    (二叉树 BFS DFS) leetcode 111. Minimum Depth of Binary Tree
    (BFS) leetcode 690. Employee Importance
    (BFS/DFS) leetcode 200. Number of Islands
    (最长回文子串 线性DP) 51nod 1088 最长回文子串
    (链表 importance) leetcode 2. Add Two Numbers
    (链表 set) leetcode 817. Linked List Components
    (链表 双指针) leetcode 142. Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10092884.html
Copyright © 2011-2022 走看看