python基础

一、字符串、列表、元组、字典、集合

(一)字符串

1 .字符串的介绍

字符串不可变

2 .字符串输入输出

3.字符串的下标和切片

字符串切片格式:字符串变量[start:end]左闭右开   字符串变量[start:end:step]默认是从左向右一个一个取元素   step:   1.步长   2.方向 step正数--从左向右,step负数--从右向左

4.字符串的常见操作

(1)获取长度--len

(2)查找内容--find、index、rfind、rindex

find:从左向右查找,只要找到一个符合要求的则返回位置,如果没有找到任何符合要求的则返回-1 rfind:从右向左查找,只要找到一个符合要求的则返回位置,如果没有找到任何符合要求的则返回-1

index与find区别:index也是表示查找,如果找不到会报错

(3)判读--startswitch、endswitch、isalpha、isdigit、isalnum、isspase、isupper

startswitch:判断字符串是否以XX开头

endswitch:判断字符串是否以XX结尾

isalpha:判断是否是纯字母组成

isdigit:判断是否是纯数字组成

isalnum:判断是否是字母、数字组成

isspace:判断是否全部由空格组成

isupper:判断是否全部是大写字母组成的

islower:判断是否全部是小写字母组成的

(4)计算出现次数--count

count:统计指定字符的个数

(5)替换内容--replace

replace(old,new,count) count--没传值时,默认全部替换

(6)切割字符串--split、rsplit、splitlines、partition、rpartition

split('分割符',maxsplit)—返回结果是一个列表,maxsplit最多分割次数

rsplit('分割符')—从右向左分割

splitlines--按行分割

(7)修改大小写--capitalize、title、upper、lower

title--首字母大写

capitalize—把一句话中每个单词的第一个字母大写

(8)空格处理--ljust、rjust、center、lstrip、rstrip、strip

strip--去除左右空格

lstrip--去除左边空格

rstrip--去除右边空格

centet -- 添加空格,控制字符串的对齐方式为居中

ljust -- 添加空格,控制字符串的对齐方式为左对齐

rjust -- 添加空格,控制字符串的对齐方式为右对齐

(9)字符串拼接--join

注意:在Python中,字符串是不可变的!所有的字符串相关方法,都不会 改变原有字符串,都是返回一个结果,再这个新的返回值里,保留了执行后的结果!

5.格式化字符串

(二)列表

1.列表的声明

定义列表的格式:[元素1,元素2,元素3,...,元素n]

如何定义一个列表?

        空列表:[]

        有内容的列表:['A','B'],[[],[],[]]

列表中的元素可以是不同类型的

2.列表的增删改查

(1)添加元素

append()---追加元素

extend()---合并两个列表

insert(下标,元素)---在指定位置添加元素

两个列表整合为一个列表

list1 = ['火腿肠']
list2 = ['面包']

list1 += list2  或 list1.extend(list2)

print(list1)  //['火腿肠', '面包']

(2)删除元素

pop(index)---根据下标删除列表中的元素。下标不能超出范围,如果下标超出则会报错

pop()---如果不填下标,会从后往前依次删除

remove(element)---根据元素名称删除,只删除第一个元素,如果元素不存在的时候则会报错

del(index)---根据下标删除元素

clear()---清空列表

del 列表---删除列表,删除列表的指针指向

list3 = ['火腿肠','酸奶','酸奶','辣条','面包','薯条','酸奶']
for i in list3:
        if i == '酸奶':
                list3.remove(i)
print(list3)  //['火腿肠', '辣条', '面包', '薯条', '酸奶']

 为什么会出现漏删的情况?

(3)修改元素

根据下标修改

insert(位置,元素)---元素占了位置,其他元素只能向后移动

(4)查找元素

元素 in 列表---返回bool类型

元素 not in 列表---元素不在列表中返回true

列表.index(元素)---返回该元素的下标,如果没有则报错

列表.count(元素)---返回整数

(5)列表的排序

sort()---默认升序,可以通过reverse参数来控制升序还是降序

sort(reverse=True)---降序排列

reverse()---对原有列表进行反转

3.遍历列表

(1)while循环遍历

(2)for循环遍历

元素交换

a,b = b,a

4.列表嵌套

5.深拷贝浅拷贝

拷贝:数据一分二的复制过程,防止数据被意外破话。

