zoukankan      html  css  js  c++  java
  • python 集合、函数和文件操作

    1.set集合

    set集合是一个无序、不可重复、可嵌套的序列,基本功能是进行成员关系测试和删除重复元素,可以使用大括号({})或者 set()函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典

    1.1 常用功能函数

    • 增加元素

      使用set.add()函数单个添加元素;使用set.update()函数来批量添加元素,参数为可迭代的对象,如列表,元组,字符串

      >>> test = {1,2,3,4,}      #创建一个集合
      >>> test.add("5")                #添加集合元素5
      >>> test.add("6")       
      >>> test
      {1, 2, 3, 4, '6', '5'}
      >>> test.add("5")      #重新添加集合元素5.发现,之前已有,印证了不重复性
      >>> test
      {1, 2, 3, 4, '6', '5'}
      >>> li = [7,8,9,0]      
      >>> test.update(li)   #将li列表的元素批量添加到集合中
      >>> test
      {0, 1, 2, 3, 4, 7, 8, 9, '6', '5'}
      >>> test.update("fuzj")   #将fuzj字符串每个字符作为元素添加到集合中
      >>> test
      {0, 1, 2, 3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
      View Code
    • 删除元素

    删除可以使用set.discard() 移除元素,不存在不报错 set.remove() 移除元素,不存在则报错 set.pop() 删除最后的元素,并打印,不能加参数

    >>> test
    {0, 1, 2, 3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
    >>> test.discard(0)   #使用dicard删除0元素
    >>> test
    {1, 2, 3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
    >>> test.discard(100)  #使用discard删除不存在的元素,不报错
    >>> test
    {1, 2, 3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
    >>> test.remove(1)   #使用remove删除1元素
    >>> test
    {2, 3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
    >>> test.remove(100)  #使用remove删除不存在的元素,报错
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 100
    >>> test.pop()  #使用pop随机删除元素
    2
    >>> test
    {3, 4, 7, 8, 9, 'f', 'z', 'j', '6', 'u', '5'}
    >>> test.pop()
    3
    View Code
    • 交集

    交集为两个集合相同的元素,使用intersection函数或者&符号,将交集重新组合为一个集合

    >>> test = {1,2,3,4,5,}
    >>> test2 = {2,3,5,6,7,8,}
    >>> test.intersection(test2)    #取test和test2的交集
    {2, 3, 5}
    >>> test3 = test.intersection(test2)
    >>> test3
    {2, 3, 5}
    >>> test & test2   #使用&符号来取交集
    {2, 3, 5}
    >>> test.intersection_update(test2)   #加update将会把test更新,只留下交集部分
    >>> test
    {2, 3, 5}
    View Code
    • 并集

    并集为两个集合合并,去重后的结果,可以用union函数或|符号,将并集重新组合为一个集合

    >>> test
    {1, 2, 3, 4, 5}
    >>> test2
    {2, 3, 5, 6, 7, 8}
    >>> test.union(test2)
    {1, 2, 3, 4, 5, 6, 7, 8}
    >>> test | test2
    {1, 2, 3, 4, 5, 6, 7, 8}
    View Code
    • 差集

    差集为两个集合不相同的元素,或者B对于A中不存在的元素,或者A对于B中不存在的元素,取差集要确定好对比的前后顺序,使用difference函数和symmetrice_difference函数,也可以使用-和符号

    >>> test
    {1, 2, 3, 4, 5}
    >>> test2
    {2, 3, 5, 6, 7, 8}
    >>> test.difference(test2)   #取A集合中,B集合不存在的元素
    {1, 4}
    >>> test - test2     #使用-号 取A集合中,B集合不存在的元素
    {1, 4}
    >>> test2.difference(test)  #取B集合中,A集合不存在的元素
    {8, 6, 7}
    >>> test2 - test    #使用-号 取B集合中,A集合不存在的元素
    {8, 6, 7}
    >>> test.symmetric_difference(test2)  #取A、B集合中互相不存在元素
    {1, 4, 6, 7, 8}
    >>> test ^ test2   #使用^号 取A、B集合中互相不存在元素
    {1, 4, 6, 7, 8}
    
    
    同样支持update将结果更新至原集合中,
    test.symmetric_difference_update(test2)
    >>> test
    {1, 4, 6, 7, 8}
    View Code
    • 其他函数

      • set.copy() 拷贝个集合,为浅copy
      • set.clear() 清空集合

    1.2 练习示例

    取old_cmdb和new_cmdb的差集,交集等,常用在cmdb更新中

    ```
    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    #pyversion:python3.5
    #owner:fuzj
    
    
    old_cmdb = {
        "#1":8,
        "#2":4,
        "#4":2,
    }
    
    
    new_cmdb = {
        "#1": 4,
        "#2": 4,
        "#3": 2,
    }
    print("old_cmdb:" , old_cmdb)
    print("new_cmdb:" , new_cmdb)
    
    
    s1 = set(old_cmdb.keys())
    s2 = set(new_cmdb.keys())
    
    #old_cmdb 要删除的
    s_del = s1.difference(s2)
    print("old_cmdb 要删除的: ",s_del)
    
    #old_cmdb 要更新的
    s_upd1 = s1.intersection(s2)
    s_upd2 = set()
    for i in s_upd1:
        if old_cmdb[i] != new_cmdb[i]:
            s_upd2.add(i)
    print("old_cmdb 要更新的:",s_upd2)
    
    
    #old_cmdb 要添加的
    s_add = s2.difference(s1)
    
    print("old_cmdb 要添加的",s_add)
    ```
    View Code

    运行结果:

    ```
    old_cmdb: {'#4': 2, '#2': 4, '#1': 8}
    new_cmdb: {'#3': 2, '#2': 4, '#1': 4}
    old_cmdb 要删除的:  {'#4'}
    old_cmdb 要更新的: {'#1'}
    old_cmdb 要添加的 {'#3'}
    
    ```
    View Code

    2.函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率,分自定义函数和内置函数

    2.1 函数的创建

    • 格式

    def 函数名(参数):
    代码块
    return 返回值

    • 要素

      • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
      • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
      • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
      • 函数内容以冒号起始,并且缩进。
      • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。函数中如果执行了return,此函数将终止执行return后面的语句
    • 示例

      ```
      >>> def hello(arg) :
              print(arg)
      
      >>> hello("Hello World!")
      Hello World!
      >>>
      ```
      View Code

      2.2 函数的参数

    • 形式参数,实际参数

      形式参数为函数名后边括号里定义的内容,实际参数是函数被调用时传入的参数
      如上面例子,arg 为hello函数的形式参数,而下面hellow()被调用时Hello World!为实际参数

    • 默认参数

      调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:

      ```
      
      #!/usr/bin/python3
      
      #printinfo函数说明
      def printinfo( name, age = 35 ):
         "打印任何传入的字符串"
         print ("名字: ", name);
         print ("年龄: ", age);
         return;
      
      #调用printinfo函数
      printinfo( age=50, name="runoob" );
      print ("------------------------")
      printinfo( name="runoob" );
      
      以上实例输出结果:
      名字:  runoob
      年龄:  50
      ------------------------
      名字:  runoob
      年龄:  35
      ```
      View Code
    • 指定参数

    关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值,如上默认参数中,name参数和age参数即为指定参数

    • 动态参数

      *arg 默认传入的参数放到元组中, 动态参数使用中,如果实际参数前加*号,会将参数的元素传入到参数中
      **kwargs默认传入的参数放入到字典中.如果实际参数前加*号,会将字典的k/v 传入到参数中
      万能参数: 即 *args,**kwargs

      ```
          #!/usr/bin/env python
          # -*- coding: UTF-8 -*-
          #pyversion:python3.5
          #owner:fuzj
      
          def send1(*args):
              print(args,type(args))
      
          def send2(**args):
              print(args,type(args))
      
          def send3(*args,**kwargs):
              print(args,type(args))
              print(kwargs,type(kwargs))
      
          li = [1,2,3,4,]
          send1(1,2,3,4)
          send1(li)
          send1(*li)    #参数前加*号会把该参数进行for循环里面的值,然后传入函数
      
          di = {"a":1,"b":2}
          send2(k=di)
          send2(**di)
      
          send3(1,2,3,4,"a"=1,"b"=2)
      
          ```
      View Code

    执行结果

    ```
    #函数send1
    (1, 2, 3, 4) <class 'tuple'>   #传递不定长参数的结果
    ([1, 2, 3, 4],) <class 'tuple'>    #传入一个列表参数的结果
    (1, 2, 3, 4) <class 'tuple'>   #传入一个带*的列表参数结果
    
    #函数send2
    {'k': {'b': 2, 'a': 1}} <class 'dict'>   #传入一个字典结果
    {'b': 2, 'a': 1} <class 'dict'>   #传入一个带**的字典结果
    
    # 函数send3
    (1, 2, 3, 4) <class 'tuple'>
    {'b': 2, 'a': 1} <class 'dict'>
    ```
    View Code

    2.3 变量作用域

    Pyhton 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
    变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称,根据作用域的不同,可分为:

    • 全局变量: 所有的作用域都可读,但是作用域内不能重新赋值全局变量,但是可以使用global来重新定义全局变量.如果变量的值是列表元组字典 在作用域内可以进行修改,不可重新赋值

    • 局部变量: 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问

    定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
    局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:

    ```
    #!/usr/bin/env python
    
    total = 0; # 这是一个全局变量
    
    # 可写函数说明
    def sum( arg1, arg2 ):
        #返回2个参数的和."
        total = arg1 + arg2; # total在这里是局部变量.
        print ("函数内是局部变量 : ", total)
        return total;
    
    #调用sum函数
    sum( 10, 20 );
    print ("函数外是全局变量 : ", total)
    以上实例输出结果:
    函数内是局部变量 :  30
    函数外是全局变量 :  0
    
    ```
    View Code

    2.4 匿名函数

    python 使用 lambda 来创建匿名函数。
    所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
    lambda 只是一个表达式,函数体比 def 简单很多。
    lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
    lambda 函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
    虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
    语法
    lambda 函数的语法只包含一个语句,如下:
    lambda [arg1 [,arg2,.....argn]]:expression
    如下实例:

    ```
    #!/usr/bin/python3
    
    # 可写函数说明
    sum = lambda arg1, arg2: arg1 + arg2;
    
    # 调用sum函数
    print ("相加后的值为 : ", sum( 10, 20 ))
    print ("相加后的值为 : ", sum( 20, 20 ))
    以上实例输出结果:
    相加后的值为 :  30
    相加后的值为 :  40
    
    ```
    View Code

    3.文件操作

    3.1 open函数

    python的内置函数open()可以打开文件,创建一个file对象,格式如下:

    file object = open(file_name [, access_mode][, buffering][,encoding=utf-8])
    

    各个参数的细节如下:

    • file_name:file_name变量是一个包含了你要访问的文件名称的字符串值。
    • access_mode:access_mode决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
    • buffering:如果buffering的值被设为0,就不会有寄存。如果buffering的值取1,访问文件时会寄存行。如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认
    • encoding = utf-8 表示使用utf-8字符集打开

    3.2 文件打开模式

    模式描述
    r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
    rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
    r+ 打开一个文件用于读写。文件指针将会放在文件的开头
    rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
    w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
    ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    PS:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,否则使用读到的是字符串,写入时也按字符串

    3.3 file对象的属性

    • 文件被打开之后,此文件对象的属性有如下几个:
    属性描述
    file.closed 返回true如果文件已被关闭,否则返回false。
    file.mode 返回被打开文件的访问模式。
    file.name 返回文件的名称。
    file.softspace 如果用print输出后,必须跟一个空格符,则返回false。否则返回true
    file.encoding 返回打开文件时使用的字符集
    • 示例

      ```
      >>> fp = open("test",'r')
      >>> fp.name    #显示打开的文件名
      'test'
      >>> fp.closed     #判断文件是否被关闭
      False
      >>> fp.mode    #输出文件打开的模式
      'r'
      >>> fp.softspace    #python3不支持此属性
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: '_io.TextIOWrapper' object has no attribute 'softspace'
      ```
      View Code

    3.4 file对象的常用操作函数

    • seek() 调整当前的指针位置,以字节为单位进行调整.从指针位置开始后面会依次覆盖
    • tell() 获取当前指针位置
    • read() 默认读取一个打开的文件中所有字符串。需要重点注意的是,Python字符串可以是二进制数据,而不是仅仅是文字
    • write() 写数据
    • close() 关闭打开的文件
    • fileno 获取文件描述符
    • flush() 强制将缓冲区内容写到硬盘
    • readable() 是否可读
    • writeable() 是否可写
    • readline() 仅读取一行
    • truncate() 截断指针位置.后面内容清空
    • readlines() 读取文件内容,将每行作为列表的元素,最终组合成一个列表

    PS:使用输入方法read() 或者 readlines() 从文件中读取行时,python并不会删除行结尾符
    tell()方法告诉你文件内的当前位置;换句话说,下一次的读写会发生在文件开头这么多字节之后。
    seek(offset [,whence])方法改变当前文件的位置。Offset变量表示要移动的字节数。whence变量指定开始移动字节的参考位置。
    如果whence被设为0,这意味着将文件的开头作为移动字节的参考位置。如果设为1,则使用当前的位置作为参考位置。如果它被设为2,那么该文件的末尾将作为参考位置。注意:python3中已经不允许非二进制打开的文件,相对于文件末尾和当前位置的定位,指针只能从文件开头开始。python2没有限制

    示例:
    test 文件内容:
    fuzengjie付增杰
    付增杰abcdefghjkl
    脚本:初衷是在test文件的第21个字符后面,指针偏移4位,插入123

     ```
        #!/usr/bin/env python
        # -*- coding: UTF-8 -*-
        #pyversion:python3.5
        #owner:fuzj
        fp = open("test","r+")   #使用r+方式打开test
        rs = fp.read(21)   #读test第21个字符以内的所有字符,包括第21个以及中间换行。如果是字符
        print("文件内容: ",rs)   #打印读取的内容
    
        ad = fp.tell()    #打印当前的指针位置
        print("当前指针位置: ",ad)
        se = fp.seek(4,1)    
        fp.write("123")   #写入123
        fp.close()
    
        ```
    View Code

    使用py3运行后会报错
    io.UnsupportedOperation: can't do nonzero cur-relative seeks。
    如果将fp.seek(4,1)改为fp.seek(4,0)从文件开头插入,则没问题。
    如果使用py2执行,则不会出现上述问题。
    可以先获取当前文件末尾的指针位置,然后再进行移动,
    fp.seek(fp.tell(),0),这样就可以将指针定位到末尾
    现在换一种方法,使用二进制打开文件,然后进行插入
    代码:

    ```
        #!/usr/bin/env python
        # -*- coding: UTF-8 -*-
        #pyversion:python3.5
        #owner:fuzj
        fp = open("test","rb+")   #使用二进制方式打开
        rs = fp.read()
        print("文件内容: ",str(rs,encoding='utf-8'))   #由于对象是二进制,所以需要使用str()来转换成字符串
    
        ad = fp.tell()
        print("当前指针位置: ",ad)
        se = fp.seek(-4,1)  #在当前位置向左移动四个指针
        print("改变后的指针位置:", fp.tell())
        fp.write(bytes("123",encoding='utf-8'))
    ```
    View Code

    运行结果:
    ```
    文件内容:  fuzengjie付增杰
    付增杰abcdefg123l
    当前指针位置:  39
    改变后的指针位置: 35
    
    test文件
    fuzengjie付增杰
    付增杰abcdefg123l   #指针移动四位到h字符串,然后使用123开始往后替换,最后l字符串没得替换,保留了。
    
    ```
    View Code

    注意:一个汉字如果使用utf-8编码集的话,会占3个字节,如果使用gbk编码集的话,会占用2个字节。

    • 文件打开的另一种方法:

    使用with 打开文件,操作完之后,自动关闭

    with open("test",'r') as f:    #打开一个文件
        pass
    
    
    #同时打开两个文件
    with open("test1",'r') as f1, open("test2",'r') as f2:
        pass
    View Code
  • 相关阅读:
    手把手教你如何逐步安装OpenStack
    掌握OpenStack部署的最佳实践 打破部署失败的魔咒
    大数据服务大比拼:AWS VS. AzureVS.谷歌
    fullcalender
    也谈---基于 HTTP 长连接的“服务(转载)
    调用页面脚本
    mssql 低版本数据库 使用高版本的命令
    行变列 pivot
    HighCharts -在包含容器尺寸发生变化时重新渲染
    ES6 import export
  • 原文地址:https://www.cnblogs.com/pycode/p/day03.html
Copyright © 2011-2022 走看看