嵌入式Python高级

嵌入式Python高级 str字符串 set集合 dict字典 slice切片 推导式 高级变量公共语法 内置函数 面向对象  __int__  __str___  私有化  属性私有化  方法私有化  面向对象三大特征 封装 继承 多态

一、str字符串

字符串就是一串字符,是编程语言中表示文本的数据类型

1. 字符串定义

Python中可以使用一对双引号或者一对单引号定义字符串

str1 = 'hello'
str2 = "hello"

2. 获取字符串中元素

和列表一样,字符串也是通过索引获取元素

str = "hello"
# 获取第三个元素
ele = str[2] # l

3. 遍历字符串

可以通过for循环遍历字符串

str = 'hello'
for ele in str:
    print(ele)

4. 字符串的常见操作

4.1. 判断

4.2. 查找替换
 4.3. 切割

4.4. 去空白
 

5. 练习-用户名和密码校验

需求

  • 用户名和密码格式校验程序
  • 要求从键盘输入用户名和密码,分别校验格式是否符合规则
    • 如果符合,打印用户名合法密码合法
    • 如果不符合,打印出不符合的原因,并提示重新输入
  • 用户名长度6-20,用户名必须以字母开头
  • 密码长度至少6位,不能为纯数字,不能有空格

分析

1.从键盘输入用户名(需要while循环)
2.长度6-20
3.必须字母开头

4.输入密码(while循环)
5.密码长度至少6位
6.不能为纯数字
7.不能有空格

实现

while True:
    # 1.从键盘输入用户名(需要while循环)
    name = input('请输入用户名:')
    # 2.长度6-20
    if not (len(name) >= 6 and len(name) <= 20):
        print('用户名必须6到20位')
        continue
    # 3.必须字母开头 ab A-Z
    # 获取第一个字母  是否是a-z A-Z a
    ele = name[0]
    if not ele.isalpha():
        print('用户名第一个必须为字母')
        continue

    # 用户名满足
    print('用户名合法')
    break

# 4.输入密码(while循环)
while True:
    pwd = input('请输入密码')
    # 5.密码长度至少6位
    if len(pwd) < 6:
        print('密码长度至少为6位')
        continue
    # 6.不能为纯数字
    if pwd.isdecimal():
        print('密码不能为纯数字')
        continue
    # 7.不能有空格
    # ' 张 三  '
    if ' ' in pwd:
        print('密码不能有空格')
        continue
    print('密码合法')
    break

 扩展

  • isalpha()字符串中所有元素都是字母,则返回True
  • isdecimal()字符串中都是数字,则返回True

二、set集合

set被称为集合,是无序的,并且集合中的元素是唯一的 

 1. 集合的创建

s = {'张三','李四','王五'}

 集合是无序的

s = {'张三','李四','王五'}
print(s)

结果: 

{'王五', '张三', '李四'}

集合元素唯一

s = {'张三','李四','王五','张三'}
print(s)

结果:

{'李四', '张三', '王五'}

2. 遍历集合中元素 

通过for循环遍历集合中的元素

s = {'张三','李四','王五'}
# 遍历集合
for ele in s:
    print(ele)

3. 集合中添加元素 

集合可以通过add方法添加元素

s = {'张三','李四','王五'}
# # 添加赵六 add
s.add('赵六')

4. 集合删除元素 

remove删除,如果有 直接删除,如果没有 程序报错

s = {'张三','李四','王五'}
# 删除张三 
s.remove('张三')

pop删除,随机删除集合中的元素并返回,如果集合中没有元素,则程序报错 

s = {'张三','李四','王五'}
# pop 随机删除
print(s.pop())

discard删除,元素存在则直接删除,如果元素不存在,则不做任何操作 

s = {'张三','李四','王五'}
# discard 删除元素 如果元素不存在,不做任何处理
s.discard('林青霞')

三、dict字典

1. 字典简介

dictionary(字典) 是 除列表以外 Python 之中 最灵活 的数据类型,类型为dict

  • 字典同样可以用来存储多个数据
  • 字典使用键值对存储数据

 

2. 字典的定义

  • 字典用{}定义
  • 键值对之间使用,分隔
  • 之间使用:分隔
d = {'中国':'China','英国':'England','美国':'America'}