深拷贝:复制整个依懒的变量。占用内存较少,修改深层数据会被破坏

浅拷贝:复制过程中,只复制一层变量,不会复制深层变量绑定的对象的复制过程。占用内存较多

import copy
list01 = ['北京',['上海','深圳']]
#赋值:传递列表的地址,列表只有一份
list02 = list01
#浅拷贝--第一层两份,深层两份
list03 = list01[:]
#深拷贝--所有层2份
list04 = copy.deepcopy(list01)
list04[0] = '北京04'
list04[1][1] = '深圳04'

6.列表与字符串相互转换

(1)列表转字符串

result = "连接符".join(列表)

#在终端中,循环录入字符串,如果录入为空则停止循环
list = []
while True:
    n = input("请输入:")
    if n != '':
        list.append(n)
    else:
        break
result = '_'.join(list)
print(result)

(2)字符串转列表

列表 = “a-b-c-d”.split(“分隔符”)

'''
练习:将下列英文语句按照单词进行翻转.

转换前:To have a government that is of people by people for people

转换后:people for people by people of is that government a have To
'''
str = 'To have a government that is of people by people for people'
list = str.split(' ')
print(list)
list.reverse()
str1 = ' '.join(list)
print(str1)

7.列表推导式

(1)概念

使用简易的方法,将可迭代对象转换成列表

(2)语法

变量 = [表达式 for 变量 in 可迭代对象]

变量 = [表达式 for 变量 in 可迭代对象 if条件]

(3)说明

如果条件不满足,则可迭代对象的元素将被丢弃

''''
练习,生成10-30之间能被3或者5整除的数字
'''
list = [item for item in range(10,31) if item%3==0 or item%5==0]
print(list)

(三)元组

Python的元组与列表类似,不同之处在于元组的元素不能修改(增、删、改),元组使用小括号,列表使用方括号

列表内存机制:预留空间+自动扩容

元组内存机制:按需分配

Python有哪些数据类型?

可变数据类型和不可变数据类型

可变类型:预留空间+按需分配

不可变类型:按需分配

可变数据类型优点:适应需求变化

可变数据类型缺点:占用空间较大

不可变数据类型优点:占用空间较小

不可变数据类型缺点:操作不方便

1.元组的声明

(1)创建空元组

        元组名 = ()

        元组名 = tuple()

(2)创建非空元组

        元组名  =  (10,)

        元组名 = (10,20,30)

        元组名 = 100,200,300

        元组名 = tuple(可迭代对象)

注意:如果元组中只有一个元素,必须加逗号

拆包: 多个变量 = 容器

t = (10,20)
a,b = t
print(a) # 10
print(b) # 20
#元组地址练习
name = '张无忌'
names = ['赵敏','周芷若']
tuple01 = ('张翠山',name,names)
name = '无忌哥哥'
tuple01[2][0] = '敏儿'
print(tuple01)  #('张翠山', '张无忌', ['敏儿', '周芷若'])

2.获取元素

变量 = 元组名[索引]

变量 = 元组名[切片] # 赋值给变量的是切片所创建的新列表

3.遍历元组

(1)正向遍历

        for 变量名 in 元组名:

        变量名就是元素

(2)反向遍历

        for 索引名 in range(len(列表名)-1,-1,-1):

        元组名[索引名]就是元素

4.作用

(1) 元组与列表都可以存储一系列变量,由于列表会预留内存空间,所以可以增加元素。

(2) 元组会按需分配内存,所以如果变量数量固定,建议使用元组,因为占用空间更小。

(3) 应用:

变量交换的本质就是创建元组:x, y = (y, x )

格式化字符串的本质就是创建元组:"姓名:%s, 年龄:%d" % ("tarena", 15)

(四)字典

1.定义

(1)由一系列键值对组成的可变散列容器

(2)散列:对键进行哈希运算,确定在内存中的存储位置,每条数据存储后无先后顺序

(3)键必须唯一且不可变(字符串/数字/元组),值没有限制

2.字典的操作

(1)字典的创建

        字典名 = {键1:值1,键2:值2}

        字典名 = dict (可迭代对象)

dict = {
    'name':'刘慧杰',
    'age': 25,
    'sex': '女'
}

(2)添加元素

        语法:字典名[键] = 数据

        说明:  键不存在,创建变量。键存在,修改值

