函数&模块(2)

函数&模块

1.函数

1.函数入门
1.1初识函数
  • 函数,可以当做一大堆功能代码的集合

    '''
    函数格式
    def 函数名():
        函数内执行的业务代码
    
    函数名()
    '''
    
    
    def info():
        print("输出第一行数据")
        print("输出第二行数据")
        print("输出第三行数据")
    
    
    info()
    
    输出第一行数据
    输出第二行数据
    输出第三行数据
    
  • 函数在项目开发中用到的两种应用场景

    • 有重复代码,用函数增加代码的重用性

      # 重复代码
      def send_message():
          # 执行业务
          pass
      
      cpuview = 0.0
      memoryview = 0.0
      diskview = 00.0
      print("欢迎使用计算机监控系统".center(20, "*"))
      if cpuview > 90 / 100:
          send_message()
      if memoryview > 98 / 100:
          send_message()
      if diskview > 99 / 100:
          send_message()
      
    • 代码太长,用函数增强代码的可读性

      # 代码太长
      def calculate_same_num_rule():
          pass
      
      
      def calculate_same_color_rule():
          pass
      
      
      def calculate_straight_rule():
          pass
      
      
      def calculate_double_card_rule():
          pass
      
      
      def calculate_single_card_rule():
          pass
      
1.2函数的参数
1.参数
  • 在定义函数时,如果括号中添加变量,称为它函数的形式参数

    # 定义函数
    def func(a1, a2, a3):
        print(a1+a2+a3)  # 4
    
    
    # 执行函数并传入参数
    func(1, 2,1)
    
  • 位置传参

    '''
    执行函数时,传入参数一一对应函数的形参
    '''
    # 位置传参
    def add(a1, a2):
        print(a1 + a2)  # 3
    
    
    # 执行函数
    add(1, 2)
    
  • 关键字传参

    # 关键字传参
    def adds(n1, n2):
        print(n1 + n2)  # 5
    
    
    adds(n1=1, n2=4)
    
2.默认参数
# 默认参数
def add_default(a1, a2, a3=15):
    print(a1 + a2 + a3)


# 位置传参-有默认参数的函数,可以忽略默认参数,不传实参
add_default(1, 2)  # 18
add_default(1, 2, 3)  # 6

# 关键字传参- 位置和关键字混合搭配时,关键字传参要放在后面
add_default(1, 2, a3=12)  # 15


3.动态参数
"""
注意点:
    - **必须放在*后面
    - 参数和动态参数混合使用时,动态参数只能放在后面
    - 默认值参数和动态参数同时存在,默认值参数放在动态参数前
"""


def add_other_Args(a1, a2, a3=15, *args, num=10, **kwargs):
    print(a1, a2, a3, num, args, kwargs)

# 默认值参数 num,在实际应用中,并不能修改其值,默认值参数放在动态参数前面
add_other_Args(12, 56, 89, 12, 45, 56, 78, name="Terry", email="hjf***@gmail.com")
1.3函数返回值
  • 开发过程中,函数可以解决一些实际业务,某些业务的功能实现之后需要反馈结果,因此函数有了返回值的概念

    def xml_to_list(city):
        data_list = []
        url = "http://ws.webxml.com.cn//WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName={}".format(city)
        res = requests.get(url=url)
        '''
            <?xml version="1.0" encoding="utf-8"?>
            <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://WebXml.com.cn/">
              <string>直辖市</string>
              <string>北京</string>
              <string>54511</string>
              <string>54511.jpg</string>
              <string>2024/3/8 9:44:19</string>
              <string>-2℃/11℃</string>
              <string>3月8日 晴</string>
              <string>西南风小于3级</string>
              <string>0.gif</string>
              <string>0.gif</string>
              <string>今日天气实况:气温:5.5℃;风向/风力:南风 2级;湿度:24%;紫外线强度:强。</string>
              <string>感冒指数:极易发,天气寒冷,昼夜温差极大。
                运动指数:较不宜,天气寒冷,推荐您进行室内运动。
                过敏指数:较易发,外出需远离过敏源,适当采取防护措施。
                穿衣指数:寒冷,建议着厚羽绒服等隆冬服装。
                洗车指数:适宜,天气较好,适合擦洗汽车。
                紫外线指数:强,涂擦SPF大于15、PA+防晒护肤品。
              </string>
              <string>-2℃/13℃</string>
              <string>3月9日 晴</string>
              <string>西风转北风小于3级</string>
              <string>0.gif</string>
              <string>0.gif</string>
              <string>0℃/13℃</string>
              <string>3月10日 晴转多云</string>
              <string>西北风转北风小于3级</string>
              <string>0.gif</string>
              <string>1.gif</string>
              <string>北京位于华北平原西北边缘,市中心位于北纬39度,东经116度,四周被河北省围着,东南和天津市相接。全市面积一万六千多平方公里,辖12区6县,人口1100余万。北京为暖温带半湿润大陆性季风气候,夏季炎热多雨,冬季寒冷干燥,春、秋短促,年平均气温10-12摄氏度。北京是世界历史文化名城和古都之一。早在七十万年前,北京周口店地区就出现了原始人群部落“北京人”。而北京建城也已有两千多年的历史,最初见于记载的名字为“蓟”。公元前1045年北京成为蓟、燕等诸侯国的都城;公元前221年秦始皇统一中国以来,北京一直是中国北方重镇和地方中心;自公元938年以来,北京又先后成为辽陪都、金上都、元大都、明清国都。1949年10月1日正式定为中华人民共和国首都。北京具有丰富的旅游资源,对外开放的旅游景点达200多处,有世界上最大的皇宫紫禁城、祭天神庙天坛、皇家花园北海、皇家园林颐和园,还有八达岭、慕田峪、司马台长城以及世界上最大的四合院恭王府等各胜古迹。全市共有文物古迹7309项,其中国家文物保护单位42个,市级文物保护单位222个。北京的市树为国槐和侧柏,市花为月季和菊花。另外,北京出产的象牙雕刻、玉器雕刻、景泰蓝、地毯等传统手工艺品驰誉世界。
              </string>
            </ArrayOfString>
        '''
        print(res.text)
        root = ET.XML(res.text)
        for node in root:
            data_list.append(node.text)
        return data_list
    
    
    result = xml_to_list("北京")
    print(result)
    
  • 返回值可以是任意类型,如果函数中没写return,则默认返回None

    # 返回值可以是任意类型
    def func():
        return [1, True, (11, 22, 33,)]
    
    
    result = func()
    print(result)  # [1, True, (11, 22, 33)]
    
    # 未写返回值 或 return 或 return None,执行函数获取的返回值都是None
    def func2():
        value = 1 +1
    
    
    ret = func2()
    print(ret)  # None
    

  • return后面的值如果有逗号,则默认会将返回值转换元组再返回

    # 后面的值有逗号,默认返回值转成元组返回
    def func3():
        return 1, 2, 3
    
    
    value = func3()
    print(value)  # (1, 2, 3)
    
  • 函数一旦遇到return就会立即退出函数(终止函数中的所有代码)

    # 遇到return就立即推出函数
    def func4():
        print(1)
        return "结束吧"
        print(2)
    
    
    ret = func4()  # 1
    print(ret)  # 结束吧
    
2.函数进阶
1.1参数的补充
'''
Python参数的特性有两个好处:
    1.节省内存
    2.对于可变类型且函数中修改元素的内容,所有的地方都会修改。可变类型: 列表、字典、集合
'''
name = "Tom"
print(id(name))  # 2957232352080
func5(name)  # Tom 2957232352080


# 可变类型 & 修改内部元素
def func6(data):
    data.append(666)


list_num = [11, 22, 33]
# id()查看列表的地址
print(id(list_num))  # 1207590744832
func6(list_num)
print(id(list_num))  # 1207590744832
print(list_num)  # [11, 22, 33, 666]


# 可变类型 & 重新赋值
def func7(data):
    data = ["Python", "JAVA"]


list_v1 = [11, 22, 33]
# id()获取地址,地址一样
print(id(list_v1))  # 2448412623744
func7(list_v1)
print(id(list_v1))  # 2448412623744
print(list_v1)  # [11, 22, 33]
1.函数的返回值是内存地址
def func8():
    data = [11, 22, 33]
    print(id(data))
    return data


num_list_1 = func8()  # 2345095810048
print(num_list_1, id(num_list_1))  # [11, 22, 33] 2345095810048

num_list_3 = func8()  # 2345095381376
print(num_list_3, id(num_list_3))  # [11, 22, 33] 2345095381376
2.参数的默认值
def func9(a1, a2=18):
    print(id(a1), id(a2))
    print(a1, a2)


# 执行函数未传值时,a2指向函数维护的内存地址
func9("root")  # 140734791238752 140734792256472   root 18
# 执行函数传值时,a2指向新传入的值,内存地址指向新地址
func9("root", 20)  # 140734791238752 140734792256536 root 20
  • 注意事项

    • 默认参数的值时可变类型列表字典集合,函数内部修改这个默认值,地址发生改变

      a2 = [11, 22]
      print(id(a2))  # 2692011379456
      
      
      def func10(a1, a2):
          a2.append(a1)
          print(id(a2))  # 2692010932096
          return a2
      
      str_list = func10("Ailke", ["Python", "JAVA"])
      print(id(str_list))  # 2692010932096
      print(str_list)  # ['Python', 'JAVA', 'Ailke']
      