3. 字典的特点 

字典中的相当于索引,必须是唯一的

d = {'中国':'China','英国':'England','美国':'America','美国':'USA'}
print(d)

运行: 

{'中国': 'China', '英国': 'England', '美国': 'USA'}

4. 字典增删改查

4.1. 增加

字典增加元素

d = {'中国':'China','英国':'England','美国':'America'}
# 添加 法国
d['法国'] = 'France'

也可以通过setdefault方法添加 

d.setdefault('法国','France')
4.2. 删除 

字典删除元素

d = {'中国':'China','英国':'England','美国':'America'}
# 删除美国 如果键不在字典中,会报错
del d['法国']

也可以通过pop删除

# pop 删除元素 并且返回删除元素的值 如果删除不存在会报错
result = d.pop('法国')

清空字典 

# 清空容器中的数据  还可以继续使用
d.clear()
4.3. 修改

修改字典中元素

d = {'中国':'China','英国':'England','美国':'America'}
# 修改美国
d['美国'] = 'USA'
4.4. 查询

查询元素

d = {'中国':'China','英国':'England','美国':'America'}
# 查找中国
value = d['中国']
print(value)

5. 字典遍历

5.1. 遍历所有的键值对

通过for循环遍历字典所有的键值对

d = {'中国':'China','英国':'England','美国':'America'}

for ele in d:
    print(ele,d[ele])

结果: 

中国 China
英国 England
美国 America
5.2. 遍历所有的键 
d = {'中国':'China','英国':'England','美国':'America'}
for key in d.keys():
    print(key)

结果:

中国
英国
美国
5.3. 遍历所有的值
d = {'中国':'China','英国':'England','美国':'America'}

for value in d.values():
    print(value)

结果:

China
England
America
5.4. 遍历所有的键值对
d = {'中国':'China','英国':'England','美国':'America'}
for key,value in d.items():
    print(key,value)

结果:

中国 China
英国 England
美国 America

6. 字典的应用场景

使用多个键值对,存储描述一个物体的相关信息---描述更复杂的数据信息

d = {'name':'张三','phone':'12332','age':40,'性别':'男'}

四、slice切片

1. 切片简介

取一个strlisttuple的部分元素是非常常见的操作

  • 切片 译自英文单词slice,指的是一部分
  • 切片 根据 步长step 从原序列中取出一部分元素组成新序列
  • 切片适用于 字符串、列表、元组

2. 切片的格式

字符串[开始索引:结束索引:步长]

包含开始索引, 不包含结束索引

2.1. 需求
string = '中华人民共和国欢迎您'
获取前三个文字
2.2. 代码
string = '中华人民共和国欢迎您'
# 获取前三个文字
newStr = string[0:3:1]

步长默认为1,可以省略,如下

newStr = string[0:3]

开始索引为0,可以省略,如下 

newStr = string[:3]

如果到末尾结束,可以省略结束索引,例如取后三个字“欢迎您

newStr = string[7:]

3. 索引的正序和倒序

索引分为正序和倒序

  • 正序:从左向右,0开始
  • 倒序:从右向左,-1开始

 

3.1. 需求
ss = "中华人名共和国欢迎您"
把字符串中从第一个到倒数第二个(不包含)打印出来
3.2. 代码 
ss = "中华人名共和国欢迎您"
# 把字符串中从第一个到倒数第二个(不包含)打印出来
# 开始位置:正序  结束位置:倒序
print(ss[:-2])

4. 步长为负数

步长也可以为负数,代表逆序切片

4.1. 需求
ss = "中华人名共和国欢迎您"
把从角标为2到7(包含)倒序打印出来
4.2. 代码
ss = "中华人民共和国欢迎您"
# 把从角标为2到7(包含)倒序打印出来
# 欢国和共名人
print(ss[7:1:-1])

注意:步长为负,索引也应该逆序索引

 五、推导式

推导式指的是轻量级循环创建数据的方式,对列表或可迭代对象中的每个元素应用某种操作,用生成的结果创建新的列表;或用满足特定条件的元素创建子序列。

推导式包括:

  • 列表推导式
  • 元组推导式
  • 集合推导式
  • 字典推导式

1. 列表推导式

