Python编程从入门到实践(第二版)_五六七八九

Python编程从入门到实践(第二版)_五六七八九

image-20230327082939406

五、IF语句

  • IF的作用:检查程序当前的状态,并采取相当的措施
  • 每条if语句的核心都是一个值为true或false的表达式,这种表达式称为条件测试,根据条件的值为true或false来决定是否执行if语句当中的代码,如果为真则执行,反之则忽略。
# 小案例
# 宝马全大写,其它的仅首字母大写
cars = ['bmw','audi','subaru','toyota']
for car in cars:
    if car == 'bmw':
        print(car.upper())
    else:
        print(car.title())
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
BMW
Audi
Subaru
Toyota

条件测试

# 检查格式是否相等
car = 'bmw'
print(car == 'bmw')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
True

car = 'bmw'
print(car == 'bmww')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
False

# 检查相等时是否忽略大小写,严格区分大小写
car = 'bmw'
print(car == 'BMW')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
False

# 如果想忽略大小写,怎么搞?直接使用lower这种小写函数
# 网站类型的方法检查用户输入的数据是否符合特定值,比如说那种带图的校验码
# 检验码当中大小写并不重要
car = 'BMw'
print(car.lower() == 'bmw')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
True

大小写转换的另一种应用,当用户在网站上创建用户名的时候,无论它输入的是什么,我们都将其转换成为小写,然后将数据库当中所有的用户也变成小写,做对比,如果对比成功了,那用户就重复了,提示用户此用户已经有人使用,让用户重新输入。

# 检查值是否不相等
panda = 'heye'
if panda != 'hehua':
    print("heye not hehua")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
heye not hehua
# 正确理解and和or
# 在条件测试当中使用and,就要求所有的条件都满足之后才是真
# 在条件测试当中使用or,就要求所有的条件只满足一个就是真
age_1 = 18
age_2 = 21
print(age_1 ==18 and age_2 == 21)
print(age_1 ==18 and age_2 == 99)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
True
False

age_1 = 18
age_2 = 21
print(age_1 ==18 or age_2 == 21)
print(age_1 ==18 or age_2 == 99)
print(age_1 ==88 or age_2 == 99)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
True
True
False
# 检查特定的值是否包含在列表当中
## 方法一
pandas = ['heye','hehua','fubao','xiangxiang']
japan_panda = 'xiangxiang'
for panda in pandas:
    if panda == japan_panda:
        print("xiangxiang online")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
xiangxiang online

## 方法二,在if当中直接使用in关键字即可
pandas = ['heye','hehua','fubao','xiangxiang']
if 'xiangxiang' in pandas:
    print("xiangxiang online!")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
xiangxiang online!

# 检查特定值是否不包含在列表中,使用not in关键字
china_pandas = ['heye','hehua']
if 'xiangxiang' not in china_pandas:
    print("xiangxiang not in china".title())
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Xiangxiang Not In China

布尔表达式只不过是条件测试的别名而已,与条件表达式一样,布尔表达式的结果要么为true,要么为false

IF语句

IF语句有很多种,而且第一种都会有其应用的场景:

  1. 仅一个IF条件判断,比如判断一个某个元素是否存在于某列表当中,存在就打印,反之,不返回任何消息,这种情况下,仅使用一个IF条件判断就好。
  2. IF+else条件判断,大家要注意这一种,应用尽量少用,因为一旦不满足前面的条件,就会使用else当中的条件,这个范围太大了,有可能会被黑客利用,传递一些非法值。
  3. IF+elif,不加else,这一种我们可以看做是if+else的安全版,elif里面也有明确的条件,if里面也有明确的条件,只有条件满足才会执行动作,这样范围更小,更安全。
  4. 大家使用了if、elif、else之后不要看不起单独的if,但实际上单独的if应用场景也是很多,你想一下,当你把if+elif+else放到一起时,其实只会判断完成之后执行一种,而多条件并列if会检查所有的条件,所以当你想检查多个条件时,请使用多条件并列判断。比如说,当我们从国外把熊猫接回中国后,我们要检查它的身体健康,血糖、血压、精神状态,骨骼等等,这种都要必须要检查的,而不是仅检查一种,所以这种情况下使用并且if其实更好,下文当中有演示。

IF语句有很多种,选择使用哪种取决于要测试的条件数。

# 仅一个IF条件,判断荷花是否在线
pandas = ['hehua','heye']
panda = 'hehua'
if panda in pandas:
    print(f"{panda} online!")
# if+else条件,else的范围太大,不安全
janpan_panda = ['xiangxiang']
if 'xiangxiang' in janpan_panda:
    print('xiangxiang is in japan!')
else:
    print('xiangxiang is in china!')
# 使用if+elif,精确匹配条件,缩小匹配范围
janpan_panda = ['']
china_panda = ['hehua','heye','xiangxiang']
if 'xiangxiang' in janpan_panda:
    print('xiangxiang is in japan!')
elif 'xiangxiang' in china_panda:
    print('xiangxiang is in china!')
# 根据不同的年龄段买票
# 写法一
age = 17
if age <=12:
    print("Ticket price:25$")
elif age <= 18:
    print("Ticket price:40$")
else:
    print("Ticket price:60$")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Ticket price:40$
## 上述案例,其实可以写的更简单,直接使用一个print,如下所示:
age = 17
if age <=12:
    price = 25
elif age <= 18:
    price = 40
else:
    price = 60
print(f'Ticket price:{price}$')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Ticket price:40$
# 并列IF,所有的条件都要检测 
panda = 'fubao'
if 'xueya' > 100:
    print(f'{panda} xueya too high!')
if 'xuezhi' > 88:
    print(f'{panda} xuezhi too high!')
if 'xintao' > 888:
    print(f'{panda} xintiao too high!')

总之,,如果想仅执行一个代码块,那就用if-elif-else结构,如果需要执行多个代码块,即多个条件,就使用一系列独立的if语句。

IF语句处理列表

# 确定列表非空
# 其实非常简单,我们只需要在IF后直接写上列表的名字即可
# 非空是为真
panda = ['hehua']
if panda:
    print("not null!")
else:
    print("List is null")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
not null!
---
panda = []
if panda:
    print("not null!")
else:
    print("List is null")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