3.动态参数
  • 动态参数,定义函数时在形参位置用 * 或 ** 可以接受任意个参数

    def func11(*args, **kwargs):
        print(args, kwargs)
    
    
    func11("Python", "JAVA", name="Ailke", age=18)  # ('Python', 'JAVA') {'name': 'Ailke', 'age': 18}
    
  • 在定义函数时可以用 * 和 **,其实在执行函数时,也可以用

    • 形参固定,实参用* 和 **

      def func12(a1, a2):
          print(a1, a2)
      
      
      func12(11,12)  # 11 12
      func12(a1=12, a2=15)  # 12 15
      func12(*[11, 33])  # 11 33
      func12(**{"a1": 12, "a2": 18})  # 12 18
      
    • 形参用* 和 *,实参也用 * 和 *

      def func13(*args, **kwargs):
          print(args, kwargs)
      
      
      func13(*[11, 22, 33], **{"name": "Ailke", "addr": "成都市"})  # (11, 22, 33) {'name': 'Ailke', 'addr': '成都市'}
      
      # 字符串格式化format
      str = "我在{},简单地{}".format("成都市", "活着")
      str = "我在{addr},简单地{status}".format(addr="成都市", status="活着")
      
      str = "我在{},简单地{}".format(*["成都市", "活着"])
      str = "我在{addr},简单地{status}".format(**{"addr":"成都市", "status":"活着")
      
1.2函数和函数名
  • 函数名其实就是一个变量,这个变量只不过代指的函数而已

  • 函数必须先定义才能被调用执行

    def add(num1, num2):
        return num1 + num2
    result = add(*[22, 44])
    print(result)  # 66
    
1.函数做元素
  • 函数同时也可被哈希,所以函数名通常也可以做 集合的元素字典的键

    def send_message(phone, content):
        pass
    
    
    def send_image(img_path, content):
        pass
    
    
    def send_emoji(emoji):
        pass
    
    
    def send_file(path):
        pass
    
    
    function_dict = {
        "a": [send_message, ['132***56985', '您好!']],
        "b": [send_image, ['**/**/**.jpeg', '消息内容']],
        "c": [send_emoji, ["😁"]],
        "d": [send_file, ['**.Zz']]
        
    }
    
    print("a.发消息 b.发图片 c.发表情 d.发送文件".center(30, "*"))
    choice = input("请选择: ")
    
    item = function_dict.get(choice)
    if not item:
        print("输入错误")
    else:
        func = item[0]
        param_list = item[1]
        func(*param_list)
    
2函数名赋值
  • 函数名赋值给其他变量,函数名其实就个变量,代指某函数;如果将函数名赋值给另一个变量,则此变量也会代指该函数

    def func(a1, a2):
        print(a1, a2)
      
    
    newFunc = func
    func(1, 2)
    newFunc(2, 3)
    
  • 对函数名重新赋值,如果将函数名修改为其他值,函数名便不再代指函数

    def func(a1, a2):
        print(a1, a2)
        
    #执行func函数    
    func(11, 12)
    
    # func重新赋值成一个字符串
    func = "ailke"
    print(func)  # ailke
    
  • 注意点: 由于函数名被重新定义之后,就会变成被定义的值,在实际的项目开发中,自定义函数时,不要与python内置的函数同名,否则会覆盖内置函数

    id(), bin(), hex(), oct(), len(), ...
    
    # len()内置函数用于计算长度
    strNum = len("Python")
    print(strNum)  # 5
    
    
    # 下面的错误示范,len()重新定义成另一个函数
    def len(a1, a2):
        return a1 + a2
    
    
    # 以后执行len()函数,只能按照重新定义来使用
    print(len(11, 22))  # 33
    
    
3.函数名做参数和返回值
  • 函数名其实就一个变量,代指某个函数;和其他的数据类型一样,也可以当作函数的参数返回值

    • 参数

      # 参数
      def plus(num):
          return num + 100
      
      
      def handler(func):
          result = func(10)
          msg = "执行func,并获取到的结果为:{}".format(result)
          print(msg)  # 执行func,并获取到的结果为:110
      
      
      handler(plus)
      
    • 返回值

      # 返回值
      def diff(num):
          return num - 10
      
      
      def handler2():
          print("执行handler函数")  # 执行handler函数
          return diff
      
      
      result = handler2()
      print(result(20))  # 10
      
1.3返回值和print
  • 在函数中使用print,只是用于在某个位置输出内容

  • 在函数中使用return,是为了将函数得执行结果返回给调用者,以便于后续其他操作

    def add(num1, num2):
        print(num1 + num2)  # 30
    
    
    result = add(10, 20)
    print(result)  # None
    
    
    def add(num1, num2):
        return num1 + num2
    
    
    result = add(22, 33)
    print(result)  # 55
    
1.4作用域
  • 作用域,可以理解为一块空间,空间的数据是可以共享的
1.函数为作用域
  • Python以函数为作用域,在函数内创建的所有数据,可以在函数中被使用,无法在其他函数中被使用

    def func():
        name = "Ailke"
        data_list = [11, 22, 33]
        print(name, data_list)  # Ailke [11, 22, 33]
        age = 20
        print(age)  # 20
    
    
    def handler():
        age = 18
        print(age)  # 18
    
    
    func()
    handler()
    
2.全局和局部
  • Python中以函数为作用域函数的作用域其实是一个局部作用域

    goods = [
        {"name": "笔记本", "price": 6999},
        {"name": "手机", "price": 5999},
        {"name": "游艇", "price": 8660000},
        {"name": "显示器", "price": 2299}
    ]
    
    
    for index in range(len(goods)):
        item = goods[index]
        print(index + 1, item['name'], item['price'])
    
    while True:
        num = input("请输入要选择的商品序号(Q/q): ")
        if num.upper() == "Q":
            break
        if not num.isdecimal():
            print("用输入的格式错误!")
            break
        num = int(num)
        if num > 4 or num < 0:
            print("范围选择错误!")
            break
        target_index = num - 1
        choice_item = goods[target_index]
        print(choice_item['name'], choice_item['price'])
    
  • 全局变量

    • COUNTRYCITY_LIST是在全局作用域,全局作用域中创建的变量称为全局变量,可以在全局作用域中被使用,也可以在局部作用域被使用
    • 全局变量一般都是大写
    # 全局变量
    COUNTRY = "中国"
    CITY_LIST = ["北京", "上海", "深圳", "成都"]
    
    
    def download():
        # 局部变量
        url = "https://www.12306.cn"
        print(url)
        print(COUNTRY)
        print(CITY_LIST)
    
    
    def upload():
        # 局部变量
        file_name = "rose.zip"
        print(file_name)
        print(COUNTRY)
        print(CITY_LIST)
    
    
    print(COUNTRY)
    print(CITY_LIST)
    download()
    upload()
    
    
    # print(file_name)  # 报错
    # print(url)  # 报错
    
3.global关键词
  • 默认情况下,在局部作用域对全局变量只能进行: 读取修改内部元素 (可变类型),无法对全局变量进行重新赋值

    • 读取

      # 全局变量
      COUNTRY = "中国"
      CITY_LIST = ["北京", "上海", "深圳", "成都"]
      
      
      def download():
          # 局部变量
          url = "https://www.12306.cn"
          print(url)
          print(COUNTRY)
          print(CITY_LIST)
      
      download()
      
    • 修改内部元素(可变类型)

      # 全局变量
      COUNTRY = "中国"
      CITY_LIST = ["北京", "上海", "深圳", "成都"]
      
      
      def download():
          # 局部变量
          url = "https://www.12306.cn"
          print(url)
          print(COUNTRY)
          CITY_LIST.append("重庆")
          CITY_LIST[0] = "西安"
          print(CITY_LIST)
          
          
      download()
      
    • 无法对全局变量重新赋值

      COUNTRY = "中国"
      CITY_LIST = ["北京", "成都", "上海", "深圳"]
      
      
      def download():
          url = "https://www.12306.cn"
          CITY_LIST = ["四川省", "陕西", "重庆"]
          print(CITY_LIST)  # ['四川省', '陕西', '重庆']
      
      
      download()
      print(CITY_LIST)  # ['北京', '成都', '上海', '深圳']
      
  • 局部作用域中对全局变量重新赋值,则可以基于 global关键字 实现

    COUNTRY = "中国"
    CITY_LIST = ["北京", "成都", "上海", "深圳"]
    
    
    def download():
        url = "https://www.12306.cn"
    
        global CITY_LIST
        CITY_LIST = ["河北省", "山西省", "山东省"]
        print(CITY_LIST)  # ['河北省', '山西省', '山东省']
    
        global COUNTRY
        COUNTRY = "中华人民共和国"
        print(COUNTRY)  # 中华人民共和国
    
    
    download()
    print(CITY_LIST)  # ['河北省', '山西省', '山东省']
    
4.nonlocal关键字
def outer_function():
    x = 12

    def inner_function():
        nonlocal x
        # 此处添加nonlocal关键字,不是创建新的变量x,是修改变量x
        x = 20
        print("inner_function:", x)  # inner_function: 20

    inner_function()
    print("outer_function: ", x)  # outer_function:  20


outer_function()
3.函数高级
1.函数嵌套
  • Python中以函数为作用域,在作用域中定义的相关数据只能被 当前作用域子作用域使用

    userName = "Ailke"
    print(userName)  # Ailke
    
    
    def func():
        print(userName)
    
    
    func()  # Ailke
    
1.1函数的作用域中
  • 函数也是定义在作用域中的数据,在执行函数时候,也同样遵循: 优先在自己作用域中寻找,没有则向上一级作用域寻找

    # 1.在全局作用域定义了函数func
    def func():
        print("上一级作用域")
    
    
    # 2.在全局作用域找到func函数并执行
    func()  # 上一级作用域
    
    
    # 3.在全局作用域定义了execute函数
    def execute():
        print("局部作用域开始")  # 局部作用域开始
        # 优先在当前函数作用域func函数,没有则向上级作用域中寻找
        func()  # 上一级作用域
        print("局部作用域结束")  # 局部作用域结束
    
    # 4.在全局作用域执行execute函数
    execute()
    
1.2函数定义的位置
  • 函数均定义在全局作用域,其实函数也可以定义在局部作用域,函数被局部作用域和其子作用域中调用(函数的嵌套)

    def func():
        print("全局作用域")
    
    
    def handler():
        print("全局作用域2")
    
        def inner():
            print("局部作用域")
        inner()
        func()
        print("全局作用域3")
    
    
    '''
    全局作用域2
    局部作用域
    全局作用域
    全局作用域3
    '''
    handler()  
    
1.3嵌套引发的作用域问题
  • 优先在自己的作用域找变量,自己没有就去上级作用域
  • 在作用域中寻找值时,确保此时此刻的值是什么
  • 分析函数的执行,并确定函数 作用域链 (函数嵌套)
userName = "李四"


def run():
    userName = "ailke"

    def inner():
        print(userName)
    return inner


'''
ailke
None
'''
userNAME = run()
print(userNAME())

'''
ailke
None
'''
userNAME = run()
print(userNAME())
2.闭包
  • 闭包,简而言之就是将数据封装在一个包(区域)中,使用时再去里面取
  • 闭包是基于函数嵌套弄出来的一个特殊嵌套
1.封装数据防止污染全局
def func(age):
    userName = "赵六"

    def f1():
        print(userName, age)

    def f2():
        print(userName, age)

    def f3():
        print(userName, age)

    def f4():
        print(userName, age)

    f1()
    f2()
    f3()
    f4()


func(18)
2.封装数据封到一个包里,使用时再取
def task(arg):
    def inner():
        print(arg)
    return inner


inner_func_list = []
for val in [11, 22, 33]:
    inner_func_list.append(task(val))

inner_func_list[0]()  # 11
inner_func_list[1]()  # 22
inner_func_list[2]()  # 33
3.装饰器
  • 装饰器,在不修改原函数内容的前提下,通过 @ 函数可以实现在函数前后自定义执行一些功能

  • 实现效果

    • 可以在不改变原函数内部代码调用方式的前提下,实现函数执行和执行扩展功能
  • 实现原理

    • 基于 @语法函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数
    def func():
        print("我是func函数")
        value = [11, 22, 33]
        return value
    
    
    def outer(origin):
        def inner():
            print('before')
            res = origin()
            print('after')
            return res
        return inner
    
    
    func = outer(func)
    print(func)  # <function outer.<locals>.inner at 0x00000274D6164220>
    # 等效输出  inner()
    result = func()
    
    
    def outers(origin):
        def inner():
            print('before')
            res = origin()
            print('after')
            return res
        return inner
    
    
    @outers
    def func():
        print('我是func函数')
        value = [11, 22, 33]
        return value
    
    
    func()
    
    
  • 优化

    • 优化以支持多个参数

      def outer(origin):
          def inner(*args, **kwargs):
              print('before')
              res = origin(*args, **kwargs)
              print('after')
              return res
      
          return inner
      
      
      @outer
      def func1(a1):
          print("我是func1()函数")
          value = [11, 22, 33]
          return value
      
      
      @outer
      def func2(a1, a2):
          print("我是func2()函数")
          value = [11, 22, 33]
          return value
      
      
      @outer
      def func3(a3):
          print("我是func3()函数")
          value = [11, 22, 33]
          return value
      
      
      func1(12)
      func2(12, a2=18)
      func3({"name": "Ailke", "addr": "成都市"})
      
1.functools
  • 装饰器实际上就是将原函数更改为其他函数,然后再此函数中再去调用原函数

  • 不用functools也可以实现装饰器的基本功能,但是后期实际项目开发时,不加functools会出错(内部会读取___name_原函数,name重名的话就报错)

    import functools
    
    
    def handler():
        pass
    
    
    handler()
    # 读取当前函数名称
    print(handler.__name__)  # handler
    
    
    def auth(func):
        def inner(*args, **kwargs):
            return func(*args, **kwargs)
        return inner
    
    
    @auth
    def handler():
        pass
    
    
    handler()
    # 读取当前函数名称
    print(handler.__name__)  # inner
    
    
    def auth_update(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            return func(*args, **kwargs)
        return inner
    
    
    @auth_update
    def handler():
        pass
    
    
    handler()
    # 读取当前函数名称
    print(handler.__name__)  # handler
    
4.内置函数和推导式
1.匿名函数
  • 传统的函数的定义包括了: 函数名 + 函数体

    def send_email():
        pass
    
    
    # 执行
    send_email()
    # 当作列表元素
    # data_list = [send_email, send_email, send_email]
    # 当作参数传递
    # other_functions(send_email)
    
  • 匿名函数,则是基于lambda表达式现实定义一个可以没有名字的函数

    # 匿名函数
    data_list = [lambda x: x + 100, lambda x: x + 110, lambda x: x + 120]
    print(data_list[0](20))
    
    • 基于Lambda定义的函数格式为: lambda 参数: 函数体

    • 参数,支持任意参数

      lambda x: 函数体
      lambda x1, x2: 函数体
      lambda *args, **kwargs: 函数体
      
    • 函数体,只能支持单行的代码

      def send(x):
          return x + 100
      
      
      f1 = lambda x: x + 100
      
      # 函数体只能支持单行代码
      # functions = lambda x:
      #     x + 100
      
      
      print(send(10))  # 110
      print(f1(10))  # 110
      
    • 返回值,默认将函数单行代码执行的结果返回给函数的执行

      func = lambda x: x + 123
      
      value = func(123)
      print(value)  # 246
      
  • 扩展: 三元运算

    • 简单的函数,可以基于lambda表达式实现

    • 简单的条件语句,可以基于三元运算实现

      '''
      三元运算
      - 格式
          结果 = 条件成立时 if 条件 else 条件不成立时
      
      '''
      
      
      # 结合lambda
      func = lambda x: "大了" if x > 66 else "小了"
      print(func(99))
      
2.生成器
  • 生成器是由函数 + yield关键字创造出来的写法,在特定情况下,可以帮助我们节省内存

  • 生成器函数,函数中有yield存在时,函数就是生成器函数

    def func():
        print(112)
        yield 12
    
  • 生成器对象,执行生成器函数时,会返回一个生成器对象

    def func():
        print(112)
        yield 12
    
    
    print(func())  # <generator object func at 0x0000021DC6F34940>
    
  • 生成器的特点是,记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上继续向下执行

    def func():
        print(112)
        yield 12
    
    
    print(func())  # <generator object func at 0x0000021DC6F34940>
    
    print(next(func()))
    
    
    def funcs():
        print(111)
        yield 1
    
        print(222)
        yield 2
        # StopIteration: 2   error
        # return 2
    
        print(333)
        yield 3
    
    
    #   print(444)
    
    
    data = funcs()
    
    print(next(data))
    
    print(next(data))
    
    print(next(data))
    
    
  • 应用场景

    import random
    
    
    def gen_random_num(max_count):
        counter = 0
        while counter < max_count:
            yield random.randint(1000, 9999)
            counter += 1
    
    
    data_list = list(gen_random_num(30000))
    print(type(data_list))
    
    print(len(data_list))
    print(data_list[8989])
    
  • 知识拓展

    def func():
        print(111)
        v1 = yield 1
        print(v1)
    
        print(222)
        v2 = yield 2
        print(v2)
    
        print(333)
        v3 = yield 3
        print(v3)
    
        print(444)
    
    
    data = func()
    
    '''
    send()方法的作用:
        - 发送一个值到生成器中,这个值将作为上一个yield表达式的结果;第一次调用生成器的send()方法时,传入None值
        - 触发生成器继续执行,直到遇到下一个yield语句,并返回该yield语句产出的值
        - 发送值之后生成器执行完毕(没有更多的yield语句),则send()方法将会引发Stopiteration异常
    '''
    
    n1 = data.send(None)
    print(n1)
    
    n2 = data.send(666)
    print(n2)
    
    n3 = data.send(777)
    print(n3)
    
    n4 = data.send(888)
    print(n4)
    
3.内置函数
# abs 绝对值
print(abs(-10))  # 10

# pow 指数
print(pow(2, 3))  # 8

# sum 求和
print(sum([1, 2, 3, -10, 12]))  # 8

# divmod 求商和余数,返回元组类型
print(divmod(9, 2))  # (4, 1)

# round,小数点后n位(四舍五入)
print(round(3.1415926, 4))  # 3.1416

# min 最小值   def min(*args, key=None):
print(min([12, 56, 8, 10]))  # 8

# max 最大值
print(max([12, 56, 88], key=lambda x: x * 10))

# all  是否全部为True
print(all([11, 22, 33, " ", ""]))  # False

# any 是否存在True
print(any([11, 22, 33, " ",""]))  # True

# oct  十进制转八进制
print(oct(125))  # 0o175
# hex 十进制转十六进制
print(hex(125))  # 0x7d
# bin 十进制转二进制
print(bin(125))  # 0b1111101

4.推导式
# 列表
num_list = [i for i in range(10)]
print(num_list)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 集合
num_set = {(i, i, i) for i in range(10) if i > 6}
print(num_set)  # {(8, 8, 8), (7, 7, 7), (9, 9, 9)}

# 字典
num_dict = {i: (i, 11) for i in range(10) if i >= 6}
print(num_dict)  # {6: (6, 11), 7: (7, 11), 8: (8, 11), 9: (9, 11)}

# 元组,不同于其他类型
# 不会立即执行内部循环去生成数据,而是得到一个生成器
num_tup = (i for i in range(10))
print(num_tup)  # <generator object <genexpr> at 0x0000025B35546A40>
print(next(num_tup))  # 0
print(next(num_tup))  # 1

2.模块

1.自定义模块
1.1模块和包
import hashlib


def encrypt(data):
    '''数据加密'''
    hash_object = hashlib.md5()
    hash_object.update(data.encode('utf-8'))
    return hash_object.hexdigest()


userName = input("Enter your username:")
pwd = input("Enter your password:")
md5_password = encrypt(pwd)
message = "用户名:{},密码:{}".format(userName,md5_password)
print(message)
  • 简单的程序,可以通过一个py文件编写完成;对于程序比较庞大,此时就需要代码结构清晰
  • 在Python中一般对文件和文件的称呼
    • 一个py文件,称为模块(Module)
    • 含多个py文件的文件夹,称为(package)
  • 注意: 在包(文件夹)中有一个默认内容为空的___init___.py的文件,一般用于描述当前包的信息
    • py2必须有,如果没有导入包就会失败
    • py3可有可无
1.2导入
  • 导入,其实就是将模块加载的内存中,以后再去内存中去拿就行

  • 在Python内部默认设置了一些路径,导入模块时,都会按照指定顺序逐一去特定的路径查找

  • 手动设置路径,进行包的导入,**sys.path()**中添加路径

    import sys
    sys.path.append("指定路径")
    
    # 导入指定路径下的一个***.py文件
    import ***
    
    • 写模块名称时,不能和内置第三方的同名
    • 项目执行文件一般在项目根目录,执行文件嵌套的内存目录,就需要自己手动在sys.path中添加路径
    • pycharm中默认会将项目目录加入到sys.path
  • 第一类方式: **import *****(开发中,一般多用于导入sys.path目录下的一个py文件)

    '''
    |---commons
    |       |---- __init__.py
    |       |---- tools
    |               |---- __init__.py
    |               |---- sum.py
    |---main.py
    
    '''
    
    
    import commons.utils
    import commons.tools.sum
    
    userName = input("Enter your username:")
    pwd = input("Enter your password:")
    # md5_password = utils.encrypt(pwd)
    md5_password = commons.utils.encrypt(pwd)
    message = "用户名:{},密码:{}".format(userName,md5_password)
    print(message)
    
    print("输入数据和: ", commons.tools.sum.sum_itme([12, 13, 14]))
    print("输入数据和: ", commons.tools.sum.sum_itme((12, 15, 16,)))
    print("输入数据和: ", commons.tools.sum.sum_itme(12.45))
    
    
    
    import hashlib
    
    
    def encrypt(data):
        '''数据加密'''
        hash_object = hashlib.md5()
        hash_object.update(data.encode('utf-8'))
        return hash_object.hexdigest()
    
    
    
    
    def sum_itme(items):
        if isinstance(items, (int, float)):
            items = [items]
        elif not isinstance(items, (list, tuple)):
            raise TypeError("The input must be a number or a list of numbers")
        return sum(items)
    
    
  • 第二类方式: from ******* import *******(常用),一般适用于多层嵌套和导入模块中某个成员的情况

    '''
    |---commons
    |       |---- __init__.py
    |       |---- tools
    |               |---- __init__.py
    |               |---- sum.py
    |---main.py
    
    '''
    
    
    from commons import utils
    from commons.tools import sum
    # import commons.utils
    # import commons.tools.sum
    
    userName = input("Enter your username:")
    pwd = input("Enter your password:")
    # md5_password = utils.encrypt(pwd)
    md5_password = utils.encrypt(pwd)
    message = "用户名:{},密码:{}".format(userName,md5_password)
    print(message)
    
    print("输入数据和: ", sum.sum_itme([12, 13, 14]))
    print("输入数据和: ", sum.sum_itme((12, 15, 16,)))
    print("输入数据和: ", sum.sum_itme(12.45))
    
    # print("输入数据和: ", commons.tools.sum.sum_itme([12, 13, 14]))
    # print("输入数据和: ", commons.tools.sum.sum_itme((12, 15, 16,)))
    # print("输入数据和: ", commons.tools.sum.sum_itme(12.45))
    
    
    import hashlib
    
    
    def encrypt(data):
        '''数据加密'''
        hash_object = hashlib.md5()
        hash_object.update(data.encode('utf-8'))
        return hash_object.hexdigest()
    
    
    
    
    def sum_itme(items):
        if isinstance(items, (int, float)):
            items = [items]
        elif not isinstance(items, (list, tuple)):
            raise TypeError("The input must be a number or a list of numbers")
        return sum(items)
    
    
1.3相对导入
  • 在导入模块时,对于from ******* import *** 这种模式,还支持相对导入

    '''
    mypackage/  
        __init__.py  
        module_a.py  
        subpackage/  
            __init__.py  
            module_x.py  
            module_y.py
    '''
    # 从module_a.py导入module_x.py
    from .subpackage import module_x
    
    # 从module_x.py导入module_a.py
    from .. import module_a
    
    
  • **.代表当前包,…**代表父级包,相对导入只能用在包中的py文件中

1.4导入别名
  • 项目在导入 成员模块 有重名,那么导入后会覆盖之前的导入,为了避免这种情况的发生,Python支持重命名

    # 两种导入方式都可重命名
    from ***.*** import *** as **
    import ***.*** as **
    
1.5主文件
  • 执行一个py文件时

    __name__ = "__main__"
    
  • 导入一个py文件时

    __name__ = "模块名"
    
  • 文件内部__name__变量的值为__main___,以主文件的形式允许此脚本时start函数才会被执行,被导入时则不会被执行

    if __name__ == '__main__':
        start()
    
2.第三方模块
1.pip (最常用)
  • pip其实是个第三方模块包管理工具,默认安装Python解释器时自动会安装,默认目录

    '''
    windows系统,即: Python安装路径的scripts目录下
    	- C:\**\Scripts\pip3.exe
    	- C:\**\Scripts\pip.版本号.exe
    
    '''
    
  • pip安装模块,默认安装最新版本

    # 默认安装
    pip3 install 模块名称
    
    # 指定版本安装
    pip3 install 模块名称==版本
    
  • pip更新版本

    # 查看当前版本
    pip3 --version
    
    # 更新
    pip3 install --upgrade pip
    
    
2.豆瓣源
  • pip默认是去https://pypi.org去下载第三方模块,国内下载可能出现问题,为了加速下载可以使用豆瓣源

  • 一次性使用下载

    # 如果按照一下指令显示对源不信任,在末尾加上--trusted-host pypi.douban.com
    pip3 install 模块名称 -i https://pypi.douban.com/simple
    
  • 永久使用

    • 配置
    # 替换主机下载路径
    pip3 config set global.index-url https://pypi.douban.com/simple/
    '''
    国内常用的镜像
    	- 阿里云:http://mirrors.aliyun.com/pypi/simple/
    	- 中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/ 
    	- 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/
    	-中国科学技术大学:http://pypi.mirrors.ustc.edu.cn/simple/
    
    '''
    
    • 使用
    
    pip3 install 模块名称
    
3.源码
  • 下载源码安装模块

    • 下载源码

      # 1.不管是GitHub或网站下载,需要解压的首先解压
      # 2.进入到目录
      # 3.运行命令
      # # 编译
      python setup.py build
      # # 安装
      python setup.py install
      
4.wheel
  • 下载wheel文件

    • 从某个源下载模块的wheel文件,wheel的文件扩展命通常是.whl
  • 安装wheel包

    # 需要安装wheel
    pip3 install wheel
    
  • 使用pip安装wheel文件

    pip3 install 模块名称.whl
    
3.内置模块
1.os
import os.path

# 获取当前脚本绝对路径
abs_path = os.path.abspath(__file__)
print(abs_path)  # C:\Tools\devTools\Pycharm\code\内置模块\main.py

# 获取当前文件的上级目录
parent_path = os.path.dirname(abs_path)
print(parent_path)  # C:\Tools\devTools\Pycharm\code\内置模块

# 路径拼接
print(os.path.join(parent_path, "test.txt"))  # C:\Tools\devTools\Pycharm\code\内置模块\test.txt

# 判断路径是否存在
print(os.path.exists(os.path.join(parent_path, "test.txt")))  # False
print(os.path.exists(os.path.join(parent_path, "main.py")))  # True

# 创建路径
os.makedirs(os.path.join(parent_path, "test"), exist_ok=True)
print(os.path.exists(os.path.join(parent_path, "test")))  # True

# 是否是文件夹
print(os.path.isdir(os.path.join(parent_path, "test")))  # True
print(os.path.isdir(os.path.join(parent_path, "test.txt")))  # False

# 删除文件或文件夹
os.remove(os.path.join(parent_path, "test.txt"))
print(os.path.exists(os.path.join(parent_path, "test.txt")))  # False

os.rmdir(os.path.join(parent_path, "test"))
print(os.path.exists(os.path.join(parent_path, "test")))  # False

# 创建文件
# 'w'模式表示写入模式,如果文件不存在,则会创建该文件
with open(os.path.join(parent_path, "test.txt"), "w", encoding="utf-8") as f:
    f.write("hello world")
print(os.path.exists(os.path.join(parent_path, "test.txt")))  # True

# 查看目录下所有的文件
print(os.listdir(os.path.join(parent_path, "test")))  # ['test.txt', 'txt']

# 查看目录下所有的文件(含子孙文件)
data = os.walk(os.path.join(parent_path, "test"))
for path, folder_list, file_list in data:
    print(path)
    print(folder_list)
    print(file_list)
    # for file_name in file_list:
    #     file_abs_path = os.path.join(path, file_name)
    #     print(file_abs_path)
    # for folder_name in folder_list:
    #     folder_abs_path = os.path.join(path, folder_name)
    #     print(folder_abs_path)
    #
    # for path_name in path:
    #     print(path_name)
2.shutil
import shutil
import os

# 获取当前脚本的绝对位置
abs_path = os.path.abspath(__file__)

# 获取当前位置的上一级目录
base_path = os.path.dirname(abs_path)
print(base_path)  # C:\Tools\devTools\Pycharm\code\内置模块
print(os.getcwd())  # C:\Tools\devTools\Pycharm\code\内置模块
# 删除文件夹
shutil.rmtree(os.path.join(os.getcwd(), 'study'))

# 拷贝文件夹  拷贝的目标地址,如果存在就会报错
shutil.copytree(os.path.join(base_path, "test"), os.path.join(os.getcwd(), 'studentInfo'))

# 拷贝文件
shutil.copy(os.path.join(abs_path), os.path.join(os.getcwd(), 'study'))

# 文件或文件夹重命名
shutil.move(os.path.join(os.getcwd(), "study/main.py"), os.path.join(base_path, "study/info.py"))

# 压缩文件
shutil.make_archive(base_name=r'dataFile', format='zip', root_dir=os.path.join(base_path, 'studentInfo'))

# 解压文件
shutil.unpack_archive(filename=r'dataFile.zip', extract_dir=os.path.join(os.getcwd(), "study"), format='zip')
3.sys
import sys

# 获取解释器版本
print(sys.version)
print(sys.version_info)
print("Python主版本号:", sys.version_info.major, ",Python此版本号:", sys.version_info.minor, ",Python微版本号:",sys.version_info.micro,
      ",Python发行级别:", sys.version_info.releaselevel, ",Python发行序列号:", sys.version_info.serial)
# 导入模块路径
print(sys.path)
4.random
import random

# 获取范围内的随机整数
print(random.randint(10, 20))

# 获取范围内的随机小数
print(random.uniform(10, 20))

# 随机抽取一个元素
print(random.choice([11, 22, 23, 56, 89]))

# 随机抽取多个元素
print(random.sample([11, 55, 66, 23, 56, 89], 3))

# 打乱顺序
data = [1, 2, 3, 4, 5, 6]
random.shuffle(data)
print(data)


5.hashlib
6.configparser
  • 见下文
7.xml
  • 见下文

3.文件操作

1.文件操作
  • 字符串类型(str),在程序中用于表示文字信息,本质上是unicode编码中的二进制

    str = "Python"
    
  • 字节类型

    • 可表示文字信息,本质上是utf-8/gbk等编码的二进制

      strInfo = "Python"
      data = strInfo.encode("utf-8")  # b'Python'
      print(data)
      
      result = data.decode("utf-8")
      print(result)  # Python
      
    • 可表示原始二进制(图片、文件等信息)

1.读文件
  • 读文本文件
# 打开文件
'''
mode是一个可选字符,默认值为 r,打开文本阅读模式
    - w 表示写入(截断文件)
    - x 表示用于创建喝写入新文件
    - a 表示追加(在某些Unix系统上,表示所有写入),追加到文件的末尾
    - b 表示二进制模式
    - t 表示文本模式(默认)
    - + 打开磁盘文件进行更新(读写)

'''
import os.path

# 打开文件
file_object = open(os.path.join(os.getcwd(), "test") + "/test.txt", mode='rb')
# 读取文件内容,并赋值给data
data = file_object.read()
# 关闭文件
file_object.close()

# 输出文件内容(二进制)
print(data)
# 解码
text = data.decode('utf-8')
print(text)


# # 打开文件
# file_object = open(os.path.join(os.getcwd(), "test") + "/test.txt", mode='rt',encoding='utf-8')
# # 读取文件内容,并赋值给data
# data = file_object.read()
# # 关闭文件
# file_object.close()
#
# print(data)
  • 读图片等非文本内容文件

    # 打开文件
    file_object = open(os.path.join(os.getcwd(), "test") + "/python安装检验.png", mode="rb")
    # 读取文件内容,并赋值给data
    data = file_object.read()
    # 关闭文件
    file_object.close()
    # 打印二进制码
    print(data)
    
  • 读文件时,文件不存在程序会报错

    file_path = os.path.join(os.getcwd(), "test/test.txt")
    exists = os.path.exists(file_path)
    if exists:
        # 打开文件
        file_object = open(file_path, mode='rt', encoding='utf-8')
        # 读取文件内容,并赋值给data
        data = file_object.read()
        # 关闭文件
        file_object.close()
        print(data)
    else:
        print("文件不存在!")
    
2.写文件
# 写文件文本
# 打开文件   用二进制方式输入
# file_object = open(os.path.join(os.getcwd() + "/test/txt.txt"), mode="wb")
# 用文本方式输入 w模式会新建,然后再写入内容;文件存在时,w模式会清空文件再写入内容
file_object = open(os.path.join(os.getcwd() + "/test/text.txt"), mode="wt", encoding='utf-8')

# 写入内容
# file_object.write("新公司真不错".encode("utf-8"))
file_object.write("新公司业务好")

# 文件关闭
file_object.close()

# 写图片等文件
f1 = open(os.path.join(os.getcwd() + "/test/python安装检验.png"), mode='rb')
content = f1.read()
f1.close()

f2 = open(os.path.join(os.path.dirname(os.path.abspath(__file__)) + "/test/python安装检验_copy.png"), mode='wb')
f2.write(content)
f2.close()

# 案例: 多用户注册
# 新建文件夹
os.makedirs(os.path.join(os.getcwd(), "files"), exist_ok=True)
file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="wt", encoding="utf-8")
while True:
    user = input("请输入用户名:")
    if user.upper() == "Q":
        break
    pwd = input("请输入密码:")
    data = "{}----{}".format(user, pwd)
    file_object.write(data + "\n")
file_object.close()
3.文件打开模式
  • 基于文件操作基本实现了写的功能,其中涉及的文件操作模式: rt 、rb、wt、wb,其实再文件操作还有其他很多模式

     Character Meaning
        --------- ---------------------------------------------------------------
        'r'       open for reading (default)
        'w'       open for writing, truncating the file first
        'x'       create a new file and open it for writing
        'a'       open for writing, appending to the end of the file if it exists
        'b'       binary mode
        't'       text mode (default)
        '+'       open a disk file for updating (reading and writing)
    The default mode is 'rt' (open for reading text)
    
  • 文件的打开模式常见应用有

    • 只读: r 、rt 、rb

      • 存在,读
      • 不存在,报错
    • 只写: w、wt、wb

      • 存在,清空再写
      • 不存在,创建再写
    • 只写: x、xt、xb

      • 存在,报错
      • 不存在,创建再写
    • 只写: a、at、ab

      • 存在,尾部追加
      • 不存在,创建再写
    • 读写:

      • r+、rt+、rb+

      • 默认光标位置,起始位置

        # rt+
        # 打开文件
        file_object = open(os.path.join(os.getcwd() + "/files/infos.txt"), mode="rt+")
        # 读取文件
        data = file_object.read()
        print(data)
        
        # 写入内容
        file_object.write("你好呀")
        
        file_object.close()
        
      • w+、wt+、wb+,默认光标位置,为起始位置(清空文件)

        # wt+
        # 打开文件
        file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="wt+")
        
        # 读取文件
        data = file_object.read()
        print(data)  # 
        
        # 写入内容
        file_object.write("你好呀")
        
        # 重置光标起始位置
        file_object.seek(0)
        
        # 读取文件
        data = file_object.read()
        print(data)  # 你好呀
        
        file_object.close()
        
      • x+、xt+、xb+,默认光标位置: 起始位置(新文件)

      • a+、at+、ab+,默认光标位置: 末尾

        # at+
        # 打开文件
        file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="at+")
        
        # 写入内容
        file_object.write("你好呀")
        
        # 重置光标起始位置
        file_object.seek(0)
        
        # 读取文件
        data = file_object.read()
        print(data)  # 你好呀
        
        file_object.close()
        
        