(3)获取元素

        变量 = 字典名[键]   # 没有键则错误

(4)遍历字典

dict = {
    'name':'刘慧杰',
    'age': 25,
    'sex': '女'
}
for key in dict:
    print(dict[key])  

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

for item in dict.items():
    print(item)

for key,value in dict.items():
    print(key,value)

(5)删除元素

del 字典名['键']

3.字典转换成列表

dict = {
    'name':'刘慧杰',
    'age': 25,
    'sex': '女'
}
print(list(dict))  #['name', 'age', 'sex']
print(list(dict.values()))  #['刘慧杰', 25, '女']
print(list(dict.items()))  #[('name', '刘慧杰'), ('age', 25), ('sex', '女')]

4. 字典推导式

(1) 定义

使用简易方法,将可迭代对象转换为字典。

(2) 语法

{键:值 for 变量 in 可迭代对象}

{键:值 for 变量 in 可迭代对象 if 条件}

'''
将两个列表,合并为一个字典
姓名列表["张无忌","赵敏","周芷若"]
房间列表[101,102,103]
{101: '张无忌', 102: '赵敏', 103: '周芷若'}
'''

name = ["张无忌","赵敏","周芷若"]
room = [101,102,103]
dict = {}

'''for i in range(len(name)):
    key = name[i]
    value = room[i]
    dict[key] = value
print(dict)'''

dict = {name[i]:room[i] for i in range(len(name)) }
print(dict)

'''
练习2:
颠倒练习1字典键值
{'张无忌': 101, '赵敏': 102, '周芷若': 103}
'''
new_dict  = {v:k for k,v in dict.items()}
print(new_dict)

(五)Python格式化

1.字符串插值

使用字符串插值,您可以将变量嵌入到字符串中。

name = "Alice"
age = 30
print(f"My name is {name} and I'm {age} years old.")

在Python 3.5及以下版本中,您可以使用.format()方法执行字符串插值

name = "Alice"
age = 30
print("My name is {} and I'm {} years old.".format(name, age))

2.百分号格式化

name = "Alice"
age = 30
print("My name is %s and I'm %d years old." % (name, age))

3.模板字符串格式化

4.字符串拼接

name = "Alice"
age = 30
print("My name is " + name + " and I'm " + str(age) + " years old.")

二、函数

1.pycharm快捷键

Ctrl + P 参数信息(在方法中调用参数)

Ctrl + Q 快速查看文档

2.定义

(1) 用于封装一个特定的功能,表示一个功能或者行为。

(2) 函数是可以重复执行的语句块, 可以重复调用。

3.作用

提高代码的可重用性和可维护性(代码层次结构更清晰)。

4.基础语法

4.1定义函数

(1) 语法

def 函数名(形式参数):

        函数体

(2) 说明

def 关键字:全称是define,意为”定义”。

函数名:对函数体中语句的描述,规则与变量名相同。

形式参数:函数定义者要求调用者提供的信息。

函数体:完成该功能的语句。

(3) 函数的第一行语句建议使用文档字符串描述函数的功能与参数。

4.2调用函数

(1) 语法

函数名(实际参数)

(2) 说明

根据形参传递内容。

4.3函数返回值

(1) 定义

函数定义者告诉调用者的结果。

(2) 语法

return 数据

(3) 说明

return后没有语句,相当于返回 None。

函数体没有return,相当于返回None。

5.函数内存分布

#1.将函数代码加入到内存代码区
def func01(p1,p2):
    data = p1+p2
    return data
num01 = 10
#2.调用函数时会在内存中开辟一块空间
#存储函数内部创建的变量
res = func01(num01,20)
#3.函数执行后,改空间立即释放
print(res)

6.可变/不可变类型在传参时的区别

(1) 不可变类型参数有:

数值型(整数,浮点数)

布尔值bool

None 空值

字符串str

元组tuple

(2) 可变类型参数有:

列表 list

字典 dict

(3) 传参说明:

不可变类型的数据传参时,函数内部不会改变原数据的值。

可变类型的数据传参时,函数内部可以改变原数据。

7.函数参数

7.1 实参传递方式argument

7.1.1 位置实参

定义:实参与形参的位置依次对应。

def fun01(p1, p2, p3):
    print(p1)
    print(p2)
    print(p3)
 