List is null
# 检查特殊的元素
# 顾客去水果店下单买水果,我们需要给顾客打印一个发票,里面有顾客购买的水果列表
fruits = ['apple','banana','orange']
for fruit in fruits:
    print(fruit)
print("finished!")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
apple
banana
orange
finished!

# 如果店里面没橘子了,程序怎么修改呢?
# 这个程序好像是超意兴的点餐系统的意思
fruits = ['apple','banana','orange']
null_fruit = 'orange'
for fruit in fruits:
    if fruit == null_fruit:
        print(f'sorry,{null_fruit} is null!')
    else:
        print(fruit)
print("finished!")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
apple
banana
sorry,orange is null!
finished!
# 双列表对比
# fruits代表一共这么多水果,customer_fruits客户点了这么几个
fruits = ['apple','banana','orange','tomato','pear']
customer_fruits = ['apple','banana','egg']
for customer_fruit in customer_fruits:
    if customer_fruit in fruits:
        print(f'{customer_fruit} OK!')
    else:
        print(f'{customer_fruit} srooy!')
print("finished!")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
apple OK!
banana OK!
egg srooy!
finished!

六、字典

基础

  • 刚开始我们学习的是列表,后来又后学习不能改变的列表—-元组,现在再来学一个由列表演化而来的数据类型—-字典。
  • 字典内部存储的就是键值对
  • 键值对的范围非常大,不仅仅是普通的键值,甚至可以是一个数据集合,也就说值可以是一个列表!
  • 字典相比于列表和元组能存储的数据的维度更广,所能描述的事物就更形象和具体,字典具有非常好的兼容性,可以容纳列表,甚至在字典进而还可以再嵌套一个字典,如下所示:
panda = {'hehua':['china','sichuan',2],
         'xiangxiang':('japan','know',2),
         'fubao':{'fubao':'hanguo'},
         'heye':'china'
         }
print(panda['hehua'])
print(panda['xiangxiang'])
print(panda['fubao'])
print(panda['heye'])
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
['china', 'sichuan', 2]
('japan', 'know', 2)
{'fubao': 'hanguo'}
china
# 列表、元组和字典的打印
# 列表示例
panda = ['hehua','heye']
print(panda[0])
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
hehua

# 元组示例
panda = ('hehua','heye')
print(panda[0])
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
hehua

# 字典示例
# 注意,在打印的时候没有指定下标,而是指定是“键”,打印出来的结果是'值'
panda = {'hehua':'china',
         'xiangxiang':'japan'
         }
print(panda['hehua'])
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
china
数据结构 括号 打印目标 是否可更改 内容
列表 中括号 [ ] 下标 可更改 字符串,数字
元组 小括号() 下标 不可更改 字符串、数字
字典 花括号 可更改 值可以字符串、数字、列表、元组、字典

修改

# 字典内容的追加,非常简单,直接把字典名写上,然后再写键值,注意两者之间有等号
name = {'zhangsan':18,
        'lisi':17
        }
print(name)
name['wanger'] = 22
print(name)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'zhangsan': 18, 'lisi': 17}
{'zhangsan': 18, 'lisi': 17, 'wanger': 22}

# 与列表与元组一样,也可以从空开始,不断进行累加
name = {}
print(name)
name['wanger'] = 22
name['zhangsan'] = 24
print(name)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{}
{'wanger': 22, 'zhangsan': 24}
# 修改值
name = {'wanger': 22, 'zhangsan': 24}
print(name)
name['zhangsan'] = 27
print(name)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'wanger': 22, 'zhangsan': 24}
{'wanger': 22, 'zhangsan': 27}
# 删除键值对,直接使用del 键即可,这一点与删除列表当中值非常相似
name = {'wanger': 22, 'zhangsan': 24}
print(name)
del name["wanger"]
print(name)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'wanger': 22, 'zhangsan': 24}
{'zhangsan': 24}
# 要打印的键值没有会导致程序严重出错
name = {'wanger': 22, 'zhangsan': 24}
print(name["lisi"])
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py
KeyError: 'lisi'

# 通过get方法去访问可避免此类问题
name = {'wanger': 22, 'zhangsan': 24}

name2 = name.get('lisi','no value!')  # 如果没这个键,就明确给我一个返回值,这样程序本身不会出错
print(name2)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
no value!

还有一个案例,我们在后面会用到,一个外星人我们给它一个初始的xy坐标,然后给它一个速度,这个速度有这么几个档:slow、medium、fast,就是低中高,初始时外星人会从初始坐标出发,然后会不断的移动,我们怎样样让其移动呢?我们就可以加上if-elif-else的判断,如果它的速度是低,移动多远,速度是高移动多远,最终我们就可以获取它的全新坐标,它的全新坐标就等于旧坐标+移动的距离,然后将这个信息告诉给用户。

遍历字典

# 遍历所有的键值对
user1={'name':'zhangsan',
       'age':18,
        'alias':'zs'
       }
for key,value in user1.items():
    print(f'key:{key}\nvalue:{value}\n')

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
key:name
value:zhangsan

key:age
value:18

key:alias
value:zs
---
# 难度再升级点,如果发现其中有两个名字呢,我们会发现结果当中的value并没有展开,还是原始数据,如下所示:
user1={'name':['zhangsan','zsan'],
       'age':18,
        'alias':'zs'
       }
for key,value in user1.items():
    print(f'key:{key}\nvalue:{value}\n')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
key:name
value:['zhangsan', 'zsan']

key:age
value:18

key:alias
value:zs
----
# 我们怎么样才能其展开呢?
user1={'name':['zhangsan','zsan'],
       'age':'18',
        'alias':'zs'
       }