4.常见功能
  • read,读

    • 读所有

      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8')
      data = file_object.read()
      file_object.close()
      
    • 读n个字符(字节)

      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8')
      # 读一个字符
      data = file_object.read(1)
      file_object.close()
      
      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="rb")
      # 读一个字节;编码格式为utf-8,参数输入3,表示读取一个字符
      data = file_object.read(1)
      file_object.close()
      
    • readline,读一行

      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8')
      data = file_object.readline()
      file_object.close()
      
    • readlines,读所有行,每行作为列表的一个元素

      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8')
      data_list = file_object.readlines()
      file_object.close()
      
    • 循环,读大文件

      # 读取二进制模式下,不需要设置字符编码
      file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding='utf-8')
      for line in file_object:
          print(line.strip())
      file_object.close()
      
  • write,写

    # 打开文件
    file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="a", encoding="utf-8")
    
    # 写入内容
    file_object.write("你好呀")
    
    file_object.close()
    
    
    
    # 打开文件
    file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="ab")
    
    # 写入内容
    file_object.write("你好呀".encode("utf-8"))
    
    file_object.close()
    
  • flush,刷到硬盘

    # 打开文件
    file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="ab")
    
    # 写入内容
    file_object.write("你好呀".encode("utf-8"))
    # 缓冲区刷到硬盘
    file_object.flush()
    
    file_object.close()
    
  • 移动光标位置(字节)

    • 在a模式下,调用write在文件中写入内容,永远只能将内容写入尾部,不会写到光标位置
    # 打开文件
    file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r+", encoding="utf-8")
    
    # 移动光标位置,(UTF-8)编码格式,按照每3个字节为一个单位移动
    file_object.seek(3)
    # 写入内容
    file_object.write("你好呀")
    # 缓冲区刷到硬盘
    file_object.flush()
    
    file_object.close()
    
  • 获取当前光标位置

    # 打开文件
    file_object = open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding="utf-8")
    
    # 获取光标位置 0
    file_object.tell()
    
    # 读取三个字符 
    file_object.read(3)
    
    # 获取光标位置 3 * 3 = 9
    file_object.tell()
    
    file_object.close()
    
