python Ai 应用开发基础训练,字符串,字典,文件,函数,装饰品,生成器(上)

--------------------------------------    编程能是大模型应用的天花板..................................................................

所以要好好将大模型应用在企业一定要好好练好最看不起的一环,基础能力字符串处理  本文档来自老男孩培训Alex 课程记录,

我在2017年听过这个老师的课,非常不错,所以在写Ai 应用开发的时候,在基础部份会参考高手的成果

name = "my name is alex"

pring(name.caitalize())  首字母大写

pring(name.count("my"))  统计字符串出现的次数,可以是单字或多词

print(name.casefold())  这个说是转换写成小写,还会对特殊字符处理,一处理就可能不是我们想要的了,况且还有更好的相同功能的方法,所以很少少用,用不着

 pring(name.center(50,"_")) 居中打印,打印50个字符,不够用——补位

print(name.ljust(50,"***"))  左边对齐,右边的用*** 代替,补齐50位

print(name.rjust(50,'*')) 右对齐,不多的补**

print("A".lower())   大写转小写    "upp".upper()  小写转大写   

"\nAlex\n".lstrip() 左边去空格   rstip()  去掉右边  strip() 去掉空格

pring(name.encode)  编码相关,将二进制编成字节

pring(name.endswith("alex"))  是否是这个结尾 返回true 或 false