# 位置实参:根据顺序与形参进行对应
fun01(1, 2, 3)
7.1.2 序列实参

定义:实参用*将序列拆解后与形参的位置依次对应。

一序列拆分为多参数,按照顺序对应

def func01(p1, p2, p3):
    print(p1, p2, p3)

# 序列实参:拆,按照顺序与形参对应
list01 = [1, 2, 3]
name = "孙悟空"
tuple01 = (4, 5, 6)
# func01(list01)
func01(*list01)  # 拆  1, 2, 3
func01(*name)  # 拆  孙 悟 空
func01(*tuple01)  # 拆  4, 5, 6
7.1.3 关键字实参

定义:实参根据形参的名字进行对应。

def fun01(p1, p2, p3):
    print(p1)
    print(p2)
    print(p3)
    
# 关键字实参:根据名字与形参进行对应
fun01(p1=1, p2=2, p3=3)
fun01(p2=2, p1=1, p3=3)
7.1.4 字典关键字实参

(1) 定义:实参用**将字典拆解后与形参的名字进行对应。

(2) 作用:配合形参的缺省参数,可以使调用者随意传参。

一字典拆分为多参数,按照名称对应,键名必须和形参名一致

def func01(p1, p2, p3):
    print(p1, p2, p3)
    
# 字典实参:拆,按照名称与形参对应
dict01 = {"p2":"B","p1":"A","p3":"C"}
func01(**dict01) #p1,p2,p3

7.2形参定义方式parameter

7.2.1 默认形参

(1) 语法:

def 函数名(形参名1=默认值1, 形参名2=默认值2, ...):

函数体

(2) 说明:

默认参数必须自右至左依次存在,如果一个参数有默认值,则其右侧的所有参数都必须有默认值

def func01(p1 =0, p2="", p3=100):
    print(p1)
    print(p2)
    print(p3) 
    
func01(p2=2)
func01(p2=2,p3=3)
# 支持同时使用位置实参与关键字实参
func01(1,p3=3)
# 注意1:先位置实参,后关键字实参
# func01(p1 =1,2,3) # 错误
7.2.2 位置形参

语法:

def 函数名(形参名1, 形参名2, ...):

函数体

7.2.3 命名关键字形参

(1) 语法:

def 函数名(*args, 命名关键字形参1, 命名关键字形参2, ...): 函数体

def 函数名(*, 命名关键字形参1, 命名关键字形参2, ...):

函数体

(2) 作用:

强制实参使用关键字传参

# 命名关键字形参:
# 星号元组形参后面的位置形参
# 限制实参必须是关键字实参
def func01(*args, p1, p2):
    print(args)
    print(p1)
    print(p2)


func01(p1=1, p2=2)
func01(1, 2, 3, p1=1, p2=2)


def func02(p1, *, p2=0):
    print(p1)
    print(p2)


# 通常星号后面的命名关键字形参属于辅助参数,可选.
func02(1)
func02(1, p2=2)
7.2.4 星号元组形参

(1) 语法:

def 函数名(*元组形参名):

函数体

(2) 作用:

可以将多个位置实参合并为一个元组

(3) 说明:

一般命名为'args'

形参列表中最多只能有一个

# 位置实参数量可以无限
def func01(*args):
    print(args)

func01()  # 空元组
func01(1, 2, 34)  # (1, 2, 34)
# 不支持关键字实参
# func01(args = 1,a=1)
7.2.5 双星号字典形参

(1) 语法:

def 函数名(**字典形参名):

函数体

(2) 作用:

可以将多个关键字实参合并为一个字典

(3) 说明:

一般命名为'kwargs'

形参列表中最多只能有一个

# 关键字实参数量无限
def func01(**kwargs):
    print(kwargs) # {'a': 1, 'b': 2}

func01(a=1,b=2)
# func01(1,2,3) # 报错
7.2.6 形参自左至右的顺序

位置形参 --> 星号元组形参 --> 命名关键字形参 --> 双星号字典形参

def fun01(list_target):
    print(list_target)

def fun02(*args):
    print(args)

def fun03(*args,**kwargs):
    print(args)
    print(kwargs)

def fun04(p1,p2,*,p4,**kwargs):
    print(p1)
    print(p2)
    print(p4)
    print(kwargs)