5.上下文管理
  • 进行文件操作时,使用with上下文管理,可以自动实现关闭文件

    # Python2.7之后,支持同时多个文件的上下文管理
    with open(os.path.join(os.getcwd() + "/files/info.txt"), mode="r", encoding="utf-8") as f1, open(os.path.join(os.getcwd() + "/files/infos.txt"), mode="rb") as fb:
        pass
    
2.csv格式文件
  • 逗号分隔值(csv,也称为字符分隔值),其文件以纯文本形式存储表格数据

    • 文本

      26044585,Hush,https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V
      19318369,柒十一,https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO
      15529690,Law344,https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd
      18311394,Jennah·,https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz
      18009711,可洛爱画画,https://hbimg.huabanimg.com/03331ef39b5c7687f5cc47dbcbafd974403c962ae88ce-Co8AUI
      30574436,花姑凉~,https://hbimg.huabanimg.com/2f5b657edb9497ff8c41132e18000edb082d158c2404-8rYHbw
      17740339,小巫師,https://hbimg.huabanimg.com/dbc6fd49f1915545cc42c1a1492a418dbaebd2c21bb9-9aDqgl
      18741964,桐末tonmo,https://hbimg.huabanimg.com/b60cee303f62aaa592292f45a1ed8d5be9873b2ed5c-gAJehO
      30535005,TANGZHIQI,https://hbimg.huabanimg.com/bbd08ee168d54665bf9b07899a5c4a4d6bc1eb8af77a4-8Gz3K1
      31078743,你的老杨,https://hbimg.huabanimg.com/c46fbc3c9a01db37b8e786cbd7174bbd475e4cda220f4-F1u7MX
      25519376,尺尺寸,https://hbimg.huabanimg.com/ee29ee198efb98f970e3dc2b24c40d89bfb6f911126b6-KGvKes
      21113978,C-CLong,https://hbimg.huabanimg.com/7fa6b2a0d570e67246b34840a87d57c16a875dba9100-SXsSeY
      24674102,szaa,https://hbimg.huabanimg.com/0716687b0df93e8c3a8e0925b6d2e4135449cd27597c4-gWdv24
      30508507,爱起床的小灰灰,https://hbimg.huabanimg.com/4eafdbfa21b2f300a7becd8863f948e5e92ef789b5a5-1ozTKq
      12593664,yokozen,https://hbimg.huabanimg.com/cd07bbaf052b752ed5c287602404ea719d7dd8161321b-cJtHss
      16899164,一阵疯,https://hbimg.huabanimg.com/0940b557b28892658c3bcaf52f5ba8dc8402100e130b2-G966Uz
      847937,卩丬My㊊伴er彎,https://hbimg.huabanimg.com/e2d6bb5bc8498c6f607492a8f96164aa2366b104e7a-kWaH68
      31010628,慢慢即漫漫,https://hbimg.huabanimg.com/c4fb6718907a22f202e8dd14d52f0c369685e59cfea7-82FdsK
      13438168,海贼玩跑跑,https://hbimg.huabanimg.com/1edae3ce6fe0f6e95b67b4f8b57c4cebf19c501b397e-BXwiW6
      28593155,源稚生,https://hbimg.huabanimg.com/626cfd89ca4c10e6f875f3dfe1005331e4c0fd7fd429-9SeJeQ
      28201821,合伙哼哼,https://hbimg.huabanimg.com/f59d4780531aa1892b80e0ec94d4ec78dcba08ff18c416-769X6a
      28255146,漫步AAA,https://hbimg.huabanimg.com/3c034c520594e38353a039d7e7a5fd5e74fb53eb1086-KnpLaL
      30537613,配䦹,https://hbimg.huabanimg.com/efd81d22c1b1a2de77a0e0d8e853282b83b6bbc590fd-y3d4GJ
      22665880,日后必火,https://hbimg.huabanimg.com/69f0f959979a4fada9e9e55f565989544be88164d2b-INWbaF
      16748980,keer521521,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4
      30536510,“西辞”,https://hbimg.huabanimg.com/61cfffca6b2507bf51a507e8319d68a8b8c3a96968f-6IvMSk
      30986577,艺成背锅王,https://hbimg.huabanimg.com/c381ecc43d6c69758a86a30ebf72976906ae6c53291f9-9zroHF
      26409800,CsysADk7,https://hbimg.huabanimg.com/bf1d22092c2070d68ade012c588f2e410caaab1f58051-ahlgLm
      30469116,18啊全阿,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4
      15514336,W/小哥,https://hbimg.huabanimg.com/a30f5967fc0acf81421dd49650397de63c105b9ead1c-nVRrNl
      17473505,椿の花,https://hbimg.huabanimg.com/0e38d810e5a24f91ebb251fd3aaaed8bb37655b14844c-pgNJBP
      19165177,っ思忆゜♪,https://hbimg.huabanimg.com/4815ea0e4905d0f3bb82a654b481811dadbfe5ce2673-vMVr0B
      16059616,格林熊丶,https://hbimg.huabanimg.com/8760a2b08d87e6ed4b7a9715b1a668176dbf84fec5b-jx14tZ
      30734152,sCWVkJDG,https://hbimg.huabanimg.com/f31a5305d1b8717bbfb897723f267d316e58e7b7dc40-GD3e22
      24019677,虚无本心,https://hbimg.huabanimg.com/6fdfa9834abe362e978b517275b06e7f0d5926aa650-N1xCXE
      16670283,Y-雨后天空,https://hbimg.huabanimg.com/a3bbb0045b536fc27a6d2effa64a0d43f9f5193c177f-I2vHaI
      21512483,汤姆2,https://hbimg.huabanimg.com/98cc50a61a7cc9b49a8af754ffb26bd15764a82f1133-AkiU7D
      16441049,笑潇啸逍小鱼,https://hbimg.huabanimg.com/ae8a70cd85aff3a8587ff6578d5cf7620f3691df13e46-lmrIi9
      24795603,⁢⁢⁢⁢⁢v,https://hbimg.huabanimg.com/a7183cc3a933aa129d7b3230bf1378fd8f5857846cc5-3tDtx3
      29819152,妮玛士珍多,https://hbimg.huabanimg.com/ca4ecb573bf1ff0415c7a873d64470dedc465ea1213c6-RAkArS
      19101282,陈勇敢❤,https://hbimg.huabanimg.com/ab6d04ebaff3176e3570139a65155856871241b58bc6-Qklj2E
      28337572,爱意随风散,https://hbimg.huabanimg.com/117ad8b6eeda57a562ac6ab2861111a793ca3d1d5543-SjWlk2
      17342758,幸运instant,https://hbimg.huabanimg.com/72b5f9042ec297ae57b83431123bc1c066cca90fa23-3MoJNj
      18483372,Beau染,https://hbimg.huabanimg.com/077115cb622b1ff3907ec6932e1b575393d5aae720487-d1cdT9
      22127102,栽花的小蜻蜓,https://hbimg.huabanimg.com/6c3cbf9f27e17898083186fc51985e43269018cc1e1df-QfOIBG
      13802024,LoveHsu,https://hbimg.huabanimg.com/f720a15f8b49b86a7c1ee4951263a8dbecfe3e43d2d-GPEauV
      22558931,白驹过隙丶梨花泪う,https://hbimg.huabanimg.com/e49e1341dfe5144da5c71bd15f1052ef07ba7a0e1296b-jfyfDJ
      11762339,cojoy,https://hbimg.huabanimg.com/5b27f876d5d391e7c4889bc5e8ba214419eb72b56822-83gYmB
      30711623,雪碧学长呀,https://hbimg.huabanimg.com/2c288a1535048b05537ba523b3fc9eacc1e81273212d1-nr8M4t
      18906718,西霸王,https://hbimg.huabanimg.com/7b02ad5e01bd8c0a29817e362814666a7800831c154a6-AvBDaG
      31037856,邵阳的小哥哥,https://hbimg.huabanimg.com/654953460733026a7ef6e101404055627ad51784a95c-B6OFs4
      26830711,稳健谭,https://hbimg.huabanimg.com/51547ade3f0aef134e8d268cfd4ad61110925aefec8a-NKPEYX
      
    • 代码

      with open(os.path.join(os.getcwd() + "/test/stuInfos.csv"), mode="r", encoding="utf-8") as file_object:
          file_object.readline()
          for line in file_object:
              user_id, userName, url = line.strip().split(",")
              # 根据URL下载图片
              res = requests.get(
                  url=url,
                  headers={
                      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
                  }
              )
              # 检查 images 目录是否存在? 不存在,创建images目录
              if not os.path.exists(os.getcwd() + "/test/images"):
                  # 创建
                  os.makedirs(os.getcwd() + "/test/images")
      
              # 将图片的内容写入文件
              with open(os.path.join(os.getcwd() + "/test/images/{}.png".format(userName)), mode="wb") as img_object:
                  img_object.write(res.content)
      