列表推导式的格式:[计算公式 for循环 if判断]

通过列表推导式快速创建[1, 11)所有数字的列表

lst = [ele for ele in range(1, 11)]
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

通过列表推导式快速创建[1, 11)所有偶数的列表

lst = [ele for ele in range(1, 11) if ele % 2 == 0]
# [2, 4, 6, 8, 10]

通过列表推导式快速创建[1, 11)所有偶数的平方的列表

lst = [ele ** 2 for ele in range(1, 11) if ele % 2 == 0]
# [4, 16, 36, 64, 100]

2. 元组推导式 

元组推导式的格式:(计算公式 for循环 if判断),其他与列表推导式一致

tp  =(ele for ele in range(1, 11))

3. 集合推导式

集合推导式的格式:{计算公式 for循环 if判断},其他与列表推导式一致

s = {ele for ele in range(1, 11)}

4. 字典推导式

d = {key:value for key, value in zip(range(1,10),range(21,30))}

zip(..., ...)range(1,10)range(21,30)里的每个元素一一组合成元组 

(1, 21)
(2, 22)
(3, 23)
...
(8, 28)
(9, 29)

再把这些元组打包成一个可迭代对象。

5. 推导式练习

5.1. 需求
请写出一段 Python 代码实现分组一个 list 里面的元素
比如 [1,2,3,...100] 变成 [[1,2,3],[4,5,6]....[100]]
5.2. 分析
需要将列表中三个元素一组分隔,剩下的最后一组,其实就是对列表进行切片操作
5.3. 代码
# 创建列表
lst = [ele for ele in range(1, 101)]

# 切片 0:3  3:6 6:9
newL = [lst[ele:ele + 3] for ele in range(0, len(lst)) if ele % 3 == 0]
print(newL)

 六、高级变量类型的公共语法

1. 内置函数

高级变量类型有一些公共的内置函数,如下

len 长度
str = 'hello'
print(len(str))

结果:

5
del 删除
lst = [1,2,3]
del lst[0]
print(lst)

结果:

[2,3]

2. 运算符

 

2.1. innot in
str = 'hello'
# h是否在str中
result = 'h' in str
print(result)
result = 'h' not in str
print(result)

结果:

True
False
2.2. +合并

只有字符串、列表、元组可以合并

# 字符串
str1 = 'hello'
str2 = 'world'
str = str1 + str2

字符串

# 字符串
str1 = 'hello'
str2 = 'world'
str = str1 + str2

列表

lst1 = [1,2,3]
lst2 = [4,5,6]
lst = lst1 + lst2

元组

t1 = (1,2,3)
t2 = (4,5,6)
t = t1 + t2
2.3. * 重复

只有字符串、列表、元组可以

str = 'hello'
print(str*3)

l = [1,2,3]
print(l * 3)

t = (1,2,3)
print(t * 3)

结果:

hellohellohello
[1, 2, 3, 1, 2, 3, 1, 2, 3]
[1, 2, 3, 1, 2, 3, 1, 2, 3]

 七、综合练习1-1

字符串逆序统计

需求:
完成字符串的逆序以及统计
设计一个程序,要求只能输入长度低于31的字符串,否则提示用户重新输入
打印如下内容:
--------------------------------------------
您输入的字符串: zhongshanshan
长度: 13
逆序后为: nahsnahsgnohz
字符统计结果: z:1 h:3 o:1 n:3 g:1 s:2 a:2
--------------------------------------------
分析 
1. 输入字符串(while循环)
2. 字符串长度小于31位,否则提示重新输入
3. 您输入的字符串: ...
4. 长度: ...
5. 逆序后为: ...  (切片)
6. 字符统计结果: ...(afsfdsf)  a:1  f:3 s:2 d:1
代码
while True:
    # 1.输入字符串(while循环)
    str = input('请输入字符串:')
    # 2.字符串长度小于31位,否则提示重新输入
    if len(str) >= 31:
        print('不能超过31位,请重新输入')
        continue
    # 跳出循环
    break