fun01([1,2,3])
fun02(1,2,3)
fun02(*[1,2,3])
fun03(1,2,3,a=4,b=5)
fun04(10,20,p4=30,a=4,b=5)

三、面向对象

1.概述

1.1 面向过程

(1) 定义:分析出解决问题的步骤,然后逐步实现。

例如:婚礼筹办

-- 请柬(选照片、措词、制作)

-- 宴席(场地、找厨师、准备桌椅餐具、计划菜品、购买食材)

-- 仪式(定婚礼仪式流程、请主持人)

(2) 公式:程序 = 算法 + 数据结构

(3) 优点:所有环节、细节自己掌控。

(4) 缺点:考虑所有细节,工作量大。

1.2 面向对象

(1) 定义:找出解决问题的人,然后分配职责。

例如:婚礼筹办

-- 发请柬:找摄影公司(拍照片、制作请柬)

-- 宴席:找酒店(告诉对方标准、数量、挑选菜品)

-- 婚礼仪式:找婚庆公司(对方提供司仪、制定流程、提供设备、帮助执行)

(2) 公式:程序 = 对象 + 交互

(3) 优点

a. 思想层面:

-- 可模拟现实情景,更接近于人类思维。

-- 有利于梳理归纳、分析解决问题。

b. 技术层面:

-- 高复用:对重复的代码进行封装,提高开发效率。

-- 高扩展:增加新的功能,不修改以前的代码。

-- 高维护:代码可读性好,逻辑清晰,结构规整。

(4) 缺点:学习曲线陡峭。

2. 类和对象

(1) 抽象:从具体事物中抽离出共性、本质,舍弃个别、非本质过程。

(2) 类:一个抽象的概念,即生活中的”类别”。

(2) 对象:类的具体实例,即归属于某个类别的”个体”。

(3) 类是创建对象的”模板”。

2.1 语法

2.1.1 定义类

(1) 代码

class 类名:
	"""
		文档说明
	"""
     def __init__(self,参数):
		self.实例变量 = 参数

	 def 实例方法(self,参数):
        pass

(2) 说明

-- 类名所有单词首字母大写.

-- init 也叫构造函数,创建对象时被调用,也可以省略。

-- self 变量绑定的是被创建的对象,名称可以随意。

2.1.2 实例化对象

(1) 代码

对象名 = 类名(数据)

(2) 说明

-- 对象名存储的是实例化后的对象地址

-- 类名后面的参数按照构造函数的形参传递

2.2 实例成员

实例就是对象(具体化)

成员包括变量和方法

2.2.1 实例变量

(1) 语法

a. 定义:对象.变量名

b. 调用:对象.变量名

(2) 说明

a. 首次通过对象赋值为创建,再次赋值为修改.

b. 通常在构造函数(__init_)中创建实例变量

(3) 每个对象存储一份,通过对象地址访问

(4) 作用:描述某个对象的数据。

(5) __dict__:对象的属性,用于存储自身实例变量的字典。

class Person:
    #数据成员
    def __init__(self, height, name=None, sex='男'):
        self.height = height
        self.name = name
        self.sex = sex
    #方法成员
    def work(self):
        print(self.name)

class Phone:
    def __init__(self, brand=None, price=None, color=None):
        self.brand = brand
        self.price = price
        self.color = color

    def tonghua(self):
        print('手机可以通话')

xiaomi = Phone('小米',2000,'白色')
xiaomi.tonghua()

print(xiaomi.__dict__)
2.2.2 实例方法

(1) 定义

def 方法名称(self, 参数):
         方法体

(2) 调用:

对象.方法名称(参数)
    # 不建议通过类名访问实例方法

(3) 说明

-- 至少有一个形参,第一个参数绑定调用这个方法的对象,一般命名为self。

-- 无论创建多少对象,方法只有一份,并且被所有对象共享。

(4) 作用:表示对象行为。

class Epidemic:
    def __init__(self, region="", new=0, now=0, total=0):
        self.region = region
        self.new = new
        self.now = now
        self.total = total

# 疫情信息
list_epidemic = [
    Epidemic("台湾",16,2339,16931),
    Epidemic("陕西",182,859,1573),
    Epidemic("浙江",2,505,2008),
]


def print_all_epidemic():
    ''' --打印所有疫情信息,'''
    for epidemic in list_epidemic:
        print(f"{epidemic.region}新增{epidemic.new},现有{epidemic.now},总计{epidemic.total}")