3.ini格式文件
  • ini文件时initialzation File的缩写,平时用于存储软件的配置文件

    • 文件

      [mysqld]
      datadir=/var/lib/mysql
      socket=/var/lib/mysql/mysql.sock
      log-bin=py-mysql-bin
      character-set-server=utf8
      collation-server=utf8_general_ci
      log-error=/var/log/mysqld.log
      # Disabling symbolic-links is recommended to prevent assorted security risks
      symbolic-links=0
      
      [mysqld_safe]
      log-error=/var/log/mariadb/mariadb.log
      pid-file=/var/run/mariadb/mariadb.pid
      
      [client]
      default-character-set=utf8
      
    • 代码

      # 初始化对象
      config = configparser.ConfigParser()
      config.read(os.path.join(os.getcwd() + "/test/my.ini"), encoding="utf-8")
      
      # 获取所有节点
      result = config.sections()
      print(result,type(result))  # ['mysqld', 'mysqld_safe', 'client'] <class 'list'>
      
      # 获取节点下的键值
      result = config.items(result[1])
      print(result, type(result))  # [('log-error', '/var/log/mariadb/mariadb.log'), ('pid-file', '/var/run/mariadb/mariadb.pid')] <class 'list'>
      
      for key,value in config.items("mysqld_safe"):
          print(key, value)
      
      
      # 获取某个节点下的键对应的值
      result = config.get("mysqld_safe", "pid-file")
      print(result, type(result))  # /var/run/mariadb/mariadb.pid <class'str'>
      
      # 检查、删除、添加节点
      hassection = config.has_section("client")
      print(hassection)  # True
      
      # 删除节点,包含该节点下面的键值对
      config.remove_section('client')
      
      # 删除节点下指定键的键值对
      config.remove_option("mysqld", "datadir")
      
      # 操作删除之后,需要更新回配置文件中
      with open(os.path.join(os.getcwd() + "/test/my.ini"), mode="w", encoding="utf-8") as configFile:
          config.write(configFile)
      
      # 添加节点
      config.add_section('server')
      config.set('server', 'port', '8080')
      config.set('server', 'ipAddr', '176.0.5.6')
      config.set('mysqld', 'datadir','/var/lib/mysql')
      
      # 添加操作之后,需要更新回配置文件  效果类似于with open...
      config.write(open(os.path.join(os.getcwd() + "/test/my.ini"), mode='w', encoding='utf-8'))
      
      