print('输入正确')
print("--------------------------------------------")
# 3.您输入的字符串: ...
print('您输入的字符串:%s' % str)
# 4.长度: ...
print('长度:%d' % len(str))
# 5.逆序后为: ...  (切片)
newStr = str[::-1]
print('逆序后为:%s' % newStr)
# 6.字符统计结果: ...(afsfadsf)  a:1  f:3 s:2 d:1
# 1.字典 保存结果  {}
resultDict = {}
for ele in str:
    if ele not in resultDict:
        # 2. 如果字典中没有这个a, 把a添加进去 {'a':1}
        resultDict[ele] = 1
    else:
        # 3.字典中有a 将元素个数+1
        resultDict[ele] += 1
print('字符统计结果:{}'.format(resultDict))
print("--------------------------------------------")

 八、面向对象

1. 面向对象和面向过程思想

面向对象面向过程都是一种编程思想,就是解决问题的思路

  • 面向过程:POP(Procedure Oriented Programming)面向过程语言代表是c语言
  • 面向对象:OOP(Object Oriented Programming)常见的面向对象语言包括:java c++ go python koltin

通过面向对象的方式,我们不再关注具体的步骤,而是将问题抽象为对象和它们之间的交互。我们可以直接调用对象的方法来实现功能,而无需显式指定每个步骤。

面向过程强调按照步骤执行操作,而面向对象强调通过定义和操作对象来解决问题。

在面向对象的编程中,我们将问题抽象为对象的集合,这些对象具有属性和行为,并通过对象之间的交互来实现功能。这种抽象和交互的方式使得面向对象编程更加灵活、可维护和可扩展。

接下来我们看同一个问题,面向过程和面向对象是怎么解决的?

 

1.1. 面向过程编程的贪吃蛇游戏

在面向过程编程中,贪吃蛇游戏可能会以以下方式实现:

  1. 定义蛇的初始位置、长度、方向等变量。
  2. 创建一个表示游戏区域的二维数组。
  3. 在游戏循环中,根据用户输入改变蛇的方向。
  4. 更新蛇的位置,根据当前方向向前移动一格。
  5. 检查蛇是否吃到食物,如果是,则增加蛇的长度。
  6. 检查蛇是否撞到边界或自己的身体,如果是,则游戏结束。
  7. 在游戏区域中绘制蛇和食物。
  8. 循环回到第3步,直到游戏结束。

在面向过程的编程中,游戏的各个方面被划分为一系列的步骤和变量,通过按照特定顺序执行这些步骤来控制游戏的逻辑和状态。

1.2. 面向对象编程的贪吃蛇游戏

现在,让我们看看如何使用面向对象编程来实现贪吃蛇游戏。

  1. 创建一个Snake类,具有属性(例如位置、颜色、长度、方向)和方法(例如移动、吃食物)。
  2. 创建一个Food类,具有属性(例如位置、颜色)。
  3. 创建一个Game类,它包含一个或多个蛇对象和一个或多个食物对象,以及游戏区域等属性。Game类还具有控制游戏逻辑的方法,例如更新游戏状态和绘制游戏界面。
  4. 在游戏循环中,通过调用Game类的方法来控制游戏的进行,例如根据用户输入改变蛇的方向,更新蛇的位置,检查碰撞等。
  5. 在游戏界面中,通过调用绘图方法来绘制蛇和食物。

在面向对象编程中,贪吃蛇游戏被视为一组对象的交互。各个对象封装了游戏的状态和行为,并通过对象之间的消息传递来实现功能。这种对【对象Object】的抽象和交互使得游戏逻辑更清晰、可维护性更高,并且可以轻松地扩展和修改游戏的功能。

1.3. 面向对象的总结
  • 面向对象,强调的是对象(实体)
  • 面向对象是一种思想,更加符合人的思维习惯
  • 面向对象使复杂的问题简单化了
  • 面向对象的出现,让曾经在过程的执行者,变成了对象的指挥者

2. 类和对象

类和对象是面向对象非常重要的概念

  • 类是描述了一种类型(相当于图纸)
  • 对象是这个类型的具体实现(相当于图纸具体实现)

思考:

旺财和狗,哪个是类,哪个是对象?

答案:

狗是一个类型,属于类

旺财是狗的实现,属于对象

类和对象的关系

类就是制造图纸,只有一个。对象是类的实体,会产生多个

 

定义类和创建对象 

类的定义格式:

