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来储存不重复的,保持原来顺序。

  • 相关阅读:
    Docker 安装各种环境
    N级树形菜单封装
    一个周期算出所有高电平的个数
    DDR3新版(3):DDR3自动读写控制器
    DDR3_新版(2):IP核再封装
    数电(6):时序逻辑电路
    Vue表单那些事
    liunx环境修改minio默认端口和后台启动
    liunx 后台启动mongodb服务
    liunx安装和部署nacos配置中心
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10092884.html
Copyright © 2011-2022 走看看