4.XML格式文件
  • 可扩展标记语言,是一种捡蛋的数据存储语言,XML被设计用来传输和存储数据

    • 存储,可用来存放配置文件
    • 传输,网络传输时以这种格式存在
1.读取文件和内容
from xml.etree import ElementTree as ET
# XML格式文件

# 打开XML文件
tree = ET.parse(open(os.path.join(os.getcwd() + "/test/data.xml")))

# 获取根标签
root = tree.getroot()

# 打印根标签
print(root.tag)  # data

# 代码中的XML解析
content = """
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2023</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2026</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2026</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>
"""
# 获取根标签
root = ET.XML(content)
print(root.tag)  # data
2.读取节点数据
# 读取节点数据
country_object = root.find("country")
# attrib函数获取标签内的属性
print(country_object.tag, country_object.attrib)  # country {'name': 'Liechtenstein'}

# 获取标签gdppc
gdppc_object = country_object.find("gdppc")
print(gdppc_object.tag, gdppc_object.text)  # gdppc 141100

# 获取data标签的子标签
for child in root:
    # 子标签的标签名和标签内部属性
    print(child.tag, child.attrib)
    print("单个data标签分割线".center(30, "*"))
    for node in child:
        # 子标签内部节点   标签命  标签内部属性   标签的值   无值用None表示
        print(node.tag, node.attrib, node.text)