def find_region_by_new_gt_value():
    ''' --查找新增人数大于10的地区名称(将结果存入新列表)'''
    new_list = []
    for epidemic in list_epidemic:
        if epidemic.new > 10:
            new_list.append(epidemic)
    return new_list


def get_max_epidemic_by_now():
    '''# --查找现有人数最大的地区信息(结果为字典)'''
    max =  list_epidemic[0]
    for i in range(1,len(list_epidemic)):
        if list_epidemic[i].now > max.now:
            max = list_epidemic[i]
    return max


def descending_order_by_now():
    '''--根据现有人数对疫情信息降序(大->小)排列'''
    for r in range(len(list_epidemic) - 1):
        for c in range(r + 1, len(list_epidemic)):
            if list_epidemic[r].new < list_epidemic[c].new:
                list_epidemic[r], list_epidemic[c] = list_epidemic[c], list_epidemic[r]





print_all_epidemic()

re2 = find_region_by_new_gt_value()
for item in re2:
    print(item.__dict__)

re1 = get_max_epidemic_by_now()
print(re1.__dict__)

descending_order_by_now()
for item in list_epidemic:
    print(item.__dict__)
print(list_epidemic)
2.2.3 跨类调用

方法一:直接创建对象

# 写法1:直接创建对象
# 语义:老张每次创建一辆新车去
class Person:
    def __init__(self, name=""):
        self.name = name

    def go_to(self,position):
        print("去",position)
        car = Car()
        car.run()

class Car:
    def run(self):
        print("跑喽~")

lz = Person("老张")
lz.go_to("东北") 

方法二:在构造函数中创建对象
 

# 写法1:直接创建对象
# 语义:老张每次创建一辆新车去
class Person:
    def __init__(self, name=""):
        self.name = name

    def go_to(self,position):
        print("去",position)
        car = Car()
        car.run()

class Car:
    def run(self):
        print("跑喽~")

lz = Person("老张")
lz.go_to("东北")

方法三:通过参数传递

# 方式3:通过参数传递
# 语义:老张用交通工具去
class Person:
    def __init__(self, name=""):
        self.name = name

    def go_to(self,vehicle,position):
        print("去",position)
        vehicle.run()

class Car:
    def run(self):
        print("跑喽~")

lz = Person("老张")
benz = Car()
lz.go_to(benz,"东北")

3、三大特征

3.1 封装性

3.1.1.数据角度

(1)定义:将一些基本数据类型复合成一个自定义类型

(2)优势

   -- 将数据与对数据的操作相互关联

   -- 代码可读性更高(类是对象的模板)。

3.1.2 行为角度

(1) 定义:

向类外提供必要的功能,隐藏实现的细节。

(2) 优势:

简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。

- 作用:无需向类外提供的成员,可以通过私有化进行屏蔽。

(3) 私有成员:

-- 做法:命名使用双下划线开头。

-- 本质:障眼法,实际也可以访问。

私有成员的名称被修改为:类名__成员名,可以通过__dict__属性查看。

class MyClass:
    def __init__(self, data):
        self.__data = data

    def __func01(self):
        print("func01执行了")

m01 = MyClass(10)
# print(m01.__data) # 无法访问
print(m01._MyClass__data)
print(m01.__dict__)  # {'_MyClass__data': 10}
# m01.__func01() # 无法访问
m01._MyClass__func01()

3.2 继承

3.2.1 继承方法

(1) 语法:

class 父类:
   def 父类方法(self):
     方法体

class 子类(父类):
   def 子类方法(self):
     方法体

儿子 = 子类()
儿子.子类方法()
儿子.父类方法()

(2) 说明:

子类直接拥有父类的方法.

3.2.2 内置函数

(1) isinstance(对象, 类型)

返回指定对象是否是某个类的对象。

(2) issubclass(类型,类型)

返回指定类型是否属于某个类型。

(3) 演示

# 对象 是一种 类型: isinstance(对象,类型)
# 老师对象 是一种 老师类型
print(isinstance(qtx, Teacher))  # True
# 老师对象 是一种 人类型
print(isinstance(qtx, Person))  # True
# 老师对象 是一种 学生类型
print(isinstance(qtx, Student))  # False
# 人对象 是一种 学生类型
print(isinstance(p, Student))  # False