for key,value in user1.items():
    if type(value) == type([]):
        print(f'key:{key}')
        for i in value:
            print(f'value:{i}')
    else:
        print(f'\nkey:{key}\nvalue:{value}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
key:name
value:zhangsan
value:zsan

key:age
value:18

key:alias
value:zs
# 遍历所有的键
user1={'name':['zhangsan','zsan'],
       'age':'18',
        'alias':'zs'
       }
for key in user1.keys():
    print(key)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
name
age
alias
---
# 其实默认如果不加任何的方法,默认也就是列出所有的键
user1={'name':['zhangsan','zsan'],
       'age':'18',
        'alias':'zs'
       }
for key in user1:
    print(key)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
name
age
alias

# 再升级一下
name_languages={
    'zhangsan':'c',
    'lisi':"python",
    'wanger':"java",
    'cuihua':"php"
}
friends = ['zhangsan','lisi']

for name in name_languages.keys():
    print(f'Hi,{name}')
    if name in friends:
        language = name_languages[name]
        print(f'\tI see you {language}')

# 按照特定顺序遍历字典当中所有的键
user1={'name':['zhangsan','zsan'],
       'age':'18',
        'alias':'zs'
       }
for key in sorted(user1.keys()):
    print(key)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
age
alias
name
# 遍历所有的值
user1={'name':['zhangsan','zsan'],
       'age':'18',
       '身高':'18',
        'alias':'zs'
       }
for value in user1.values():
    print(value)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
['zhangsan', 'zsan']
18
18
zs

# key有重复的怎么办?如下所示加上set
user1={'name':'zs',
       'age':'18',
       '身高':'18',
        'alias':'zs'
       }
for value in set(user1.values()):
    print(value)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
zs
18

嵌套

重点理解一点逻辑关系:

集合-列表-元组-字典,都是由事件驱动而来的,整体的演变过程是混乱到秩序,从简单到复杂的历程。

集合最为简单,数据并不要求有序,看着比较混乱。

从集合到列表,开始有秩序

从列表到元组,又是一个新的进化,关注点着眼于不可变量的元素

从元组又到字典,在量上又有了一个飞跃,字典能存储不再以单个元素做为单位,而是某种“集合”做为单位,大开大合,这种演变有点类似于从IGP到BGP的过程,BGP基于IGP。

列表当中嵌套字典

# 先遍历一下
zhangsan={'gender':'boy','alias':'zs'}
lisi={'gender':'boy','alias':'ls'}
cuihua={'gender':'girl','alias':'ch'}

list_a = [zhangsan,lisi,cuihua]
for name in list_a:
    print(name)

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'gender': 'boy', 'alias': 'zs'}
{'gender': 'boy', 'alias': 'ls'}
{'gender': 'girl', 'alias': 'ch'}

上述例子当中仅有三个用户,我们怎么让python自动创建三十个用户呢?通过for 加上 range其实就可以的。

# 生成了30个,只要求显示了前三个,其实这三十个都是一模一样的,但在python看来
# 这里的每一个用户都单独的,我们后面的代码再来慢慢修改,让不用的外星人拥有不用的属性
aliens=[]
for i in range(1,31):
    new_alien= {'color':'green','points':5,'speed':'slow'}
    aliens.append(new_alien)
for alien in aliens[:3]:
    print(alien)
print(f'一共创建了{len(aliens)}名外星人!')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
一共创建了30名外星人!
# 进化一下,我们要将将三个外星人的皮肤修改成黄色,速度为中等,值为十分
# 下面这种思路是在追加的过程当中修改的
aliens=[]
for i in range(1,31):
    new_alien= {'color':'green','points':5,'speed':'slow'}
    if i <= 3:
        new_alien['color'] = 'yellow'
        new_alien['points'] = '10'
        new_alien['speed'] = 'medium'
    aliens.append(new_alien)
for alien in aliens[:4]:
    print(alien)