# 通过根标签指定内部标签,获取内部标签的相关信息
for child in root.iter('rank'):
    '''
        rank 2
        rank 5
        rank 69
    '''
    print(child.tag, child.text)

# 查找XML中指定的所有标签
root_son = root.findall("country")
print(root_son)  # [<Element 'country' at 0x0000025D2B79FBF0>, <Element 'country' at 0x0000025D2B79FDD0>, <Element 'country' at 0x0000025D2B79FF60>]

# 通过find()函数,查找多层标签,仅限查询到的一个符合标签
root_son_str = root.find("country").find("year")
print(root_son_str.tag, root_son_str.attrib, root_son_str.text)
3.修改和删除节点
# 修改节点内容和属性
rank = root.find("country").find("rank")
print(rank.text)
rank.text = "123"
rank.set("update", "no")
print(rank.text, rank.attrib)

# 保存配置
tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/data.xml"), encoding="utf-8")

# 删除节点
root.remove(root.find("country"))
print(root.findall("country"))
# 保存文件
tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/data.xml"), encoding="utf-8")
# 笑死,禁忌切勿混合模块
# tree.write(open(os.path.join(os.getcwd() + "/test/data.xml"), mode="w", encoding="utf8"))
4.构建文档
  • student.csv

    李四,18,四川省成都市
    田六,20,四川省德阳市
    王五,27,四川省南充市
    Tom,38,NewYork
    
# 创建根标签
root = ET.Element("studentInfos")
#
# # 创建根标签的子节点
# student1 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "张三"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "20"
# address = ET.Element("address")
# address.text = "成都市"
# student1.append(name)
# student1.append(age)
# student1.append(address)
#
# student2 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "赵六"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "25"
# address = ET.Element("address")
# address.text = "上海市"
# student2.append(name)
# student2.append(age)
# student2.append(address)
#
# student3 = ET.Element("student", {"desc": "学生信息"})
# name = ET.Element("name")
# name.text = "李四"
# age = ET.Element("age", {"desc": "Data legitimacy"})
# age.text = "18"
# address = ET.Element("address")
# address.text = "重庆市"
# student3.append(name)
# student3.append(age)
# student3.append(address)
#
# root.append(student1)
# root.append(student2)
# root.append(student3)


def create_student_info(username, Age, addr):
    student = ET.Element("student", {"desc": "学生信息"})
    name = ET.Element("name")
    name.text = username
    age = ET.Element("age", {"desc": "Data legitimacy"})
    age.text = Age
    address = ET.Element("address")
    address.text = addr
    student.append(name)
    student.append(age)
    student.append(address)
    return student


with open(os.path.join(os.getcwd() + "/test/student.csv"), mode="rt", encoding="utf-8") as stu_infos:
    for stu_info in stu_infos:
        name, age, addr = stu_info.strip().split(",")
        root.append(create_student_info(name, age, addr))


tree = ET.ElementTree(root)
tree.write(os.path.join(os.getcwd() + "/test/studentInfos.xml"), encoding="utf-8", short_empty_elements=False)
  • studentInfos.xml

    <studentInfos>
        <student desc="学生信息">
            <name>李四</name>
            <age desc="Data legitimacy">18</age>
            <address>四川省成都市</address>
        </student>
        <student desc="学生信息">
            <name>田六</name>
            <age desc="Data legitimacy">20</age>
            <address>四川省德阳市</address>
        </student>
        <student desc="学生信息">
            <name>王五</name>
            <age desc="Data legitimacy">27</age>
            <address>四川省南充市</address>
        </student>
        <student desc="学生信息">
            <name>Tom</name>
            <age desc="Data legitimacy">38</age>
            <address>NewYork</address>
        </student>
    </studentInfos>
    
5.Excel格式文件
  • Python内部未提供处理Excel文件的功能,需要按照第三方的模块来处理

    pip3 install openpyxl
    