# 类型 是一种 类型: issubclass(类型,类型)
# 老师类型 是一种 老师类型
print(issubclass(Teacher, Teacher))  # True
# 老师类型 是一种 人类型
print(issubclass(Teacher, Person))  # True
# 老师类型 是一种 学生类型
print(issubclass(Teacher, Student))  # False
# 人类型 是一种 学生类型
print(issubclass(Person, Student))  # False

# 是的关系
# 老师对象的类型 是 老师类型
print(type(qtx) == Teacher)  # True
# 老师对象的类型 是 人类型
print(type(qtx) == Person)  # False
3.2.3 继承数据

(1) 语法

class 子类(父类):
 def __init__(self,父类参数,子类参数):
   super().__init__(参数) # 调用父类构造函数
   self.实例变量 = 参数

(2) 说明

子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()函数调用父类的构造函数,以确保父类实例变量被正常创建

3.2.4 定义

(1) 概念: 重用现有类的功能,并在此基础上进行扩展。

(2) 说明:子类直接具有父类的成员(共性),还可以扩展新功能。

(3) 相关知识

-- 父类(基类、超类)、子类(派生类)。

-- 父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。

-- 单继承:父类只有一个(例如 Java,C#)。

-- 多继承:父类有多个(例如C++,Python)。

-- Object类:任何类都直接或间接继承自 object 类。

3.3 多态

3.3.1 定义

(1) 字面意思:对于一种行为有不同表现形态。

(2) 概念:对于父类的一个方法,在不同的子类上有不同体现。

(3) 说明:编码时调用父类方法,运行时传递子类对象执行子类方法。

3.3.2 重写

(1) 定义:在子类定义与父类相同的方法。

(2) 作用:改变父类行为,体现子类个性。

(3) 算数运算符

(4)复合运算符重载

注:+和+=不一样

+=内部调用__iadd__,会返回自身对象

+内部调用__add__,会返回新对象

(5) 比较运算重载

''' 只需要定义好eq和gt其他的会自动匹配'''
class Vector(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

pos1 = Vector(1,1)
pos2 = Vector(1,1)
#== 是按照eq去比较
print(pos1 == pos2)
# is是按照地址去比较
print(pos1 is pos2)

#Python语言的内存优化机制
#对象池:创建对象是,会判断池中是否具有相同的对象,如果有会返回地址,如果没有会开辟空间
#类型有__eq__函数,按照内容比较
#没有__eq__函数,按照地址比较
a = ['a','b']
b = ['a','b']
print(a == b)
print(a is b)

print(['A'] == ['A'])

四、MVC架构

经典MVC架构中,M是模型(model) V是视图(view) C是控制器(contrller)

from typing import List

class StudentModel:
    '''学生数据模型:封装View与controller之间的数据'''
    def __init__(self, name='',age=0,score=0,sid=''):
        self.name = name
        self.age = age
        self.score = score
        self.sid = sid

class StudentView:
    ''' 学生视图,处理界面逻辑 输入输出'''
    def __init__(self):
        self.controller = StudentController()
    def display_menu(self):
        print("按1键录入学生信息")
        print("按2键显示学生信息")
        print("按3键删除学生信息")
        print("按4键修改学生信息")

    def select_menu(self):
        number = input("请输入:")
        if number == '1':
            #重点1:本类调用实例方法
            self.input_student()
        elif number == '2':
            self.display_student()

    def input_student(self):
        #重点2:每次使用新Model存储学生信息
        model = StudentModel()
        model.name = input("请输入学生姓名")
        model.age = input("请输入学生年龄")
        model.score = input("请输入学生分数")
        #重点3:每次使用旧的contrller添加学生信息
        self.controller.add_student(model)

    def display_student(self):
        for st in self.controller.list_student:
            print(f'{st.name}的年龄为{st.age},成绩是{st.score}')


class StudentController:
    '''
    学生控制器:负责核心功能的算法
    '''
    def __init__(self):
        self.list_student = []  #type:List[StudentModel]
        self.sid = 1001
    def add_student(self,new):
        #自增长的数
        new.sid = self.sid
        self.sid += 1
        self.list_student.append(new)

view = StudentView()
while True:
    view.display_menu()
    view.select_menu()

  • 20
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值