print(f'一共创建了{len(aliens)}名外星人!')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'color': 'yellow', 'points': '10', 'speed': 'medium'}
{'color': 'yellow', 'points': '10', 'speed': 'medium'}
{'color': 'yellow', 'points': '10', 'speed': 'medium'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
一共创建了30名外星人!

# 方法有很多,我们再来换一种方法
# 思路是从列表完成之后进行修改
aliens=[]
for i in range(1,31):
    new_alien= {'color':'green','points':5,'speed':'slow'}
    aliens.append(new_alien)
for alien in aliens[:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['points'] = 10
        alien['speed'] = 'medium'
for alien in aliens[:4]:
    print(alien)
print(f'一共创建了{len(aliens)}名外星人!')

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
一共创建了30名外星人!
# 再进一步,再加一个判断
aliens=[]
for i in range(1,31):
    new_alien= {'color':'green','points':5,'speed':'slow'}
    aliens.append(new_alien)
for alien in aliens[:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['points'] = 10
        alien['speed'] = 'medium'
    elif alien['color'] == 'yellow':
        alien['color'] = 'red'
        alien['points'] = 15
        alien['speed'] = 'fast'
for alien in aliens[:4]:
    print(alien)
print(f'一共创建了{len(aliens)}名外星人!')

在字典当中存在列表

  • 每当需要在字典中将一个键关联到多个值时,都可以在字典当中嵌套一个列表。

外星人的属性是比较规范,它的颜色、坐标、移动速度,我们是批量生成的,它在字典当中的体现都是格式化的,比如:

new_alien= {'color':'green','points':5,'speed':'slow'}

但有的时候,数据并不是这么规范,比如说客户在披萨店点餐,客户要选一个是要厚的,还是要薄款的,选完这个之后,还得选配料表,就是披萨上要放哪些东西,这些东西可能是苹果、辣椒、鸡肉之类的,如下面这样:

厚薄:厚
配料表:蘑菇,奶酪

就样的数据格式,肯定要用字典,但是这格式也太不规范,我们可以将其规范一下,外面是字典,里面有普通的元素,也有列表,将一个列表当成一个元素,这样就规范了,如下所示:

披萨:{
			厚薄 = 厚
			配料表 = [蘑菇,奶酪]
			}
pizza = {
    'crust':'thick',
    'toppings':['mushromms','extra cheese']
    }
# 描述一下
print(f'您点的披萨的{pizza["crust"]}(厚)的!')
print("它的配料表有:")
for topping in pizza['toppings']:
    print(f'\t{topping}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
您点的披萨的thick(厚)的!
它的配料表有:
	mushromms
	extra cheese

再来举一个例子,我们统计一些学生喜欢的明星,如下所示:

张三:韩红,谭晶
李四:李荣浩,薛之谦
王二:姜文,范伟、赵本山
# 通过字典和列表将其规范一下
喜好名单:{
					张三:[韩红,谭晶]
					李四:[李荣浩,薛之谦]
					王二:[姜文,范伟、赵本山]
       }
# 打印浆果
张三同学,他喜欢的明星有:
	韩红
	谭晶
names = {
    '张三':['韩红','谭晶'],
    '李四':['李荣浩','薛之谦'],
    '王二':['姜文','范伟','赵本山']
}
for name,starts in names.items():
        print(f'{name}同学')
        for start in starts:
            print(f'\t{start}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
张三同学
	韩红
	谭晶
李四同学
	李荣浩
	薛之谦
王二同学
	姜文
	范伟
	赵本山

# 再进一步
names = {
    '赵六': ['小沈阳'],
    '张三':['韩红','谭晶'],
    '李四':['李荣浩','薛之谦'],
    '王二':['姜文','范伟','赵本山']
}
for name,starts in names.items():
        if len(starts) == 1:
            print(f'{name}同学:{starts[0]}')
        else:
            print(f'{name}同学:')
            for start in starts:
                print(f'\t{start}')
赵六同学:小沈阳
张三同学:
	韩红
	谭晶
李四同学:
	李荣浩
	薛之谦
王二同学:
	姜文
	范伟
	赵本山

在字典当中存储字典

每个用户的属性信息是一个字典,现在要将所有的用户信息都放到一个字典当中,也就是字典当中嵌套字典,如下所示:

users = {
    'zhangsan':{'age':18,'alias':'zs'},
    'lisi':{'age':19,'alias':'ls'},
    'wanger':{'age':22,'alias':'we'}
}

for name,atts in users.items():
    print(f'用户名是:{name}')
    age = atts['age']
    alias = atts['alias']
    print(f"\t您的年龄是:{age}")
    print(f"\t您的外号是:{alias}")

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py
用户名是:zhangsan
	您的年龄是:18
	您的外号是:zs
用户名是:lisi
	您的年龄是:19
	您的外号是:ls
用户名是:wanger
	您的年龄是:22
	您的外号是:we

七、用户输入和whil循环

INPUT

INPUT的工作原理:函数INPUT让程序暂停运行,等待用户输入一些文本,获取用户输入之后,python将其赋值给一个变量,以方便你使用。

message = input('tell me something: ')
print(message)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
tell me something: hello
hello
# 当提示内容太多需要折行时,优雅的输入
prompt="hello!"
prompt+="\nplease enter your name: "
message = input(prompt)
print(f'\nyou name:{message}')

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
hello!
please enter your name: zhangsan

you name:zhangsan
# 用户通过input输入的数字默认被识别成字符串,如果需要数学计算则需要转换:
age = input("how old are your: ")
print(f'您输入的数据类型是:{type(age)}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
how old are your: 18
您输入的数据类型是<class 'str'>

# 通过int做转换,如下所示:
age = int(input("how old are your: "))
print(f'您输入的数据类型是:{type(age)}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
how old are your: 18
您输入的数据类型是:<class 'int'>
# 判断一个数是奇数还是偶数,用一个简单的if就可以实现了
number = int(input("请输入一个数字: "))
if number % 2 == 0:
    print(f"您输入的数字是偶数!")
else:
    print(f"您输入的数字是奇数!")

while

for 循环用于针对集合中每一个元素都执行一个代码块,而while循环则不断运行,直到指定的条件不满足为止。

# 通过while循环从1数到5
x = 1
while x <= 5:
    print(x)
    x+=1
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
1
2
3
4
5

基于上面的理解,那如果我们把一个input函数放到while循环当中是不是就会一直运行了呢?我们来试一下:

# 会发现what is your name会不断的运行,提示你输入你的名字
while True:
    message = input("what is your name: ")

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
what is your name: zhangsan
what is your name: zhangsan
what is your name: zhangsan
what is your name:

一直这么运行也不行呀,得让用户选择一下什么时候才能停下,如果一直不能停下,那用户岂不是特别恼火?那怎样停呢?我们可以根据第一个小例子的思路,让用户输入三次之后自动停止:

x = 1
while x <= 3:
    message=input("what is your name:")
    x+=1
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
what is your name:zhangsan
what is your name:zhangsan
what is your name:zhangsan

Process finished with exit code 0

上述这种方法看起来不太聪明的样子,用户也会骂你的,我们如何改进一下呢?我们其实可以借鉴一下vim,当用户输入q的时候,vim就知道用户想要退出了,于是就停止程序。我们也可以借鉴一下这个思路,当用户输入quit的时候就不再满足循环条件,如下所示:

x = ""
while x != "quit":
    message=input("what is your name:")
    x=message

# 上面这个我们也可以再升级一下,无论用户输入exit还是quit都能退出,这个地方有点难理解,叫双非取反
x = ""
while (x != "quit") and (x != "exit"):
    message=input("what is your name:")
    x=message
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
what is your name:zhangsan
what is your name:lisi
what is your name:exit

Process finished with exit code 0

如下所示,把x的初始值去除行不行,x必须存在,哪怕是空也得存在,存在本身就是有意义的。

上述内容全都是仅有提示输入的信息,并没有打印结果的信息,我们加一点,如下所示:

x = ""
while (x != "quit") and (x != "exit"):
    message=input("what is your name:")
    print(f'{message}')
    x=message

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
what is your name:zhanghe
zhanghe
what is your name:quit
quit

上述打印的结果有些奇怪,你看哈,我都输入quit的,它还打印了一次,这样不科学呀,我想实现,当我输入quit的时候,它直接退出,不要打印最后一次了,怎么搞?其实if判断就好,判断用户输入的一旦是quit,就直接退出,如果不是quit那就执行,这通过if和else就能做呀。

message=""
while message != "quit":
    message=input("what is your name:")
    if message != "quit":
        print(f'{message}')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
what is your name:zhangsan
zhangsan
what is your name:quit

八、函数

简单函数

函数的定义:函数是带名字的代码块,用于完成具体的工作。

# 例一:一个简单的函数应用
def print_test():
    print("where are your from?".title())
print_test()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Where Are Your From?

---
# 例二,利用函数还完成一些重复性的工作
def print_test():
    print("where are your from?".title())
some_name=['zhangsan','lisi','wanger','jia']
for name in some_name:
    print(f'Hi! {name}')
    print_test()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Hi! zhangsan
Where Are Your From?
Hi! lisi
Where Are Your From?
Hi! wanger
Where Are Your From?
Hi! jia
Where Are Your From?
  • def是defination 定义的缩写,后面跟的就是需要自己定义的函数名字,如上述的”print_test”。
  • 函数名后面的括号里面要写什么?是写要传递进函数的信息的,有些函数是不需要信息的,如上述的例一。
  • 我们经常用函数来完成一些批量性的工作,如上述当中的例二
# 向函数传递单个参数
def test1_fun(name):
    print(f'Hi! {name},welcome to china'.title())

some_name=['zhangsan','lisi','wanger','jia']
for name in some_name:
    test1_fun(name)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Hi! Zhangsan,Welcome To China
Hi! Lisi,Welcome To China
Hi! Wanger,Welcome To China
Hi! Jia,Welcome To China
# 向函数传递多个参数
def fun_1(con1,con2):
    print(f'{con1}和{con2}进行了亲切友好的交谈,双方在贸易、经济方面充分交换了意见……')

fun_1('中国','日本')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
中国和日本进行了亲切友好的交谈,双方在贸易、经济方面充分交换了意见……

传递参数

# 位置参数要要非常注意顺序
def fun_1(p1,p2):
	print(f"i like {p1},don't like {p2}".title())

fun_1("dogs","cats")
fun_1("cat","dog")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
I Like Dogs,Don'T Like Cats
I Like Cat,Don'T Like Dog

如果想让顺序不出错,那最好用关键字参数,如下所示:

def fun_1(p1,p2):
	print(f"i like {p1},don't like {p2}".title())

fun_1(p2="cat",p1="dog")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
I Like Dog,Don'T Like Cat

如果原本函数要接收两个参数,结果调用的时候只写了一个,会有什么现象?会报错提示!那这种情况下怎么办?就可以使用默认值,如果用户不写,那就使用默认的。

默认值是第二优先级,只有当用户没有明确指定的时候才会使用默认值!

def fun_1(p1,p2="cat"):
	print(f"i like {p1},don't like {p2}".title())
fun_1("dog")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
I Like Dog,Don'T Like Cat
------
def fun_1(p1,p2="cat"):
	print(f"i like {p1},don't like {p2}".title())
fun_1("dog","panda")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
I Like Dog,Don'T Like Panda

返回值

我们前面使用的到的函数都关于打印直接输入内容的,但函数作用并不是仅仅如此,它还可以有返回值,在函数当中,可以使用return语句将值返回到调用函数的代码行。

# return 的正确理解应该是当你调用此函数的时候你要什么?举个例子
def test_fun(a,b,c):
    x = a + b
    y = b * c
test_fun(1,2,3)
## 返回值是空,什么都没有
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Process finished with exit code 0

# 你得告诉它你要什么,如下所示:
def test_fun(a,b,c):
    x = a + b
    y = b * c
    return y
test_fun(1,2,3)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Process finished with exit code 0
## 还有没有价格返回值,为什么?现在就相当于你告诉它y=6,但你没要求它打印

# 好,那我要求它打印
def test_fun(a,b,c):
    x = a + b
    y = b * c
    return y
print(test_fun(1,2,3))
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
6

# 现在理解了吧,那我们来做一个小例子 
def format_name(firstname,second_name):
    full_name = f'{firstname}{second_name}'
    # print(full_name)
    return full_name

testname = format_name('zhang','san')
print(testname.title())
# 让实参变成可选的
## 先搞一个正常的
def get_format_name(first_name,middle_name,last_name):
    full_name=f"{first_name} {middle_name} {last_name}"
    return full_name

print(get_format_name("li","xiao","lai"))
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
li xiao lai

# 下面这段代码涉及到两个知识点:默认值为空+可选
def get_format_name(first_name,last_name,middle_name=""):
    if middle_name:
        full_name = f"{first_name} {middle_name} {last_name}"
    else:
        full_name = f"{first_name} {last_name}"

    return full_name

print(get_format_name("feng","tang"))
print(get_format_name("li","xiao","lai"))
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
feng tang
li lai xiao

# 上面代码有问题,再改一下
def get_format_name(first_name,last_name,middle_name=""):
    if middle_name :
        full_name = f"{first_name}  {last_name} {middle_name}"
    else:
        full_name = f"{first_name} {last_name}"

    return full_name

print(get_format_name("feng","tang"))
print(get_format_name("li","xiao","lai"))
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
feng tang
li  xiao lai
# 让函数的返回值是字典
def get_format_name(first_name,last_name,middle_name=""):
    if middle_name:
        full_name = {'first':first_name,'midd':middle_name,'last':last_name}
    else:
        full_name = {'first':first_name,'last':last_name}

    return full_name

print(get_format_name("feng","tang"))
print(get_format_name("li","lai","xiao"))
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'first': 'feng', 'last': 'tang'}
{'first': 'li', 'midd': 'xiao', 'last': 'lai'}

# 让函数的返回值是字典,并且在函数内部结合if处理字典
if middle_name:
        full_name = {'first':first_name,'midd':middle_name,'last':last_name}
    else:
        full_name = {'first':first_name,'last':last_name}
    if age:
        full_name[age]=age

    return full_name

print(get_format_name("feng","tang",age=27))
print(get_format_name("li","lai","xiao",age=27))
# 真空还是假空
a = ""
b = ''
c = None

test_list = [a,b,c]
for i in test_list:
    if i is None:
        print("this is NUll")
    else:
        print("this is not NULL")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
this is not NULL
this is not NULL
this is NUll
# 结合前面学过的知识
# 一旦调用函数会自动询问用户的姓,然后再询问用户的名,最终做一个打印,无限进行循环
## 先写一个这种打印
def test_fun1(first_name,last_name):
    first_name=input("请输入您的姓氏: ")
    last_name=input("请输入您的名: ")
    full_name = f'{first_name} {last_name}'
    print(full_name)

test_fun1(1,2)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
请输入您的姓氏: zh
请输入您的名: san
zh san

## 放到whlie循环里面
def test_fun1(first_name,last_name):
    while True:
        first_name=input("请输入您的姓氏: ")
        last_name=input("请输入您的名: ")
        full_name = f'{first_name} {last_name}'
        print(full_name)

test_fun1(1,2)

## 怎样让循环停止呢?
def test_fun1(first_name,last_name):
    while True:
        first_name=input("请输入您的姓氏: ")
        if first_name == "quit":
            break
        last_name=input("请输入您的名: ")
        if last_name == "quit":
            break
        full_name = f'{first_name} {last_name}'
        print(full_name)

test_fun1(1,2)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
请输入您的姓氏: zhang
请输入您的名: san
zhang san
请输入您的姓氏: quit

向函数传递列表

既然函数可以帮助我们更有效率的处理数据,那我们向里面传递更复杂的数据岂不是更好,比如说向里面传递数据集—列表

def users(names):
    for name in names:
        print(f"Hi,{name} welcome to china!")
users(['zhangsan','lisi','wanger'])

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
Hi,zhangsan welcome to china!
Hi,lisi welcome to china!
Hi,wanger welcome to china!

我们先来写一个打印店用的小程序片段:

not_print = ['apple','dog','panda','cat']
com_print = []

while not_print:
    current_print=not_print.pop()
    print(f'当前正在打印{current_print}')
    com_print.append(current_print)

print(f'当前已经完成的素材有: ')
for i in com_print:
    print(i)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
当前正在打印cat
当前正在打印panda
当前正在打印dog
当前正在打印apple
当前已经完成的素材有: 
cat
panda
dog
apple

def print_process(not_print,com_print):
    while not_print:
        current_print = not_print.pop()
        print(f"当前打印的是{current_print}")
        com_print.append(current_print)

def show_com_print(com_print):
    print(f'当前已经打印成功的有:')
    for i in com_print:
        print(i)

not_print = ['apple','dog','panda','cat']   # print_process(not_print[:],com_print)
com_print = []

print_process(not_print,com_print)
show_com_print(com_print)
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
当前打印的是cat
当前打印的是panda
当前打印的是dog
当前打印的是apple
当前已经打印成功的有:
cat
panda
dog
apple

传递任意数量的实参

产生背景:有时候,预先不知道需要接受多少个实际参数,默念会存储到一个元组当中

# 函数接收任意数量的参数
def make_pizza(*toppings):
    print(toppings)

make_pizza('apple')   # 注意,这个地方是一个元组
make_pizza('apple','egg')

def make_pizza(*toppings):
    print(f'\n您点的配料有:')
    for i in toppings:
        print(f'{i}')

make_pizza('apple')
make_pizza('apple','egg')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
您点的配料有:
apple

您点的配料有:
apple
egg
# python优先匹配位置实参和关键数实参
# 如果要让函数同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后
def make_pizza(size,*toppings):
    print(f'\n您点的配料有:')
    for i in toppings:
        print(f'{i}')

make_pizza('apple','green pepppers','mushrooms')
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 

您点的配料有:
green pepppers
mushrooms
# 使用任意数量的关键字实参
# 比如说微信QQ注册时的个性签名

def users(name,age,**infomation):
    infomation["name"] =name
    infomation["age"] = age
    return infomation

print(users('zhangsan','17',like='aaa',like2="bbbb"))

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
{'like': 'aaa', 'like2': 'bbbb', 'name': 'zhangsan', 'age': '17'}

Process finished with exit code 0

将函数存储在模块中

# 导入整个模块,import后面的pizza实际上一个后缀名为.py的文件
import pizza
pizza.make_pizza('18','apple')

实际上是导入整个模块,其实是整个文件,然后在文件里面查找make.pizza这个函数。

# 导入特定函数
from pizza import make_pizza
make_pizza('18','apple')
  • 仅导入模块里面一个函数,这样战用的内存比较少,函数后面可以加逗号,这样就可以在一个文件当中导入多个函数了。
  • 使用这种语法时,调用函数无须使用句点,由于在import语句中显式导入了函数make.pizza,调用时只需要声明其名称即可。
# 使用as给函数指定别名
# 为什么要指定别名呢?因为有的函数名字太长了,使用起来不方便。也可能与主程序当中的其它函数名字冲突
from pizza import make_pizza as pz
pz('18','apple')
# 使用函数给模块指定别名
import pizza as pz
pz.make_pizza('18','apple')
# 导入模块中的所有函数,不建议这么做
import pizza
from pizza import *
pizza.make_pizza('18','apple')

九、类

image-20230327083022310

@xiaolai's works

面向对象编程(OOP),是使用对象(Objects)作为核心的编程方式。进而就可以把对象(Objects)的数据和运算过程封装(Encapsulate)在内部,而外部仅能根据事先设计好的界面(Interface)与之沟通。比如,你可以把灯泡想象成一个对象,使用灯泡的人,只需要与开关这个界面(Interface)打交道,而不必关心灯泡内部的设计和原理 —— 说实话,这是个很伟大的设计思想。生活中,我们会遇到无数有意无意应用了这种设计思想的产品 —— 并不仅限于编程领域。你去买个车回来,它也一样是各种封装之后的对象。当你转动方向盘(操作界面)的时候,你并不需要关心汽车设计者是如何做到把那个方向盘和车轮车轴联系在一起并如你所愿去转向的;你只需要知道的是,逆时针转动方向盘是左转,而顺时针转动方向盘是右转 —— 这就可以了!

image-20230327083034247

创建和使用类

# 一个小例子展示一下类
class Dog:
    '''一次模拟小狗的简单尝试'''
    def __init__(self,name,age):    # init方法表示创建一个特定小狗的实例,并使用提供的值来设置属性name和age,name和age是属性,同时也是创建实例之后的结果
        '''初始化属性name和age'''
        self.name = name
        self.age = age
    def sit(self):
        '''模拟小狗收到命令时蹲下'''
        print(f'{self.name} is now sitting.')
    def roll_over(self):
        print(f'{self.name} roll over!')

我们来看上面的代码,有几点需要注意:

  • 定义类的时候要使用驼峰式的书写方式
  • 类名称后面可以没有括号,函数后面是必须有括号的
  • 上述这个类体当中有三个函数,在类当中,函数就是方法
  • 从书写方式你可以看出来init这个函数以及其后跟的self不一般,看着有点邪乎,其实是init后面的三个参数只有self是固定的,self其实上代表本身,我们要传递变量的时候只传递name和age就可以了,不用管self
  • self有点像调用的接口,你看后两个代码在定义函数的时候都使用了self做为开头
# 在上一段代码的基础上,做下述操作
my_dog = Dog('willie',6)
print(f"my dog's name is {my_dog.name}")
print(f"my dog's is {my_dog.age}")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
my dog's name is willie
my dog's is 6

Process finished with exit code 0

init方法表示创建一个特定小狗的实例,并使用提供的值来设置属性name和age,name和age是属性,同时也是创建实例之后的结果,init创建实例之后,这个实例将赋予给my_dog,注意,此时my_dog即这个实例,同时还携带了两个结果,也可以说是两个属性,一个属性是name=willie,另一个属性是age=6,这都是你之前将数据传输进init之后的计算出来的结果,计算完成之后最后赋值给了my_dog,最后两行打印就是将这两个属性打印了出来。

Dog是实例不假,my_dog现在也等于Dog了,那my_dog自然也是一个实例,这一点需要注意一下;

# 访问属性,使用句点表示法,实例后面加一点,然后跟属性,如
my_dog.name

上述过程很简单了,先找到my_dog实例,然后再根据实例找到它的属性name,属性name其实是self.name,在类里面做了赋值self_name = name。


上述我们通过实例,借由实现最终找到了小狗的属性,下面还有两个函数代表小狗的动作,两个函数就是两个方法,下面我们就来调用一下两个方法。

class Dog:
    '''一次模块小狗的简单尝试'''
    def __init__(self,name,age):
        '''初始化属性name和age'''
        self.name = name
        self.age = age
    def sit(self):
        '''模拟小狗收到命令时蹲下'''
        print(f'{self.name} is now sitting.')
    def roll_over(self):
        print(f'{self.name} roll over!')
# 两个函数就是两个方法,下面我们就来调用一下两个方法。
my_dog = Dog('wangcai','2')
my_dog.sit()
my_dog.roll_over()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
wangcai is now sitting.
wangcai roll over!

my_dog.sit()是调用sit这个方法,发现于调用属性时基本上一样,只不过没有加print而已,因为类体当中已经有print了,但有一点需要注意,在调用方法当中,你调用是一个真正的函数,因为后面的括号,而在调用name属性的时候并没有小括号。


下面演示一个创建多个实体,我们通过看代码可以知道,类体只创建一个实例Dog,怎么创建多个实例呢?其实很简单,就是把一个实例多次调用而已,然后每一次调用都将其赋值给不同变量而已,如:

my_dog = Dog('willie','6')
your_dog = Dog('lucy',3)
print(f"my dog's name is {my_dog.name}")
print(f"my dog's is {my_dog.age}")
my_dog.sit()
print()
print(f"your dog's name is {your_dog.name}")
print(f"your dog's is {your_dog.age}")
your_dog.sit()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
my dog's name is willie
my dog's is 6
willie is now sitting.

your dog's name is lucy
your dog's is 3
lucy is now sitting.

使用类和实例

通过前一小节的学习,我们发现其实编写类其实和函数真的差不多呀,都是将一些繁琐的操作放置在代码前面,然后在主程序代码当中向函数或类不断的传递参数,让其执行运算,最终把我们想要结果送到前台来而已。

在这里我想到日本寿司,其实在上寿司之前,菜已经做了有八成了,前台只是完成最后的关键部分而已。

# car类,我们再来编写一个新的类,car类
class Car:
    '''一次模拟汽车的简单尝试'''
    def __init__(self,make,model,year):
        self.make = make
        self.model = model
        self.year = year
    def get_descriptive(self):
        '''返回整洁描述性信息'''
        long_name = f'{self.year} {self.make} {self.model}'
        return long_name.title()

my_new_car = Car('audi','a4',2019)
print(f'my car model: {my_new_car.model}')
print(my_new_car.get_descriptive())
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
my car model: a4
2019 Audi A4

创建实例时,有些属性无须通过形参来定义,可在方法__init__中为其指定默认值。这感觉和函数非常像呀,函数也可以这么做呀

# 给属性指定默认值
class Car:
    '''一次模拟汽车的简单尝试'''
    def __init__(self,make,model,year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0   # 注意这个值是默认的,如果不传进来,就默认是0了
    def get_descriptive(self):
        '''返回整洁描述性信息'''
        long_name = f'{self.year} {self.make} {self.model}'
        return long_name.title()
    def read_olometer(self):
        print(f"this car has {self.odometer_reading} miles on it")

my_new_car = Car('audi','a4',2019)
my_new_car.read_olometer()


我们能以三种方式修改属性的值,直接通过实例进行修改,通过方法进行设置,以及通过方法进行递增,下面依次介绍这些方式。

# 最简单粗暴的方式,在类外面直接进行修改
my_new_car = Car('audi','a4',2019)
my_new_car.odometer_reading = 23
my_new_car.read_olometer()

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
this car has 23 miles on it
Process finished with exit code 0
# 通过方法修改属性的值,其实就是再加一个函数,然后向这个函数里面传递参数,从而达到修改旧的参数的目的
class Car:
    '''一次模拟汽车的简单尝试'''
    def __init__(self,make,model,year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
    def get_descriptive(self):
        '''返回整洁描述性信息'''
        long_name = f'{self.year} {self.make} {self.model}'
        return long_name.title()
    def read_olometer(self):
        print(f"this car has {self.odometer_reading} miles on it")
    def update_odometer(self,mileage):                                          # 这个函数是新增的
        self.odometer_reading= mileage

my_new_car = Car('audi','a4',2019)
my_new_car.update_odometer(99)
my_new_car.read_olometer()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
this car has 99 miles on it

# 再加一点东西,禁止有人为了卖车把进程表向回调
def update_odometer(self,mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading= mileage
        else:
            print("干啥呢?想干啥?竟然想把进程表向小了调!告诉你,这不不允许的")

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
干啥呢?想干啥?竟然想把进程表向小了调!告诉你,这不不允许的
this car has 99 miles on it  # 这里面的99是我们设置的的默认值

有的时候,我们需要将属性值递增特定的量,而不是设置一个全新的值,比如像进程数,它是随着车慢慢递增的呀

# 通过方法对属性的值进行递增
def increment_olometer(self, miles):
        self.odometer_reading += miles
my_new_car = Car('audi','a4',2019)
my_new_car.increment_olometer(44)
my_new_car.read_olometer()

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
this car has 143 miles on it  # 默认是99,现在加上44,正好是143

继承

继承非常好理解,你看哈,电动汽车也是车的范围内,那我们上述定义的车里面方法,或称之为函数,以及里面的参数,比如车的属性:品牌、型号、年份,在电车当中都可以继续使用,并不需要我们从新定义一个关于电动汽车的类,可以让其直接继承用车的类。

继承的要求:

  • 子类不用在父类不用缩进,子类在缩进上与父类相等
  • 父类和子类必须位于同一个文件,子类才能继承
  • 子类可以直接调用并使用父类的方法,也可以自己生成单独属性自己的方法
# 我们先来看一下,子类最基础的方法__init__()
class Car:
    '''一次模拟汽车的简单尝试'''
    def __init__(self,make,model,year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 99
    def get_descriptive(self):
        '''返回整洁描述性信息'''
        long_name = f'{self.year} {self.make} {self.model}'
        return long_name.title()
    def read_olometer(self):
        print(f"this car has {self.odometer_reading} miles on it")
    def update_odometer(self,mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading= mileage
        else:
            print("干啥呢?想干啥?竟然想把进程表向小了调!告诉你,这不不允许的")
    def increment_olometer(self, miles):
        self.odometer_reading += miles
# 上述代码是上一小节的,没动,新的代码从此处开始
# 注意呀,子类的括号里面带了父类的名字,子类必须声明父类
class ElectricCar(Car):
    def __init__(self,make,model,year):
        super().__init__(make,model,year)

my_tesla = ElectricCar('tesla','model s','2019')
print(f"{my_tesla.get_descriptive()}")
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
2019 Tesla Model S
  1. class ElectricCar(Car): 子类必须声明继承的父类
  2. def init(self,make,model,year): 子类必须也有自己的init
  3. super().init(make,model,year),通过super可以直接调用父类的init,相当于你使用子类的init时,会将参数再传递到父类
  4. print(f"{my_tesla.get_descriptive()}") 可通过子类直接使用父类的函数或方法

下面我们给子类添加独属于自己方法,添加一个电动车才有的属性:电瓶,那电瓶的容器定义成方法

class ElectricCar(Car):
    def __init__(self,make,model,year):
        super().__init__(make,model,year)
        self.battery_size = 75   # 这是电瓶容量的默认值
    def decribe_bettery(self):
        print(f'this car has a {self.battery_size}-KWh battery')
my_tesla = ElectricCar('tesla','model s','2019')
my_tesla.decribe_bettery()

"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
this car has a 75-KWh battery

如果父类的方法子类并不适合,除了定义新的方法之外,还可以重写父类的方法,其实子类不可能更改父类的方法,其实仅仅是在子类当中写一个与父类同名的方法,这样的话在调用子类的时候,就会优先用子类本地定义的,而不去用父类的了,很好理解呀

image-20230327083050024


当方法越来越多时,就要定义很多的函数(方法),我们可以把一部分有相似点的属性拿出来,比如电车的电池,用电池再定义一个新类,然后在电车这个子类里面将电瓶当做是是一个属性来调用,如下所示:

# 将实例用做属性
class Battery:   # 没有继承任何类,因为他不需要继承,它在等待被调用
    def __init__(self,battery_size=75):  # 不需要传参,自己定义了一个默认电量75
        self.battery_size = battery_size  # 简单的赋值
    def descrite_battery(self):           # 定义了一个函数,打印一下电量
        print(f"this car has a {self.battery_size}--kwh battery")

class ElectricCar(Car):
    def __init__(self,make,model,year):
        super().__init__(make,model,year)
        self.battery = Battery()          **# 前面都没变,就这里参与调用了新的关于电池的类,将电池整个实例当成一个类**
    def fill_gas_tank(self):
        print("这是子类")
my_tesla = ElectricCar('tesla','model s','2019')
print(my_tesla.get_descriptive())
my_tesla.battery.descrite_battery()      # 调用的时候除了指明电车类,还要指定电子类,才能调用其方法
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
2019 Tesla Model S
this car has a 75--kwh battery

# 再改进一下,新增方法get_range做一个简单分析,如果电瓶的容易为75,就将续航进程设置为260
class Battery:
    def __init__(self,battery_size=75):
        self.battery_size = battery_size
    def descrite_battery(self):
        print(f"this car has a {self.battery_size}--kwh battery")
    def get_range(self):
        if self.battery_size == 75:
            range = 260
        elif self.battery_size == 100:
            range = 315
        print(f"this car can go about: {range} miles on a full charge.")
class ElectricCar(Car):
    def __init__(self,make,model,year):
        super().__init__(make,model,year)
        self.battery = Battery()
    def fill_gas_tank(self):
        print("这是子类")
my_tesla = ElectricCar('tesla','model s','2019')
print(my_tesla.get_descriptive())
my_tesla.battery.descrite_battery()
my_tesla.battery.get_range()
"C:\Program Files\Python311\python.exe" G:\python2\黑客.py 
2019 Tesla Model S
this car has a 75--kwh battery
this car can go about: 260 miles on a full charge.

导入类

导入类这个非常简单,当类越来长的时候,我们就得将他们拆到不同的文件,我们跨文件来调用。

# 导入单个类
# from后面跟的一个文件car,import后面跟的是文件当中的Car这个类
from car import Car
my_new_car = Car('auti','a4',2019)
print(my_new_car.get_descriptive())
my_new_car.odometer_reading = 23
my_new_car.read_olometer()
# 直接调用电车类,也将会拉动汽车类进来,只是没有在from和import当中体现出来罢了
# 也就是说电车这类,其实存储着多个类,你导入一个,其它的也跟着导入了
from car import ElectricCar
my_tesla = ElectricCar('tesla','model s','2019')
print(my_tesla.get_descriptive())
my_tesla.battery.descrite_battery()
my_tesla.battery.get_range()
# 在一个模块当中导入多个类
from car import Car,ElectricCar
my_tesla = ElectricCar('tesla','model s','2019')
print(my_tesla.get_descriptive())
my_beetle = Car("volkswagen",'beetle',2018)
print(my_beetle.get_descriptive())
# 导入整个模块
import car
my_beetle = car.Car("volkswagen",'beetle',2018)
print(my_beetle.get_descriptive())
# 导入模块中的所有类
from car import *
my_beetle = Car("volkswagen",'beetle',2018)
print(my_beetle.get_descriptive())
# 跨文件,或称之为跨模块调用时,要先from其它的模块
# 使用别名
from car import Car as Ec
posted @ 2023-03-27 08:33  张贺贺呀  阅读(110)  评论(0编辑  收藏  举报