1.读Excel
  • 读sheet

    from openpyxl import load_workbook
    
    # #sheet
    # 获取C盘根目录的
    # c_drive = os.path.join(os.environ['SystemDrive'])
    
    # 获取其他盘根目录
    # try:
    #     d_drive = os.path.join('D:\\', '')
    #     print(d_drive)
    # except OSError:
    #     print("D盘不存在!")
    
    wb = load_workbook(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试.xlsx"))
    # 获取excel文件中的所有sheet名称
    print(wb.sheetnames)  # ['学生信息', '商品价格']
    
    # 指定sheet,基于指定的sheet获取指定位置数据
    sheet = wb[wb.sheetnames[0]]  #  wb['学生信息']  等效
    cell = sheet.cell(2, 2)
    print(cell.value)  # username
    
    # 指定sheet,基于索引位置
    sheet = wb.worksheets[0]
    cell = sheet.cell(2, 2)
    print(cell.value)  # username
    
    
    # 循环所有的sheet
    for name in wb.sheetnames:
        sheet = wb[name]
        cell = sheet.cell(2, 2)
        '''
            username
            名称
        '''
        print(cell.value)
    
    for sheet in wb.worksheets:
        cell = sheet.cell(2, 2)
        print(cell.value)
    
    
    for sheet in wb:
        cell = sheet.cell(2, 2)
        print(cell.value)
    
  • 读sheet中单元格的数据

    from openpyxl import load_workbook
    from openpyxl.worksheet.merge import MergedCellRange
    
    # 读取sheet中单元格的数据
    # 获取第n行第n列的单元格(单元格计算是1开始)
    cell = wb.worksheets[0].cell(1, 1)
    # 单元格的值
    print(cell.value)
    # 单元格的样式
    print(cell.style)
    
    # 单元格的字体
    print(cell.font)
    # 单元格的单元格中文本的对齐方式
    print(cell.alignment)
    
    # 获取某一个单元格
    value = wb.worksheets[0]['A2'].value
    print(value)  # uid
    
    value = wb.worksheets[0]['D4'].value
    print(value)  # 56
    
    
    # 获取n行所有单元格
    for cell in wb.worksheets[0][2]:
        print(cell.value)
    
    
    # 获取行的数据(获取某一列的数据)
    for row in wb.worksheets[0].rows:
        print(row[0].value, row[1].value)
    
    
    # 获取所有列的数据(获取某一行的数据)
    for col in wb.worksheets[0].columns:
        print(col[1].value)
    
    
    # 读合并单元格
    for row in wb.worksheets[1].rows:
        print(row)
    
    
    for item in sorted(wb.worksheets[1].merged_cells.ranges):
        if wb.worksheets[1].cell(1, 2).coordinate in item:
            print(item.start_cell.value)
    
2.写Excel
  • 原文件基础上写内容

    # 写Excel
    # 修改单元格数据
    sheet = wb.worksheets[1]
    cell = sheet.cell(2, 4)
    cell.value = "生产产地"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试修改.xlsx"))
    
  • 新创建Excel文件写内容

    from openpyxl import load_workbook, workbook
    from openpyxl.styles import Alignment, Border, Side, Font, PatternFill, GradientFill
    
    # 创建Excel且默认会创建一个sheet(名称为Sheet)
    wb = workbook.Workbook()
    # 或 sheet = wb["Sheet"]
    sheet = wb.worksheets[0]
    # 找到单元格,并修改单元格的内容
    cell = sheet.cell(1, 1)
    cell.value = "测试参数"
    
    # 将Excel表保存到指定位置
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    '''
    insert_rows(idx, amount=1)
        - idx 插入位置的行索引,新的行被插入到这个行之前
        - amount 要插入的行数,默认值为1
    insert_cols(idx, amount=1)
        - idx 插入位置的列索引,新的行被插入到这个列之前
        - amount 要插入的列数,默认值为1
    delete_rows(idx, amount)
        - idx 要删除的第一行的索引
        - amount 要删除的行数,默认值为1
    delete_cols(idx, amount)
        - idx 要删除的第一列的索引
        - amount 要删除的列数,默认值为1
    '''
    
    # 添加2行
    # sheet.insert_rows(2, amount=2)
    # 删除2行
    # sheet.delete_rows(1, amount=2)
    # 删除2列
    # sheet.delete_cols(1, amount=1)
    # 保存
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    
    # 修改sheet名称
    wb.worksheets[0].title = "测试表格"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 创建sheet并设置sheet颜色
    sheet = wb.create_sheet("工作计划", 0)
    sheet.sheet_properties.tabColor = "1072BA"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 设置默认打开的sheet
    wb.active = 1
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 拷贝sheet
    new_sheet = wb.copy_worksheet(wb["工作计划"])
    new_sheet.title = "新的工作计划"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 删除sheet
    del wb["测试表格"]
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 获取某些单元格,修改值
    cell_list = wb.worksheets[0]["B2":"C3"]
    for row in cell_list:
        for cell in row:
            cell.value = "测试值"
    
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 对齐方式
    '''
        horizontal,水平方向对齐方式 general, left, center, fill, justify, centerContinuous, distributed
        vertical,垂直方向对齐方式 top, center, bottom, justify, distributed
        text_rotation,旋转角度
        wrap_text,是否自动换行
    '''
    cell = wb.worksheets[0].cell(2, 2)
    cell.alignment = Alignment(horizontal="center", vertical="center", textRotation=45)
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 边框
    '''
    side的style有一下这些
        - dashDot','dashDotDot', 'dashed','dotted','double','hair', 'medium', 'mediumDashDot', 'mediumDashDotDot','mediumDashed', 'slantDashDot', 'thick', 'thin'
    '''
    cell = wb.worksheets[0].cell(2, 3)
    cell.border = Border(
        top=Side(style="thin", color="FF86C1"),
        bottom=Side(style="dashed", color="FFB6C1"),
        left=Side(style="dashed", color="FEB6C1"),
        right=Side(style="dashed", color="F86CC1"),
        # 对角线
        diagonal=Side(style="thin", color="48DF51"),
        # 对角线的方向
        # 左下 ~ 右上
        diagonalUp=True,
        # 左上~ 右下
        diagonalDown=True
    
    )
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 字体
    cell = wb.worksheets[0].cell(3, 2)
    cell.font = Font(name="微软雅黑", size=12, bold=True, color="EF23EE", underline="single")
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 背景色
    cell = wb.worksheets[0].cell(3, 3)
    cell.fill = PatternFill(start_color="EE86C1", end_color="FF86E2", fill_type="solid")
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 渐变背景色
    cell = wb.worksheets[0].cell(2, 2)
    cell.fill = GradientFill("linear", stop=("FFFFFF", "99CCFF", "000000"))
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 宽高(索引从1开始)
    wb.worksheets[1].row_dimensions[1].height = 30
    wb.worksheets[1].column_dimensions['B'].width = 40
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 合并单元格
    wb.worksheets[1].merge_cells("B2:C5")
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 取消合并单元格
    wb.worksheets[1].unmerge_cells("B2:C5")
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    
    # 写入公式
    wb.worksheets[0]["D1"] = "合计"
    wb.worksheets[0]["D2"] = "=SUM(D3:D5)"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 移动
    wb.worksheets[1]["E3"] = "总计"
    wb.worksheets[1]["E4"] = "=A2*B4"
    wb.worksheets[1]["E5"] = "=SUM(A2,C4)"
    # 将A2:E5范围的数据,向右移动10个单元格,向下移动1个单元格
    wb.worksheets[1].move_range("A2:E5", cols=10, rows=1, translate=True)
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 打印区域
    wb.worksheets[1].print_area = "A2:E5"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
    # 打印时,每个页面的固定表头
    wb.worksheets[1].print_title_cols = "A:D"
    wb.worksheets[1].print_title_rows = "1:3"
    wb.save(os.path.join(os.environ['SystemDrive'], "/Users/梁/Desktop/测试新表输入.xlsx"))
    
6.压缩文件
  • 见上文shutil
7.补充知识
1.深浅拷贝
1.浅拷贝
  • 不可变类型,不拷贝

    • 由于python内部优化机制,内存地址是相同的;对于不可变类型而言,以后修改值,会重新创建一份数据。不会影响原数据
      
import copy

string = "Ailke"
print(id(string))  # 2674432039728

cstr = copy.copy(string)
print(id(cstr))  # 2674432039728


object_list = ["Ailke", "root", [45, 23]]
print(id(object_list))  # 2437294345408
print(id(object_list[2]))  # 2437296306752

copy_object_list = copy.copy(object_list)
print(id(copy_object_list))  # 2437296306496
print(id(copy_object_list[2]))  # 2437296306752
  • 可变类型,只拷贝第一层

    object_list = ["Ailke", "root", [45, 23]]
    print(id(object_list))  # 2437294345408
    print(id(object_list[2]))  # 2437296306752
    
    copy_object_list = copy.copy(object_list)
    print(id(copy_object_list))  # 2437296306496
    print(id(copy_object_list[2]))  # 2437296306752
    
2.深拷贝
  • 不可变类型,不拷贝

    strs = "Ailke"
    print(id(strs))  # 1769370573616
    
    copy_strs = copy.deepcopy(strs)
    print(id(copy_strs))  # 1769370573616
    
  • 特殊的元组

    • 元组元素中无可变类型,不拷贝

      tup_list = ("Ailke", "root",)
      print(id(tup_list))  # 2283265800896
      
      copy_tup_list = copy.deepcopy(tup_list)
      print(id(copy_tup_list))  # 2283265800896
      
    • 元素中有可变类型,找到所有[ 可变类型 ]或[ 含有可变类型的元组 ] 均拷贝一份

      tup_list = ("Ailke", "root", [11, [44, 55], (11, 22), (11, [], 22), 33])
      copy_tup_list = copy.deepcopy(tup_list)
      
      print("分割线".center(30, "#"))
      print(id(tup_list))  # 2219888325184
      print(id(copy_tup_list))  # 2219888318080
      
      print(id(tup_list[2]))  # 2219886650944
      print(id(copy_tup_list[2]))  # 2219887055424
      
      print(id(tup_list[2][1]))  # 2219886331968
      print(id(copy_tup_list[2][1]))  # 2219887012608
      
      print(id(tup_list[2][2]))  # 2219886197568
      print(id(copy_tup_list[2][2]))  # 2219886197568
      
      print(id(tup_list[2][3]))  # 2219888325504
      print(id(copy_tup_list[2][3]))  # 2219888318016
      
  • 可变类型

    • 找到所有层级的 [ 可变类型 ] 或[ 含有可变类型的元组 ] 均拷贝一份

      tup_list = ("Ailke", "root", [11, [44, 55], (11, 22), (11, [], 22), 33])
      copy_tup_list = copy.deepcopy(tup_list)
      
      print(id(tup_list[2][2]))  # 2219886197568
      print(id(copy_tup_list[2][2]))  # 2219886197568
      
      print(id(tup_list[2][3]))  # 2219888325504
      print(id(copy_tup_list[2][3]))  # 2219888318016
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值