第九章 集合set
9.1 创建集合:set()、集合生成式
- 一种是直接把一对元素用花括号括起来
- 一种是使用set()工厂函数
- 集合生成式
1.set()
例1
set1 = set([1,2,3,4,5,6]) #将list转换成set print(set1) print(type(set1))
{1, 2, 3, 4, 5, 6} <class 'set'>
2.集合生成式
"""集合生成式,就是把列表的改成集合""" # 列表生成式 list1 = [i*i for i in range(6)] print(list1) # 集合生成式 set1 = {i*i for i in range(6)} print(set1)
[0, 1, 4, 9, 16, 25] {0, 1, 4, 9, 16, 25}
9.2 集合性质
- 集合无映射关系,也是大括号
- 集合无序,不能索引
- 集合中每个元素只出现一次
num = {} #字典 print(type(num)) num2 = {1,2,3,4,5} #集合,无映射关系 print(type(num2))
<class 'dict'> <class 'set'>
集合数据具有唯一性
num1 = {1,2,3,4,5,5,4,3,2,1} #集合数据具有唯一性,集合是无序的,不能索引 print(num1) #print(num1[2]) #错误,不可索引
{1, 2, 3, 4, 5}
例
num1 = [1,2,3,4,5,5,3,1,0] num1 = set(num1) #数据唯一,重复的自动删去 print(num1)
{0, 1, 2, 3, 4, 5}
集合中的数学操作:交集、并集、差集、对称差集
1、交集:intersection()、&
# 方法一:.intersection() s1 = {10, 20, 30, 40} s2 = {20, 30, 40, 50, 60} print(s1.intersection(s2)) # 方法二 print(s1 & s2)
{40, 20, 30} {40, 20, 30}
2、并集:union()、|
s1 = {10, 20, 30, 40} s2 = {20, 30, 40, 50, 60} # 方法一 print(s1.union(s2)) # 方法二 print(s1 | s2)
{40, 10, 50, 20, 60, 30} {40, 10, 50, 20, 60, 30}
3、差集:-
s1 = {10, 20, 30, 40} s2 = {20, 30, 40, 50, 60} print(s1.difference(s2)) # s1中不同于s2的 print(s1 - s2)
{10} {10}
4、对称差集:s1 + s2 - (s1 & d2) symmertric_difference()
s1 = {10, 20, 30, 40} s2 = {20, 30, 40, 50, 60} print(s1.symmetric_difference(s2)) # 除去两者相同的 print(s1 ^ s2)
{50, 10, 60} {50, 10, 60}
9.3 一些函数:issubset()、issuperset()、isdisjoint()
1、判断相等
s = {10, 20, 30, 40} s2 = {40, 20, 10, 30} print(s == s2)
True
2、.issubset()判断是否为子集
s = {10, 20, 30, 40} s3 = {10, 20, 30} s4 = {20, 30, 40} print(s3.issubset(s)) # 判断子集,s3是s的子集 print(s4.issubset(s))
True True
3、.issuperset()判断是否为超集
s = {10, 20, 30, 40} s3 = {10, 20, 30} print(s.issuperset(s3)) # 判断超集,s是s3的超集
True
4、isdisjoint()判断是否有交集,有交集为False
s = {10, 20, 30, 40} s3 = {10, 20, 30} print(s3.isdisjoint(s)) # 有交集为False,否则为True
False
in, not in判断集合元素
s = {10, 20, 30, 40} print(10 in s) print(50 not in s)
True True
9.4 集合增加元素:add()、update()
.add():集合添加元素
num1 = {1,2,3,4,5} num1.add(6) #添加6 print(num1)
{1, 2, 3, 4, 5, 6}
.update():可以一次添加多个
s = {10, 20, 30, 40} s.update([50]) print(s) s.update({60}) print(s)
{40, 10, 50, 20, 30} {40, 10, 50, 20, 60, 30}
9.5 集合删除元素:remove()、discard()、pop()、clear()
.remove():集合删除指定元素,如果不存在就抛出异常
num1 = {1,2,3,4,5} num1.remove(5) #移除5 print(num1)
{1, 2, 3, 4}
.discard():一次删除一个指定元素,删除没有的不会报异常
s = {10, 20, 30, 40} s.discard(10) s.discard(50) # 删除没有的不会报异常 print(s)
{40, 20, 30}
.pop():一次只删除任意一个元素,删谁不知道
不能添加参数
s = {10, 20, 30, 40} s.pop() s.pop() # 删除任意,删谁不知道 print(s)
{20, 30}
错误实例:
s.pop(10) # 不能带参数,错误代码
.clear():清空集合,清空后为空集合
9.6 创建不能修改元素的集合:frozenset()
frozen:冰冻的,冻结的
num1 = frozenset([1,2,3,4,5]) print(num1) print(type(num1)) num1.add(0) #错误,frozenset删不掉 print(num1)
frozenset({1, 2, 3, 4, 5}) <class 'frozenset'> num1.add(0) #错误 AttributeError: 'frozenset' object has no attribute 'add'
第十章 函数
什么是函数:函数就是执行特定任务和完成特定功能的一段代码
函数的作用:
- 1、复用代码
- 2、隐藏实现细节
- 3、提高可维护性
- 4、提高可读性便于调试
函数命名规则:
- 小写
- 下划线隔开单词
- 注释函数功能
10.1 函数定义:def
形参赋值默认值等号两边不要有空格
def greet_user(): """显示简单的问候语""" print("Hello!") greet_user()
Hello!
空函数
def nop(): pass
问题:pass语句什么都不做,那有什么用?
答:实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。
内嵌函数:即函数内嵌入函数
def fun1(): print('fun1正在被调用...') def fun2(): #fun2为fun1的内嵌函数 print('fun2正在被调用...') fun2() #fun1内部的函数,不可以在外部调用 fun1()
fun1正在被调用... fun2正在被调用...
10.2 闭包
def FunX(x): def FunY(y): #闭包,引用了外层函数的参数x return x*y return FunY i = FunX(8) #x=8 print(i) print(type(i)) print(i(5)) #y=5 print(FunX(8)(5)) #只能调用X,不能Y,Y为内部局部变量
<function FunX.<locals>.FunY at 0x000002C19FBCF168> <class 'function'> 40 40
例2
def Fun1(): x = [5] def Fun2(): x[0] *= x[0] return x[0] return Fun2() print(Fun1())
25
例3
def Fun1(): x = 5 def Fun2(): x *= x #x未知 return x return Fun2() print(Fun1())
错误
x *= x UnboundLocalError: local variable 'x' referenced before assignment
用函数封装代码
foods = ['苹果', '香蕉', '梨子'] # 所有的食物 my_foods = [] # 我想要的食物,初始化为空 while foods: # 遍历食物 food = foods.pop() # 删除食物列表的最后一个,变成当前我点的食物 print("我当前点的食物: " + food) my_foods.append(food) # 把当前我点的食物加到我想要的食物列表中 print("\n我所有点的食物有以下:") for my_food in my_foods: print(my_food)
我当前点的食物: 梨子 我当前点的食物: 香蕉 我当前点的食物: 苹果 我所有点的食物有以下: 梨子 香蕉 苹果
版本二: 用函数封装起来
def now_food(foods, my_foods): while foods: # 遍历食物 food = foods.pop() # 删除食物列表的最后一个,变成当前我点的食物 print("我当前点的食物: " + food) my_foods.append(food) # 把当前我点的食物加到我想要的食物列表中 def all_my_foods(my_foods): print("\n我所有点的食物有以下:") for my_food in my_foods: print(my_food) foods = ['苹果', '香蕉', '梨子'] # 所有的食物 my_foods = [] # 我想要的食物,初始化为空 now_food(foods, my_foods) all_my_foods(my_foods)
商品打折小游戏
def discounts(price,rate): #局部变量,只在定义里面 final_price = price * rate return final_price #局部变量,只在定义里面 old_price = float(input('请输入原价:')) #old_price:全局变量,不在函数内 rate = float(input('请输入折扣率:')) new_price = discounts(old_price,rate) print('打折后价格是:',new_price) #print('这是试图打印局部变量final_price的值:'final_price) #错误,局部变量
请输入原价:100 请输入折扣率:0.5 打折后价格是: 50.0
10.3 函数变量的作用域:局部、全局(global、nonlocal)
局部变量(local variable)
全局变量(global variable )
- 局部变量:在函数内定义并使用的变量,只有函数内部有效,局部变量使用global声明,这个变量就会变成全局变量
- 全局变量:函数体外定义的变量,可作用于函数内外
global:定义全局变量
count=5 def MyFun(): count=10 #局部变量 print(count) MyFun() print(count)
10 5
例2
count=5 def MyFun(): global count #定义count为全局变量,定义了则可以修改 count=10 print(count) MyFun() print(count)
10 10
nonlocal:定义非局部变量
def Fun1(): x = 5 def Fun2(): nonlocal x #定义x为非局部变量 x *= x #5*5 return x #25 return Fun2() print(Fun1())
25
10.4 实参和形参
def greet_user(username): # 形参 """显示简单的问候语""" print("Hello, " + username.title() + "!") greet_user("huzhuzhu") # 实参
Hello, Huzhuzhu!
1. 位置实参:要求实参的顺序和形参的顺序相同
def describbe_pey(animal_type, pet_name): """显示宠物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name + ".") describbe_pey('z', 'zdb')
I have a z. My z's name is zdb.
例2: 调用函数多次
def describbe_pey(animal_type, pet_name): """显示宠物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name + ".") describbe_pey('z', 'zdb') describbe_pey('pet', 'zzz')
I have a z. My z's name is zdb. I have a pet. My pet's name is zzz.
例3 :位置实参的顺序很重要
def describbe_pey(animal_type, pet_name): """显示宠物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name + ".") describbe_pey('zdb', 'z')
I have a zdb. My zdb's name is z.
2. 关键字实参
接收的是dict,关键字实参是传递给函数的名称-值对
def describbe_pet(animal_type, pet_name): """显示宠物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name + ".") describbe_pet(animal_type= 'z', pet_name= 'zdb')
I have a z. My z's name is zdb.
命名关键字实参
从这个*之后的参数,只能采用关键字实参
def person(name, age, *, city, job): print(name, age, city, job) person('Jack', 24, city='Beijing', job='Engineer') person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer Jack 24 Beijing Engineer
3. 默认实参:指定默认值的形参要放在未指定默认值的形参后面
注:提供的实参多余或少于函数完成其工作所需的信息时,将出现实参不匹配错误。
def describbe_pey(pet_name, animal_type='dog'): """显示宠物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name + ".") describbe_pey(pet_name= 'z')
I have a dog. My dog's name is z.
例2
# end的默认值为换行,这里修改为制表符 print('hello', end='\t') print('world')
hello world
默认实参为空字符,实现实参可选
例1:有中间名的情况
def get_formatted_name(first_name, middle_name, last_name): """返回整洁的姓名""" full_name = first_name + " " + middle_name + " " + last_name return full_name.title() musician = get_formatted_name('z', 'a', 'db') print(musician)
Z A Db
例2: 中间名赋值为空字符
def get_formatted_name(first_name, last_name, middle_name=' '): """返回整洁的姓名""" if middle_name: #python将没空字符串解读为True full_name = first_name + " " + middle_name + " " + last_name else: full_name = first_name + " " + last_name return full_name.title() musician = get_formatted_name('z', 'db') print(musician) musician = get_formatted_name('z', 'db', 'a') print(musician)
Z Db Z A Db
4. 任意个数参数:*
个数可变的位置实参:*args
- 定义函数时,可能无法实现确定传递的位置实参的个数时,使用可变的位置参数;结果为一个元组
个数可变的位置参数只能定义一个
def make_pizza(*toppings): """打印顾客点的所有配料""" print(toppings) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese')
('pepperoni',) ('mushrooms', 'green peppers', 'extra cheese')
例3
def calc(numbers): sum = 0 for n in numbers: sum = sum + n * n return sum print(calc([1, 2, 3])) print(calc((1, 2, 5, 7)))
14 79
例4
def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n print(sum) calc(1, 2) calc() nums = [1, 2, 3] calc(nums[0], nums[1], nums[2]) calc(*nums)
5 0 14 14
个数可变的关键字参数:**args
- 定义函数时,无法事先确定传递的关键字形参的个数,使用可变的关键字形参
- 结果为一个字典;个数可变的关键字参数也只能定义一个
# 个数可变的关键字形参 # 定义函数时,无法事先确定传递的关键字形参的个数,使用可变的关键字形参 # **arg # 结果为一个字典 # 个数可变的关键字参数也只能定义一个 def fun(**args): print(args) fun(a=10) fun(a=10, b=20, c=30)
{'a': 10} {'a': 10, 'b': 20, 'c': 30}
例2:形参**user_info中的两个星号让python创建一个名为profile的空字典,并将收到的所有名称键-值对都封装到这个字典中。
def build_profiles(first, last, **user_info): """创建一个字典,其中包含我们知道的有关用户的一切""" profile = {} # 空字典profile profile['姓'] = first # 键first name; 值first profile['名'] = last # 键last name: 值last for key, value in user_info.items(): # 遍历键值对 profile[key] = value # 把value赋值给键对应的值 return profile # 返回字典 # 调用函数 information = build_profiles('z', 'db', 性别='男', 家='南昌') print(information) #输出
{'姓': 'z', '名': 'db', '性别': '男', '家': '南昌'}
例3:可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。
而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:
def person(name, age, **kw): print('name:', name, 'age:', age, 'other:', kw) person('Bob', 35, city='Beijing') person('Adam', 45, gender='M', job='Engineer') extra = {'city': 'Beijing', 'job': 'Engineer'} person('Jack', 24, city=extra['city'], job=extra['job']) person('Jack', 24, **extra)
name: Bob age: 35 other: {'city': 'Beijing'} name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'} name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'} name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
注意:
在一个函数的定义过程中,既有个数可变的关键字形参,又有个数可变的位置形参
要求,个数可变的位置形参,放在个数可变的关键字形参之前
5. 参数小结
参数顺序问题
def fun5(a, b, *, c, d, **args): pass def fun6(*args1, **args2): pass def fun7(a, b=10, *args, **args2)
实参为列表
def greet_users(names): #names形参,对应实参usernames """向列表中的每位用户都发出简单的问候""" for name in names: #name临时参数 msg = "Hello, " + name.title() + "!" print(msg) usernames = ['hannnah', 'try', 'margot'] #实参为列表 greet_users(usernames)
Hello, Hannnah! Hello, Try! Hello, Margot!
结合使用位置实参和任意数量实参
- 如果要让函数接受不同类型的实参,必须在函数定义中接纳任意数量实参的形参放在最后。python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。
def make_pizza(size, *toppings): """概述要制作的披萨""" print("我想要个 " + str(size) + "块的手抓饼," + "我要加:") for topping in toppings: print(topping) make_pizza(16, '番茄酱') make_pizza(12, '番茄酱', '热狗', '鸡蛋')
参数组合
def f1(a, b, c=0, *args, **kw): print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw) def f2(a, b, c=0, *, d, **kw): print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw) f1(1, 2) f1(1, 2, c=3) f1(1, 2, 3, 'a', 'b') f1(1, 2, 3, 'a', 'b', x=99) f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 args = () kw = {} a = 1 b = 2 c = 3 args = () kw = {} a = 1 b = 2 c = 3 args = ('a', 'b') kw = {} a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99} a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
例2
def f1(a, b, c=0, *args, **kw): print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw) def f2(a, b, c=0, *, d, **kw): print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw) args = (1, 2, 3, 4) kw = {'d': 99, 'x': '#'} f1(*args, **kw) args = (1, 2, 3) kw = {'d': 88, 'x': '#'} f2(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'} a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}