pring(name.expandtabs(tabsize = 30)) 字符串中出现的\t  等于多少个空格
pring.find("y")  找到字符串的索引取出来,用于切片时候用   那么。name[name.find("name") :])
pring(name.format(name="alex",year = 33))  格式化字符串,将字符串中的{name} 变量替换
print(name.format_map({}) 可以传一下字字賟 来格式化字符串,通常format 就够用了

pring(name.isalnum)  是不是阿拉伯数字

print (''ssss".isalpha()) 是不是纯英文

print("1A".isdecimal)  是不是只包括十进制

print("1A".isdigit) 是不是整数

title(),将字母的首字母变大写

translate 映射majetrabs   这二个方法一起使用,先用majetrabs 创建一个射映表,然后translate 转换

# 创建字符映射表
mapping = str.maketrans("aeiou", "12345")

# 使用translate()方法进行字符替换
string = "Hello, World!"
translated_string = string.translate(mapping)

print(translated_string)    输出结果是   H2ll4, W4rld!   
解释  先给aeiou  映一个其它字符,然后在使用中遇到这几个字符就替换成映射字符,比较好理解

 

 replace   替换

print("xsy".isidentifier())  是不是一个合法的变量名。支持中文英文,但是不能数字开头

print("33.33".isnumeric())是不是只有数字

"my".isprintable 是不是包括可打针印的,其实就是说这个字符中是不是非输出的法字符,说是说\n  \t 这样的字符,有制表符会返false

istitle()  是不是每个单词都 是首字母大写,单词之间有空格

join     '+++'.join(['a','b','c'])   将列表的元素用什么点连起来。

split()  将字符串切成列表

 

string = "Hello, World! How are you?"
words = string.split()
print(words)   //输出结果   ['Hello,', 'World!', 'How', 'are', 'you?']  

 

字典操作

可以将每个人的信息保存起来,比如省市县的关联信息,一个人信息这些都 可以用字典来保存,info = {"姓名":"张三"}} 有索引,有信息的元素叫做字典,

编程中叫有key和valu由于是key 是唯 一的,所以字母无序,

假设一个字典是这样子  

 

info = {
    "stu1101": "TengLan",
    "stu1102": "Loula",
    "stu1103": "Maliy"
}

name = info["stu1101"]
print(name)  # 输出: TengLan
打印这个字典方式是: for key, value in info.items(): print(key, value)

取出一个值:
print(info["stu1101"])
查找
"stu1101" in info //True
info["stu11011"] 查找这个值,但是这个值如果没有会报错,用get不会错,info.get("stu11011")

修改一个值
info["stu1101"] = "武腾兰"

删除
del info["11011"] 删除
info.pop("stu11011")
info.popitem()随便删一个
更新整个字典,可以用一个新字典更新,相同dey 覆盖,不同的增加 info.update(b)
将一个例表转换为列表 info.item()
info.formdeys([6,7,9])创建一个新字典,key 是6,7,8
c = dict.fromkeys([6, 7, 8], [1, {"name": "alex"}, 444])
c = dict.fromkeys([6, 7, 8], [1, {"name": "alex"}, 444])
运行结果是:
{
    6: [1, {"name": "alex"}, 444],
    7: [1, {"name": "alex"}, 444],
    8: [1, {"name": "alex"}, 444]
}

  以下代码是说dict.fromkeys()如果用以下方式创建的话,可以value 是一个引用的值,以后修改其中一个值,会影起其它值改变,

在这个代码段中,​c​ 是通过 ​dict.fromkeys()​ 方法创建的字典,该方法的作用是使用指定的键列表创建一个新字典,其中所有的值默认为 None 或者指定的默认值。

c = dict.fromkeys([6, 7, 8], [1, {"name": "alex"}, 444])
c = dict.fromkeys([6, 7, 8], [1, {"name": "alex"}, 444])
​
运行这段代码后,​c​ 的内容将是:

{
    6: [1, {"name": "alex"}, 444],
    7: [1, {"name": "alex"}, 444],
    8: [1, {"name": "alex"}, 444]
}
{
    6: [1, {"name": "alex"}, 444],
    7: [1, {"name": "alex"}, 444],
    8: [1, {"name": "alex"}, 444]
}
​
注意,在这个操作中,由于 ​dict.fromkeys()​ 方法创建的字典中每个键都引用同一个列表对象 ​[1, {"name": "alex"}, 444]​,因此当修改其中一个键对应的列表时,其他键对应的列表也会随之改变。这是因为它们实际上引用的是同一个对象。

如果希望每个键引用不同的列表对象,可以考虑使用以下方式创建 ​c​:

c = {key: [1, {"name": "alex"}, 444] for key in [6, 7, 8]}
c = {key: [1, {"name": "alex"}, 444] for key in [6, 7, 8]}
​
这样每个键的值都是一个新的列表对象,而不是共享同一个列表对象,指定的值实际上是同一个对象的引用。当您修改其中一个键对应的值时,因为其他键对应的值与之相同,所以会看到它们也发生了变化。

如果您希望每个键引用不同的列表对象,可以使用以下方式创建 ​c​:

keys = [6, 7, 8]
values = [1, {"name": "alex"}, 444]
c = {key: list(value) for key in keys}
keys = [6, 7, 8]
values = [1, {"name": "alex"}, 444]
c = {key: list(value) for key in keys}
​
这样每个键的值都是一个新的列表对象,而不是共享同一个列表对象。

以下是修正后的代码示例:

keys = [6, 7, 8]
values = [1, {"name": "alex"}, 444]
c = {key: list(value) for key in keys}
print(c)

c[7][1]['name'] = "Jack Chen"
print(c)  # 输出: {6: [1, {'name': 'alex'}, 444], 7: [1, {'name': 'Jack Chen'}, 444], 8: [1, {'name': 'alex'}, 444]}

keys = [6, 7, 8]
values = [1, {"name": "alex"}, 444]
c = {key: list(value) for key in keys}
print(c)

c[7][1]['name'] = "Jack Chen"
print(c)  # 输出: {6: [1, {'name': 'alex'}, 444], 7: [1, {'name': 'Jack Chen'}, 444], 8: [1, {'name': 'alex'}, 444]}
在Python中,使用 ​for i in data​遍历字典时,​i​表示的是字典的键(key),而不是键值对。这是因为字典是由键值对组成的数据结构,而在遍历时,默认情况下只遍历字典的键。如果你想同时访问键和值,
可以使用 ​data.items()​方法来遍历字典的键值对,例如:
data = {"key1": "value1", "key2": "value2", "key3": "value3"} # 遍历键值对 for key, value in data.items(): print(key, value) data = {"key1": "value1", "key2": "value2", "key3": "value3"} # 遍历键值对 for key, value in data.items(): print(key, value) ​ 输出结果: key1 value1 key2 value2 key3 value3 key1 value1 key2 value2 key3 value3

  

 案例,叫三级查询,程序运行时,先列出要查询省份名称,然后用户输出省的名称和编号进行相询,如果输入某个省的编号或省份名称,系统就列表这个省下面所有市的序号和名称 ,然后提示请输入你要查那个市 ,列出市下面所有县的编号和名称,用户可以查某一个市所有的县。在任意菜单都 可以按Q退程序,按E 返回一上级。如果没有上级则不显示,返回一级。

# 省市县数据
data = {
    "1": {"name": "浙江省", "cities": {
        "1": {"name": "杭州市", "counties": {
            "1": "西湖区",
            "2": "上城区",
            "3": "下城区"
        }},
        "2": {"name": "温州市", "counties": {
            "1": "鹿城区",
            "2": "龙湾区",
            "3": "瓯海区"
        }}
    }},
    "2": {"name": "江苏省", "cities": {
        "1": {"name": "南京市", "counties": {
            "1": "玄武区",
            "2": "白下区",
            "3": "秦淮区"
        }},
        "2": {"name": "苏州市", "counties": {
            "1": "姑苏区",
            "2": "虎丘区",
            "3": "吴中区"
        }}
    }}
}

# 显示省份列表
print("省份列表:")
for key, value in data.items():
    print("{}: {}".format(key, value["name"]))

# 用户选择省份
province_choice = input("请输入省份名称或编号进行查询:")
if province_choice.lower() == "q":
    exit()
elif province_choice.lower() == "e":
    exit()

# 根据用户选择的省份获取市信息
cities = data[province_choice]["cities"]
print("\n{} 下的市列表:".format(data[province_choice]["name"]))
for key, value in cities.items():
    print("{}: {}".format(key, value["name"]))

# 用户选择市
city_choice = input("请输入市编号进行查询,按Q退出,按E返回上一级:")
if city_choice.lower() == "q":
    exit()
elif city_choice.lower() == "e":
    exit()

# 根据用户选择的市获取县信息
counties = cities[city_choice]["counties"]
print("\n{} 下的县列表:".format(cities[city_choice]["name"]))
for key, value in counties.items():
    print("{}: {}".format(key, value))

 不同的格式和不同的思路

  

# 作者信息
__author__ = "www.51"

# 多级城市县镇村的字典数据
data = {
    '北京':{  # 北京作为一级键
        "昌平":{  # 昌平作为二级键
            "沙河":["oldboy","test"],  # 沙河作为三级键,值为列表
            "天通苑":["链家地产","我爱我家"]  # 天通苑作为三级键,值为列表
        },
        "朝阳":{  # 朝阳作为二级键
            "望京":["奔驰","陌陌"],  # 望京作为三级键,值为列表
            "国贸":{"CICC","HP"},  # 国贸作为三级键,值为集合
            "东直门":{"Advent","飞信"},  # 东直门作为三级键,值为集合
        },
        "海淀":{},  # 海淀作为二级键,值为空字典
    },
    '山东':{
        "德州":{},  # 德州作为二级键,值为空字典
        "青岛":{},  # 青岛作为二级键,值为空字典
        "济南":{}  # 济南作为二级键,值为空字典
    },
    '广东':{
        "东莞":{},  # 东莞作为二级键,值为空字典
        "常熟":{},  # 常熟作为二级键,值为空字典
        "佛山":{},  # 佛山作为二级键,值为空字典
    },
}

# 退出标志
exit_flag = False

# 主循环,根据用户输入不断展示相应的数据
while not exit_flag:
    for i in data:  # 遍历一级键
        print(i)  # 打印一级键
    choice = input("选择进入1>>:")  # 用户选择一级键
    if choice in data:  # 判断用户输入是否为一级键
        while not exit_flag:  # 进入二级键选择循环
            for i2 in data[choice]:  # 遍历二级键
                print("\t",i2)  # 打印二级键
            choice2 = input("选择进入2>>:")  # 用户选择二级键
            if choice2 in data[choice]:  # 判断用户输入是否为二级键
                while not exit_flag:  # 进入三级键选择循环
                    for i3 in data[choice][choice2]:  # 遍历三级键
                        print("\t\t", i3)  # 打印三级键
                    choice3 = input("选择进入3>>:")  # 用户选择三级键
                    if choice3 in data[choice][choice2]:  # 判断用户输入是否为三级键
                        for i4 in data[choice][choice2][choice3]:  # 遍历四级键(值)
                            print("\t\t",i4)  # 打印四级键(值)
                        choice4 = input("最后一层,按b返回>>:")  # 提示用户输入
                        if choice4 == "b":  # 如果用户输入b
                            pass  # 继续下一个循环
                        elif choice4 == "q":  # 如果用户输入q
                            exit_flag = True  # 设置退出标志为True
                    if choice3 == "b":  # 如果用户输入b
                        break  # 退出当前循环,返回上一级
                    elif choice3 == "q":  # 如果用户输入q
                        exit_flag = True  # 设置退出标志为True
            if choice2 == "b":  # 如果用户输入b
                break  # 退出当前循环,返回上一级
            elif choice2 == "q":  # 如果用户输入q
                exit_flag = True  # 设置退出标志为True

  

简化理解版本:

 文件操作

Python 3 中,文件的读写模式主要包括以下几种:

​​r​: 只读模式。若文件不存在,会发生异常。
​​w​: 只写模式。文件若存在,覆盖原有内容;若文件不存在,则创建新文件。
​​x​: 排他性创建。如果文件已存在,操作将失败。
​​a​: 追加模式。若文件存在,指针将移动到文件末尾,新的内容将被写入到已有内容之后;若文件不存在,则创建新文件。
​​b​: 二进制模式。与其他模式结合使用(如 ​rb​ 或 ​wb​)以读取或写入二进制数据。
​​t​: 文本模式(默认)。与其他模式结合使用(如 ​rt​ 或 ​wt​)以读取或写入字符串数据。
​​+​: 更新模式。与 ​r​ 或 ​w​ 结合使用,如 ​r+​ 或 ​w+​,以同时读写文件。
组合模式:

​​rb​, ​wb​, ​ab​, ​xb​: 以二进制模式读取、写入、追加、创建文件。
​​rt​, ​wt​, ​at​, ​xt​: 以文本模式读取、写入、追加、创建文件。
​​r+b​ 或 ​rb+​, ​w+b​ 或 ​wb+​, ​a+b​ 或 ​ab+​, ​x+b​ 或 ​xb+​: 以二进制模式读写、写读、追加读、创建读。
​​r+t​ 或 ​rt+​, ​w+t​ 或 ​wt+​, ​a+t​ 或 ​at+​, ​x+t​ 或 ​xt+​: 以文本模式读写、写读、追加读、创建读。
这些模式之间的主要区别在于:

读、写、追加这三种基本模式,决定了文件打开后的操作类型。
文本和二进制区别,决定了数据读写是按照字符串处理还是按照字节流处理。
排他性创建模式 ​x​ 用于在创建文件时避免覆盖已有文件。
更新模式 ​+​ 允许对文件同时进行读取和写入操作。

  

# 打开文件
file = open('file.txt', 'r')  ##示例二  with open ("info.txt", "r", encodeing="utf-8") as file  

# 读取文件内容
content = file.read()  
print(content)
# 关闭文件
file.close()
​
逐行读取文件
# 打开文件
file = open('file.txt', 'r')

# 逐行读取文件内容
for line in file:
    print(line)

# 关闭文件
file.close()
# 打开文件
file = open('file.txt', 'r')

# 逐行读取文件内容
for line in file:
    print(line)

# 关闭文件
file.close()
​
写入文件
# 打开文件(如果文件不存在则会创建)
file = open('new_file.txt', 'w')

# 写入内容到文件
file.write('Hello, World!')

# 关闭文件
file.close()
# 打开文件(如果文件不存在则会创建)
file = open('new_file.txt', 'w')

# 写入内容到文件
file.write('Hello, World!')

# 关闭文件
file.close()
​
追加内容到文件
# 打开文件
file = open('existing_file.txt', 'a')

# 追加内容到文件
file.write('\nAppending new content.')

# 关闭文件
file.close()
# 打开文件
file = open('existing_file.txt', 'a')

# 追加内容到文件
file.write('\nAppending new content.')

# 关闭文件
file.close()

# file.detach(self) 底层方法,能分离缓冲区,可以在运行中指定编码,我们用不上,

   # f. encoding   输出文件编码

  # f.errors    内部处理异常 ,我们用不上   

  # f.lileno()   返回文件在内存中的编号,我们用不上,操作系统内部动作,我们用不上,

  # f.name  打印文件名    

# f.flush()  刷新缓冲区,确保也写入

 

  文件读取的时候readlines  是按行读取整个文件,如果读取还要记录行号的,可以用枚举方式。读取文件也可以用for line in f:

这样的话它行一行一行的读,最节约内存,

f = open("infotxt.txt","r",encoding="utf-8")
for line in f.readlines():  #如果是读取时候还要有行号  for index line in enumerate(f.readlines()):
    print(line.strip())    
f.close()    
# 使用行读取,并记住行号
for line in f:
  if coun == 9:
    print("-----我是分害线----")
    coune += 1
    contine
  print(line)
  coune += 1

### 文件读取时候 f.read(50) 读取50个 f.tell()返回读到字节数



#在Python中,当你打开并读取一个文件后,文件的"光标"(即读取位置)会移动到文件的末尾。如果你尝试再次从当前位置读取内容,
因为已经是文件末尾了,所以将不会得到任何内容。这就是为什么第二次读取时候得不到内容的原因。为了重新从文件开始处读取内容,
你需要手动将文件指针(光标)重新置回到文件起始位置,可以使用 ​seek(0)​方法来完成这个任务。下面是示例代码:
with open("example.txt", "r", encoding="utf-8") as file:
    # 第一次读取全部内容
    content_first_read = file.read()
    print("第一次读取的内容:")
    print(content_first_read)
    
    # 尝试连续第二次读取内容,将读不到任何内容
    content_second_read = file.read()
    print("尝试第二次读取的内容:")
    print(content_second_read)
    
    # 重置光标到文件开头
    file.seek(0)
    
    # 第三次读取后,由于光标已重置,将可以再次读到内容
    content_third_read = file.read()
    print("重置光标后第三次读取的内容:")
    print(content_third_read)

  ##  示例一,通过文件字节数来读取示例:然后最后重置光标到0

# 打开文件
with open("example.txt", "r", encoding="utf-8") as file:
    # 读取一些内容
    content = file.read(10)
    print("读取的内容:")
    print(content)
    
    # 获取并打印当前文件的位置
    current_position = file.tell()
    print("当前文件位置:", current_position)
    
    # 继续读取一些内容
    more_content = file.read(5)
    print("继续读取的内容:")
    print(more_content)
    
    # 再次获取并打印当前文件的位置
    new_position = file.tell()
    print("新的文件位置:", new_position)
    
    # 如果需要重置光标,可以结合使用seek()和tell()
    file.seek(0)
    print("重置后的文件位置:", file.tell())

  

其它关于输出  time可以做到 延时  例:time.sleep(0.1) 我们想让计算机延时隔讲课费间打印默认情况下,由于计算机会将要打印
的结果放入缓存,仍然会一次输出, 所以我们要结合使用flush()清空缓存才能使实。

示例二,读取一个文件,每次读取一段,然后等待用户是不是要继续输出,这儿流程思是先将文件读取到内存,
然后用多线程yield方式读一行,等待调用,内存调用后在生成一行,方便节省内存。
def read_paragraphs(file_path):
    with open(file_path, 'r') as file:
        content = file.read()
        
    paragraphs = content.split('\n\n')
    
    for paragraph in paragraphs:
        yield paragraph

def main():
    file_path = 'yourfile.txt'  # 替换为你的文件路径
    try:
        for paragraph in read_paragraphs(file_path):
            print(paragraph)  # 输出段落内容
            input("按回车键继续...\n")
    except FileNotFoundError:
        print(f"未能找到文件:{file_path}")
    except Exception as e:
        print(f"读取文件时发生错误:{e}")

if __name__ == "__main__":
    main()  

文件编码转码和编码,在Python 3中,默认的字符串类型已经是Unicode了,所以大多数情况下,除非涉及I/O操作,
通常不需要手动对其进行编码或解码。
# 字符串
s = "你好世界"

# 将字符串编码为UTF-8格式字节流
encoded_s = s.encode('utf-8')
print(encoded_s)  # 输出编码后的字节序列​
输出示例:
b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'​
​​'utf-8'​是最常用的编码格式,可以很好地兼容ASCII并支持非常广泛的字符集。

解码 (Decoding)
对标编码,解码是通过已知的编码格式,将字节序列转换回相应的字符串的过程。如果接收到的数据是字节序列(如从文件读取或者网络接收),而你需要处理它作为文本,则需要进行解码。
# 假设我们从某处得到了一个UTF-8编码的字节序列
encoded_s = b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'

# 将字节序列解码回字符串
decoded_s = encoded_s.decode('utf-8')

print(decoded_s)  # 输出解码后的字符串
# 假设我们从某处得到了一个UTF-8编码的字节序列
encoded_s = b'\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'

# 将字节序列解码回字符串
decoded_s = encoded_s.decode('utf-8')
print(decoded_s)  # 输出解码后的字符串​
输出示例:
你好世界
你好世界
​
编码和解码时使用的字符集必须匹配,否则可能导致错误,如乱码或抛出 ​UnicodeDecodeError​异常。

  python 参数有几种类型,除了位置参数是必传,其它参数是非必传  附: 如果函数的参数接收一个函数做参数,叫做高阶函数

位置参数 (Positional arguments)

这是最常见的参数类型。它们在函数定义中按照声明的顺序接收传递给函数的值。
如:​def func(a, b):​ 那么调用 ​func(1, 2)​ 时,参数 a 的值为 1,参数 b 的值为 2。
关键字参数 (Keyword arguments)

允许在调用函数时通过“键-值”对形式明确指定参数值。
如:​def func(a, b):​ 可以使用 ​func(b=2, a=1)​,不必遵循位置顺序。
默认参数 (Default parameters)

在定义函数时,可以为参数提供默认值。如果调用者没有传递该参数,则使用默认值。
如:​def func(a, b=2):​ 调用 ​func(1)​ 时,默认参数 b 将使用其默认值 2。
可变长位置参数 (Arbitrary positional arguments)

使用星号 * 来接受任意数量的位置参数,这些参数会被包装进一个元组。
如:​def func(*args):​ 则 ​func(1, 2, 3)​ 中的 1, 2, 3 会作为一个元组 (1, 2, 3) 传递给 args。
可变长关键字参数 (Arbitrary keyword arguments)

使用双星号 ** 来接受任意数量的关键字参数,这些参数会被包装成一个字典。
如:​def func(**kwargs):​ 调用 ​func(a=1, b=2)​ 时,参数 a 和 b 会存储在一个名为 kwargs 的字典中。
强制关键字参数 (Keyword-only arguments)

在可变长位置参数后定义的参数,或者在仅有星号(*)后定义的参数,将被当作关键字参数,在调用时必须明确指明参数名。
如:​def func(*args, c):​ 或者 ​def func(*, c):​ 要求参数 c 必须使用关键字方式指定。
仅位置参数 (Positional-only arguments)

在 Python 3.8+ 中,可以使用 / 符号之前的参数定义为仅限位置的参数,意味着在调用时只能按照位置来传递这些参数,不能使用关键字。
如:​def func(a, b, /, c):​ 这里 a 和 b 是仅位置参数,而 c 是既可以按位置传递也可以作为关键字参数传递。
每种参数类型都有其应用场景和优势。例如,关键字参数提高了代码的可读性,而默认参数使得函数更加灵活。可变长参数允许我们创建更加通用和灵活的函数,而强制关键字参数则能够确保函数的调用更清晰和更易于维护。适当地使用这些参数类型可以编写出高质量且易于理解的代码。

 简单示例,以下将所以参数写上,请认真分析具体使用:假设一个函数定义成以下样子
        def test4(name,age=18,*args,**kwargs):       

   test4​函数的参数定义了四种类型的参数:

  1. ​name​: 位置参数。
  2. ​age​: 带有默认值的关键字参数(也可以作为位置参数传入)。
  3. ​*args​: 可变长位置参数,接收多余的位置参数,存储为元组。
  4. ​**kwargs​: 可变长关键字参数,接收多余的关键字参数,存储为字典。

        调用这个函数时,你需要至少提供一个 ​name​参数,而 ​age, *args​和 ​**kwargs​是可选的。下面是几种不同方式的调用示例:

       

# 仅提供必需的位置参数
test4('Alice')

# 提供位置参数和默认关键字参数
test4('Bob', 20)

# 提供所有类型的参数
test4('Carol', 25, 'female', 'developer', city='New York', country='USA')

# 使用关键字参数的方式来指定'age'参数,其余为可变长参数
test4(name='Dave', age=30, '6 feet tall', hobby='basketball', nationality='Canadian')

# 只提供一个额外的位置参数和一个额外的关键字参数
test4('Eve', 22, 'singer', favorite_color='blue')

  

 局部变量:

在Python中,全局变量确实可以在函数内部被访问,但是直接修改全局基本数据类型(如整数和字符串)的值会导致出现意外行为,除非使用 ​global​ 关键字。对于不可变类型(包括字符串、整数、布尔值、元组等),

果你在函数内部尝试直接修改它们,那么实际上你会创建一个同名的新的局部变量,而不是改变全局变量的值。如果你想修改全局变量的值,需要在函数内部明确声明该变量为全局变量,用到关健字:global  这样才能在函数内部对其进行修改。

以下是一个展示如何修改全局变量的示例:

# 全局变量
school = "xsy"
number = 10

def change_global_var():
    global school
    global number
    # 现在可以改变全局变量的值了
    school = "zy"
    number = 20
    print("Inside function:", school, number)

# 在函数调用前打印原始值
print("Before function call:", school, number)

# 调用函数,预期会修改全局变量的值
change_global_var()

# 在函数调用后打印新的值
print("After function call:", school, number)

# 调数调用前输出   Before function call: xsy 10
# 函数内输出   Inside function: zy 20
#  函数后输出  After function call: zy 20    ### 这儿也经修改了

  但是对于字典,列表,集合,之类可以在内部直接修改的  以下示例,附带一句,元组是不可以修改,在任何地方都 不能修改

# 全局变量
school = "0ldboy edu."
# 名称列表
names = ["Alex", "Jack", "Rain"]
# 定义函数来修改名称列表中的第一项
def change_name():
    global names
    # 这里需要确保我们修改的是全局变量中的列表
    names[0] = "金角大王"
    print(names)
# 调用函数
change_name()

 如果字符串的内容是一个正常的字典,可以用eval(str) 转换   b = eval(str)

python函数

  python 函数取变量

在Python中,函数是一段组织好的、可重复使用的、用来实现单一或关联功能的代码块。函数可以提高应用的模块化和代码的重复利用率。

定义函数

在Python中,使用关键字 ​def​来定义一个函数,后面跟上函数名称和圆括号()。圆括号之间可以用来定义参数。函数的第一行可以选择性地使用文档字符串—用于存放函数说明。函数内容以冒号起始,并且缩进。return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return等于返回 None。

def greet(name):
    """这是一个打招呼的函数"""
    return "Hello, " + name + "!"

 

调用函数

通过函数名调用函数,如果你定义了一个参数,那么在函数调用时就需要传递相应的参数。

greeting = greet("Alice")
print(greeting)  # 输出: Hello, Alice!

  

参数传递

函数调用时,有几种方式可以传递参数:

  1. 位置参数 (positional arguments): 这些参数需要按照参数在函数定义中的位置来传递。
  2. 关键字参数 (keyword arguments): 当函数调用时,关键字参数被关联到函数中的形参,可以不考虑参数的顺序。
  3. 默认参数 (default parameters): 在定义函数时,可以为参数提供默认值。在调用函数时如果未传递,则使用默认值。
  4. 可变参数 (*args and **kwargs): 允许你传入不定数量的参数。其中,*args 是用来发送一个非键值对的可变数量的参数列表给一个函数,**kwargs 允许你将不定长度的键值对, 作为参数传递给一个函数。

例子:

# 使用位置参数
def foo(animal, name):
    print(animal)
    print("My " + animal_type + "'s name is " + name+ ".")
#调用函数如下 foo('a', 'b') # 使用关键字参数,有些类同默认参数,但是它是按字典放在内存中的,非必须传参, describe_pet(animal='dog', name='willie') # 使用默认参数 def describe_pet(name, animal='dog'): print("\nI have a " + animal + ".") print("My " + animal + "'s name is " + name.title() + ".") #name.title()首字母大写 #这儿由于animal_type有默认传参所以可以不传,采用默认就要可以 describe_pet(pet_name='willie') # 使用 *args 和 **kwargs def make_pizza(*toppings, **pizza_info): print("\输入打印:") for topping in toppings: #输出一个*的变量 print("- " + topping) for key, value in pizza_info.items(): #输出二个**的变量样子 print(key + ": " + str(value)) #调用这个这个函数,先给他模拟传一下值 make_pizza('pepperoni', 'mushrooms', size='large', crust='thick')

局部变量与生命周期
函数在内部定的变量和函数在外面不能访问,在变量中可以加globle, 函数参数在代码中也可以理解一个变量,

 

 高阶函数介绍
1什么叫高阶函数,把一个函数当实参,2 返回值包含函数名,

官方解释:
1,接受一个或多个函数作为输入 2,输出一个函数,不修改函数的调用方式
这意味着高阶函数对于函数式编程来说非常重要,因为它们可以接收函数作为参数,或者将函数作为结果返回。在Python中,函数是一级对象,
这意味着函数可以作为参数传递给其他函数,可以作为返回值,还可以赋值给变量。

import time

# 定义一个装饰器
def timer_decorator(function):
    def wrapper(*args, **kwargs):
        start_time = time.time()  # 记录当前时间
        result = function(*args, **kwargs)  # 调用原始函数
        end_time = time.time()  # 记录当前时间
        print(f"{function.__name__} ran in: {end_time - start_time} sec")
        return result
    return wrapper

# 使用装饰器
@timer_decorator
def some_function(delay_time):
    """模拟耗时操作的函数"""
    time.sleep(delay_time)
    print("Function completed")

some_function(3)

  

以上代吗的装饰器等于是让调用新函数时,将以前的函数作作参传进来,由于新函数的返回是一个函数,它就是旧函数,所以在这儿解决的过程是函数内套一个函数,将参数放在内套的函数内,但是作为装饰器自身也需要参数,所以得内套函数在套一层,请从代码中分析:

  

  生成器和迭代器

(一:生成器)

我们平时做实例的时候的数据,或者后端返回的数据是自己写的或由后端返回的,但是python 除了做后端,还用于科学计算,有时候我们要模拟的数据可以需要生成,通过某个规则生成,以前的方式也可以解决生成,不过叫做生成式,不叫生成器。传统列表生成式也可以生成数据:生成器除了解决生成还可以解决内存优化,

 

传统方式:举一个简单的例子,假设我们想要创建一个包含0到9的平方数的列表:
squares = [x**2 for x in range(10)]
print(squares)
# 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  我们也可以加入条件来过滤出仅当x是偶数时的平方数:列表推导是Python编程中非常强大的工具之一,让代码更加简洁易读。
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)
# 输出: [0, 4, 16, 36, 64]
 还可以用函数来处理一下生成的数据  [func(i) for i in range(10)] 