class 类名:
    pass

创建对象

对象名 = 类名()

代码演示:

# 定义类
class Person:
    pass
# 创建对象
p1 = Person()

3. 类的组成

类可以描述世间万物,类都需要有类名,也应该具备一些属性行为

  • 类的关键字:class
  • 类的名称:类名
  • 类的属性:一组数据
  • 类的方法:允许进行操作的方法(行为)

人(Person)类应该具备什么属性和行为呢?

  • 属性:姓名(name) 、年纪(age)
  • 方法:吃(eat)、跑(run)、说话(say)
3.1. 成员属性

成员属性的定义需要在初始化方法__init__方法下定义

格式:

def __init__(self):
	self.属性 = 属性值

举例:

class Person:
    def __init__(self, name, age):
        # 成员属性
        self.name = name
        self.age = age
        
# 创建对象
p = Person('张三', 30)
# 访问成员属性
print(p.name)
print(p.age)

在创建对象时,属性值可以由外部传进来,也可以在初始化方法里设置为任意值

3.2. 成员方法

成员方法的定义格式为 def 函数名(self):

class Person:
    
    # 定义成员方法 say_hello
    def say_hello(self):
        print('hello')
        
	# 定义成员方法run
    def run(self):
        print('跑')

# 创建对象
p = Person()
# 调用成员方法
p.say_hello()

注意:

成员方法都会默认有参数self,调用的时候不需要传递self

九、 特殊方法和参数

1. 成员方法的self参数

成员方法中self表示调用该方法的对象。
对象调用⽅法时,python解释器会把这个对象作为第⼀个参数传递给⽅法
通过self也可以获取对象的属性,调用对象的其它成员方法

class Person:
    def __init__(self, name, age):
        # 定义成员属性
        self.name = name
        self.age = age

    def say_hello(self):
        # 通过self访问成员属性
        print(self.name)


# 对象
p = Person('张三', 30)
p.say_hello()

2. __init__方法

__init__是一个内置的方法
对象创建的时候就会自动执行__init__方法

# 定义类
class Person:
    def __init__(self):
        print('执行了init方法')

# 创建对象
p1 = Person()
p2 = Person()

运行程序,输出:

执行了init方法
执行了init方法

一旦创建了该类的对象就会执行__init__方法

3. __str__方法

__str__也是类的内置方法

用于将对象转化为适于人阅读的形式

先看一段代码:

class Person:
    def __init__(self,name,age):
        # 成员属性
        self.name = name
        self.age = age

# 创建对象
p1 = Person('张三',30)
p2 = Person('李四',40)
print(p1)
print(p2)

创建了两个对象,输出两个对象

结果:

<__main__.Person object at 0x03769D10>
<__main__.Person object at 0x03769FD0>

从结果中我们并不能区分出到底哪个是属于p1,哪个是属于p2

可以通过__str__提取对象的主要特征用于区分不同的对象

class Person:
    def __init__(self,name,age):
        # 成员属性
        self.name = name
        self.age = age

    def __str__(self):
        '''
        以字符串输出对象,把对象变成我们能够读懂的形式输出出来
        :return:
        '''
        return 'name:{}, age:{}'.format(self.name,self.age)

# 创建对象
p1 = Person('张三',30)
p2 = Person('李四',40)
print(p1)
print(p2)

 输出结果:

name:张三, age:30
name:李四, age:40

我们从结果中很容易就区分出两个对象的不同 

十、私有化

属性或者方法设置为不能在外部访问,就是私有化

私有化包括:属性私有化方法私有化

1. 属性私有化

属性私有化格式,注意是两个下划线__
self.__属性名 = 属性值

class Circle:
    def __init__(self,radius):
        # 半径
        self.radius = radius
        # 私有化圆周率属性 
        self.__PI = 3.1415926


    def perimeter(self):
        '''
        求圆的周长
        :return: 圆的周长
        '''
        return 2 * self.__PI * self.radius

私有化作用:保证类中数据安全

2. 方法私有化

方法的私有化方式和属性私有化方式一样

class Person:
    def __say_hello(self):
        print('hello')

十一、面向对象三大特征

面向对象三大特征是:


●封装 (Encapsulation)
●继承 (Inheritance)
●多态 (Polymorphism)


1.封装


封装就是隐藏内部实现的细节,只保留功能接口
需求
定义一个洗衣机类,其中包含了打开/关闭洗衣机门、设置洗衣模式、设置马达转速、开始洗衣服等方法。
在初始化时,需要传入品牌brand和容量capacity两个参数。洗衣机门的状态is_closed、洗衣模式__mode和马达转速motor_speed都有默认值。
调用wash()方法时,会根据门的状态和模式来执行相应的操作,最终完成洗衣任务。
步骤:


1定义WashMachine类,初始化时传入品牌和容量两个参数,并设置默认值。
2定义打开/关闭洗衣机门的方法,通过修改is_closed属性来实现。
3定义设置洗衣模式的方法,通过修改__mode属性来实现。
4定义设置马达转速的私有方法,通过修改motor_speed属性来实现。
5定义开始洗衣服的方法,根据门的状态和模式来执行相应的操作,最终完成洗衣任务。
6实例化WashMachine类,传入品牌和容量两个参数,得到一个洗衣机对象。
7调用打开/关闭洗衣机门的方法,模拟打开/关闭洗衣机门的操作。
8调用设置洗衣模式的方法,传入一个参数,设置洗衣模式。
9调用开始洗衣服的方法,根据门的状态和模式来执行相应的操作,最终完成洗衣任务。

 实现:

class WashMachine:
    def __init__(self, brand, capacity):
        """
        初始化
        :param brand: 品牌
        :param capacity:  容量
        """
        self.brand = brand
        self.capacity = capacity
        # 是否关闭
        self.is_closed = False
        # 模式 0:未设定模式 1:轻揉模式 2:狂揉模式
        self.__mode = 0
        # 马达转速
        self.motor_speed = 0

    def open_door(self):
        self.is_closed = False
        print('打开洗衣机门')

    def close_door(self):
        self.is_closed = True
        print('关闭洗衣机门')

    def set_mode(self, new_mode):
        """
        调节模式
        :param new_mode:
        :return:
        """
        if new_mode not in [1, 2]:
            print('设置模式错误')
        else:
            self.__mode = new_mode

    def __set_motor_speed(self, speed):
        """
        设置马达的转速
        :param speed:  1000: 轻揉模式  2000:狂揉模式
        :return:
        """
        self.motor_speed = speed

    def wash(self):
        if not self.is_closed:
            # 洗衣机门是否关闭 ,没有关闭  提示
            print('请关闭洗衣机门,哔哔哔哔...')
            return
        elif self.__mode == 0:
            print('请设置模式')
            return
        
        # 执行下面的操作
        print('放水...')
        print('放满了...')
        if self.__mode == 1:
            print('轻揉模式, 洗内衣')
            # 调节马达转速
            self.__set_motor_speed(1000)
            print('马达转速:{}'.format(self.motor_speed))
            print('开始洗...')
        elif self.__mode == 2:
            print('狂揉模式, 洗外套')
            # 调节马达抓霉素
            self.__set_motor_speed(2000)
            print('马达转速:{}'.format(self.motor_speed))
            print('开始洗...')

        print('洗完了')


machine = WashMachine('海尔', 10)
machine.open_door()
machine.close_door()
machine.set_mode(2)
machine.wash()

封装的范围:

  1. 封装属性
  2. 封装成方法/函数
  3. 封装成类
  4. 封装模块和包

 

2. 继承

继承指的是一个对象直接使用另一个对象的属性或方法

继承的格式:
class 子类名(父类名):

"""------------------ 定义Person类 ------------------"""


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hello(self):
        print('hello from ', self.name)


"""------------------ 定义Student类继承Person ------------------"""


class Student(Person):
    def __init__(self, name, age, height):
        # 调用父类的初始化方法
        super().__init__(name, age)
        # 定义自己的属性
        self.height = height


# 创建学生类
stu = Student('小明', 15, '180')
# 访问属性
print("name: {} age: {} height: {}".format(stu.name, stu.age, stu.height))
# 调用方法
stu.say_hello()

Student类继承自Person

可以使用Person类中定义的属性nameage以及方法say_hello

3. 多态

多态指的是一类事物有多种形态(一个类有多个子类)