生成器提供了一种方式,可以在需要时逐个按需计算元素,而不是像列表那样一次性地生成整个列表。当处理的元素数量非常大,或者不确定要处理多少元素时,使用生成器能有效节省内存资源。例如,如果你创建一个包含百万级别元素的列表,将会占用相当多的内存,尤其是当你只需要访问列表中前几个项的时候。大部分列表项将不必要地消耗内存空间。生成器就是为了解决这个问题而出现的,它允许我们通过迭代的方式逐步推导出每个元素,而不需要预先在内存中构造出整个列表。

在Python中创建生成器的一种方法是使用列表推导的语法结构,将列表推导的方括号 ​[]​替换为圆括号 ​()​,即可定义一个生成器。

比如,以下代码创建了一个简单的生成器:

my_generator = (x**2 for x in range(10)) 
在Python2.7中,使用生成器表达式创建的 ​my_generator​是一个迭代器,你无法直接通过索引来访问特定元素。但你可以通过迭代获取到第二个元素。

下面是一个简单的方法,使用 ​next()​函数来获取生成器的下一个元素:在python2.7中使用next()    新版本python3.+是__next__
my_generator = (x**2 for x in range(10)) # 获取第一个元素 first_element = next(my_generator) # 获取第二个元素 second_element = next(my_generator) print(second_element) # 结果为1,因为 1**2 等于 1 my_generator = (x**2 for x in range(10)) # 获取第一个元素 first_element = next(my_generator) # 获取第二个元素 second_element = next(my_generator) print(second_element) # 结果为1,因为 1**2 等于 1 ​ 此方法调用两次 ​next()​,第一次获取并丢弃第一个元素,第二次才获取我们需要的第二个元素。 另外,如果你需要频繁地访问生成器的多个元素,你可能需要考虑使用列表(如果内存允许)。列表允许你直接通过索引访问元素。当然,这会失去使用生成器的内存高效性。例如: # 如果生成器表达式中的元素数量较小,且对内存不敏感,可以考虑转换为列表 my_list = list(x**2 for x in range(10)) # 直接访问第二个元素(索引为1,因为索引是从0开始的) second_element = my_list[1] print(second_element) # 如果生成器表达式中的元素数量较小,且对内存不敏感,可以考虑转换为列表 my_list = list(x**2 for x in range(10)) # 直接访问第二个元素(索引为1,因为索引是从0开始的) second_element = my_list[1] print(second_element)

  

生成器非常强大。其可以用来处理一些复杂的推算算法,这些算法可能无法通过常规的列表生成式或循环来实现。

例如,斐波那契数列是一个著名的例子,除了第一个和第二个数外,任意一个数都是由前两个数相加得到的。在使用列表生成式时无法直接表达该序列,但是我们可以使用函数来生成并打印出斐波那契数列:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n += 1
    return 'done'

fib(10)
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n += 1
    return 'done'

fib(10)
​
在上述代码中,我们定义了一个函数 ​fib()​,它接受一个参数 ​max​,表示要打印的斐波那契数列的最大值。通过使用 ​while​循环及赋值语句,我们可以不断地计算并打印下一个斐波那契数。函数返回一个字符串作为结束标志。

注意,在赋值语句 ​a, b = b, a + b​中,我们利用了元组的特性来同时更新 ​a​和 ​b​的值。这相当于将当前的 ​b​赋给 ​a​,并将当前的 ​a+b​赋给 ​b​。

通过调用 ​fib()​函数并传入适当的参数,我们可以打印出指定范围内的斐波那契数列。  

 

posted @ 2024-03-09 16:18  稷下元歌  阅读(67)  评论(0编辑  收藏  举报