多态的概念依赖于继承

中国人、美国人、非洲人都是属于Human人类的子类

对于Human来说有多个子类就称为多态

"""
多态案例
"""
# 父类
class Human:
    def eat(self):
        print('人类吃饭')

# 中国人
class ZhHuman(Human):
    def eat(self):
        print('中国人使用筷子吃饭')

# 美国人
class UsHuman(Human):
    def eat(self):
        print('美国人使用刀叉吃饭')

# 非洲人
class AfricaHuman(Human):
    def eat(self):
        print('非洲人直接用手吃恩希玛')


# 函数
def someone_eat(someone):
    '''
    接收一个具备吃eat功能的对象
    '''
    someone.eat()


# 创建四个对象
human = Human()
zh_human = ZhHuman()
us_human = UsHuman()
africa_huamn = AfricaHuman()

# 调用translate方法
someone_eat(human)
someone_eat(zh_human)
someone_eat(us_human)
someone_eat(africa_huamn)

someone_eat方法需要接收具备eat功能的对象,但是由于ZhHuman USHuman AfricaHuman都具备eat功能(继承了Human)。所以也可以传递到someone_eat方法中

4. 扩展知识

4.1. 鸭子类型

一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟可以被称为鸭子。这就是鸭子类型Duck Typing

对于上述多态中的的someone_eat

class Dog:
    def eat(self):
        print('狗吃骨头')

# 函数
def someone_eat(someone):
    '''
    接收一个具备吃eat功能的对象
    '''
    someone.eat()

dog = Dog()
someone_eat(dog)

someone_eat需要传递一个具备eat方法的对象,但是Dog也具备eat功能,所以也可以传递运行

这是由于python是动态类型语言,不能像C++、Java等静态类型语言一样,限制传递的数据类型

只要运行时发现dog对象有这个功能,就可以在函数中使用

4.2. 多继承

当一个类从多个父类继承属性和方法时,就称为多继承。

多继承格式:
class 子类(父类1,父类2...)

下面是一个使用多继承的示例案例,展示了一个动物类和一个能飞的特性类和游泳的特性类:

class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name} is eating.")

    def sleep(self):
        print(f"{self.name} is sleeping.")


class Flyable:
    def fly(self):
        print(f"{self.name} is flying.")


class Swimmable:
    def swim(self):
        print(f"{self.name} is swimming.")


class Duck(Animal, Flyable, Swimmable):
    def __init__(self, name):
        super().__init__(name)


duck = Duck("Donald")
duck.eat()   # 输出: Donald is eating.
duck.sleep()   # 输出: Donald is sleeping.
duck.fly()   # 输出: Donald is flying.
duck.swim()   # 输出: Donald is swimming.

 

在上面的示例中,Animal是基类,FlyableSwimmable是特性类。Duck类通过多继承从这些类继承了属性和方法。通过调用这些继承的方法,我们可以看到Duck对象具有吃、睡、飞和游泳的行为。

注意,在多继承的情况下,当多个父类中具有相同名称的方法时,解释器将按照方法解析顺序(Method Resolution Order,MRO)来确定使用哪个方法。在上述示例中,Python的默认MRO算法会按照类定义时的顺序来解析方法。在这个例子中,Duck类首先从Animal类继承方法,然后是Flyable类,最后是Swimmable类。

十二、搬家具进房子

1. 搬家具规则

家具

  • 家具分不同的类型,并占用不同的面积
  • 输出家具信息时,显示家具的类型和家具占用的面积

房子

  • 房子有自己的地址和占用的面积
  • 房子可以添加家具
    • 如果房子的剩余面积可以容纳家具,提示家具添加成功;
    • 否则提示添加失败
  • 输出房子信息时,可以显示房子的地址、占地面积、剩余面积
  • 查看房子中所有的家具

2. 类的设计

可以提取两个类:家具类Item和房子类House

每个类具备的属性和方法如下:

 3. 家具类

1.使用 Item 类可以创建 家具对象
2.家具有两个属性:
	家具类型 type:字符串
	家具面积 area:整数
3.实现__str__方法
4.显示家具的 type 和 area 属性

 4. 房子类

1.使用 House 类可以创建 房子对象
2.房子有四个属性:
	地址 address:字符串
	房子面积 area:整数
	房子剩余面积 free_area:整数,默认为房子的面积
	家具列表 items:列表
3.实现__str__方法
	显示房子的 address 、area、free_area 属性
4.实现add_item方法,提供item参数来添加家具
	如果 可以容纳家具:
		家具 加入 item属性
		剩余面积 减少
	如果 不能容纳家具: 提示家具添加失败

5. 主程序逻辑

1. 创建 家具对象, 输出 家具信息
2. 创建 房子对象, 输出 房子信息
3. 房子添加家具, 输出 房子信息

6. 代码实现 

"""------------------ Item家具类 ------------------"""
class Item:
    def __init__(self, type, area):
        '''
        创建家具类的初始化方法
        :param type: 家具类型
        :param area: 家具面积
        '''
        self.type = type
        self.area = area

    # def __str__(self):
    #     return 'str家具类型: {},家具占用面积: {}'.format(self.type, self.area)

    def __repr__(self):
        return 'repr家具类型: {},家具占用面积: {}'.format(self.type, self.area)


"""------------------ House房子类 ------------------"""
class House:
    def __init__(self, address, area):
        '''
        房子的初始化方法
        :param address: 房子地址
        :param area: 房子面积
        '''
        self.address = address
        self.area = area
        # 剩余面积
        self.free_area = self.area
        # 家具列表
        self.items = []

    def __str__(self):
        return '房子地址: {},占地面积: {},剩余面积: {}'.format(self.address, self.area, self.free_area)

    def add_item(self, item):
        """
        添加家具到房子中
        :param item: 家具类Item的实例
        :return:
        """
        if self.free_area >= item.area:
            # 家具添加到列表中
            self.items.append(item)
            # 修改剩余面积
            self.free_area -= item.area
            # 可以添加
            print('添加成功')
        else:
            # 不能添加
            print('面积不足, 不能添加家具')


# 创建家具
item1 = Item('桌子', 40)
item2 = Item('椅子', 10)
item3 = Item('家庭影院', 80)
print(item1)
print(item2)
print(item3)

# 创建房子
house = House('深圳湾一号', 100)
# 打印家具
print(house)

print("---------------------------------------------")
# 添加家具
house.add_item(item1)
house.add_item(item2)
house.add_item(item3)
print(house)
print("所有家具: ", house.items)

扩展:

  • __str__方法返回一个友好的、可读性较高的字符串,主要用于用户可见的输出,强调可读性和易理解性。常用于直接print对象。
  • __repr__方法返回一个准确和详细的字符串,主要用于开发和调试过程中,强调准确性和完整性。常用于打印listsetdict等内部的所有对象

 

相关推荐

  1. 高效嵌入系统架构设计

    2024-04-25 11:38:04       36 阅读
  2. Python 虚拟环境 + 嵌入 部署方案

    2024-04-25 11:38:04       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-25 11:38:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-25 11:38:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-25 11:38:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-25 11:38:04       18 阅读

热门阅读

  1. 简单的接口自动化实现demo

    2024-04-25 11:38:04       15 阅读
  2. Spark pivot数据透视从句

    2024-04-25 11:38:04       17 阅读
  3. vue keepAlive的使用

    2024-04-25 11:38:04       14 阅读
  4. 深入理解Vue插槽

    2024-04-25 11:38:04       12 阅读
  5. 利用API内存地址参数执行shellcode

    2024-04-25 11:38:04       11 阅读
  6. Linux打开html

    2024-04-25 11:38:04       12 阅读
  7. 常用的Git和Linux命令

    2024-04-25 11:38:04       13 阅读
  8. unity快捷键

    2024-04-25 11:38:04       12 阅读
  9. 云托管 代码 项目

    2024-04-25 11:38:04       10 阅读
  10. 数据解读:AARRR系列:激活用户,开启留存之路

    2024-04-25 11:38:04       13 阅读
  11. 【SAP ME 26】SAP ME创建开发组件(DC)mobile

    2024-04-25 11:38:04       13 阅读
  12. Apache Hadoop 输入格式示例

    2024-04-25 11:38:04       13 阅读
  13. Set实现(2)| LinkedHashSet

    2024-04-25 11:38:04       15 阅读