使用对象组织数据
在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的
- 在程序中设计表格,我们称之为:
设计类 (class)
class Student:
name = None # 记录学生姓名。这里none是初始化值
2.在程序中打印生产表格,我们称之为: 创建对象
#基于类创建对象
stu_1 = Student
stu_2 = Student()
3.在程序中填写表格,我们称之为:
对象属性赋值
stu_1.name =“周杰轮"#为学生1对象赋予名称属性值
stu_2.name = “林军杰"#为学生2对象赋予名称属性值
- 方法调用自身成员,需要在参数列表中添加形参self
构造方法
Python类可以使用:
__init__()
方法,称之为构造方法。
可以实现:
在创建类对象(构造类)的时候,会自动执行
在创建类对象(构造类)的时候,将传入参数自动传递给 __init__
方法使用
class Student:
name = None
def __init__(self,name):
self.name = name
print("创建了一个Student对象")
def printSelf(self):
print(f"我是{self.name}")
stu1 = Student("小希")
同时需要自带self
其他常见类内置方法
又叫魔术方法
__init__构造方法
_str_ 字符串方法
class student:
def __init__(self,name, age):
se7f.name = name
self.age = age
student = student("周杰轮",11)
print(student)# 结果:< main__.student object at 0x000002200CFD7040>
print(str(student)) # 结果:<main.student obiect at 0x000002200CFD7040>
当类对象需要被转换为字符串之时,会输出如上结果 (内存地址)
内存地址没有多大作用,我们可以通过重载__str__
方法,控制类转换为字符串的行为
class Student:
name = None
age = None
def __init__(self, name: "str", age: "int"):
self.name = name
self.age = age
def __str__(self) -> str:
return f"这是Student对象,name成员{self.name},age成员{self.age}"
stu1 = Student("reimu", 24)
print(str(stu1))
_lt_ 小于符号,大于符号比较
实则重载小于符号为true时的规律,如
class Student:
age = None
name = "223"
def __init__(self, age) -> None:
self.age = age
def __lt__(self, other: "Student"):
return self.age < other.age
print(Student(20) < Student(15))
_le_ 小于等于,大于等于符号比较
= <= 规则类似于__lt__
_eq_ ==符号比较
规则也类似__lt__,但规则默认是判断内存地址是否相等
面向对象OOP
基于模板(类)去创建实体(对象),使用对象完成功能开发
三大特性:封装,继承,多态
封装
私有成员
不公开的属性和行为
变量和方法只需以两个下划线开头即可
类外访问成员不报错,无效。访问方法报错。
和c++相同,可以被其他的成员使用
实际意义
在类中提供仅供内部使用的属性和方法
而不对外开放(类对象无法使用 )
继承
概念,使用方式,pass关键字
class 类名(父类名):
类内容体
继承分为单继承和多继承
多继承,继承多个父类
class Xiaomi(Phone,NFCreader,RemoteControl):
pass
多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级
先继承的保留,后继承的被覆盖
比如Phone的producer成员是"Huawei"
NFCreader的producer成员是"Samsung"
那么最终Xiaomi的producer是"Huawei"
复写和使用父类成员
子类继承父类成员和方法后,不满意可进行复写
在子类中重新定义同名的属性和方法即可
(属性的是初始化的量)
一旦复写成功后,那么类调用成员的时候就会调用复写后的新成员
如果需要调用被复写的父类成员,需要特殊的调用方法:
- 直接调用父类成员
- 使用成员变量:父类名.成员变量
- 使用成员方法:父类名.成员方法(self)
- 使用**super()**调用父类成员
- 使用成员变量:super().成员变量
- 使用成员方法:super().成员方法()
变量的类型注解
为什么需要:定义函数中的类型方法自动补齐
# 例如这里,虽然心中所想data是list类型,但是不会补齐
def func(data):
data.app^
用处:标注数据类型
- 变量的类型注解
- 函数(方法)形参列表和返回值的类型
基础语法:
变量:类型
var_1:int = 10
var_2:bool = False
# 类对象:
class Student:
pass
stu:Student = Student()
# 基础容器类型注解
my_list:list = [1,2,3]
my_dict:dict = {"it":23}
# 容器类型详细注解
my_list:list[int] = [1,2,3]
my_tuple:tuple[str,int,bool] = ('it',666,True)
my_set:set[int] = {1,2,3}
my_dict:dict[str,int] = {'it':666}
'''
注意:
元组类型设置类型详细注解,需要将每一个元素都标记出来
字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
'''
# 另外可以通过注释进行类型注解
# 语法: #type:类型
var_1 = random.randint(1,10) # type: int
类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会导致错误
形参注解
def func(data:list):
pass
返回值进行类型注解
def func(data:list)->list:
return data
pass
但如果语法没有问题的话,其实你传个1其实不会error只会warning
union类型
# 类型统一
my_list:list[int] = [1,2,3]
my_dict:dict[str,int] = {"age":11, "num":3}
# 如何描述混合类型?
my_list = {1, 2, "itcast", "itheima"}
my_dict = {"name":"周", "age":31}
# 使用union[类型,类型...]
my_list = {1, 2, "itcast", "itheima"}
my_dict = {"name":"周", "age":31}
多态
多种状态,即完成某个行为时,使用不同的对象会得到不同的状态
# 复写
class Anima1:
def speak(se1f):
pass
class Dog(Anima1):
def speak(se1f):
print("汪汪汪")
class cat(Animal):
def speak(se1f) :
print("喵喵喵")
def make_noise(animal: Animal) : # 子类继承Animal类,故有speak()方法不会报错
animal.speak()
dog = Dog()
cat = cat()
make_noise(dog)# 输出: 汪汪汪
make_noise(cat)# 输出: 喵喵喵
多态常作用在继承关系上
比如
- 函数(方法)形参声明接收父类对象
- 实际传入父类的子类对象进行工作
即: - 以父类做定义声明
- 以子类做实际工作
- 用以获得同一行为,不同状态
这里Animal的speak方法是空实现,设计含义是
- 父类用来确定有哪些方法
- 具体的方法实现,由子类自行决定
这种写法,就叫做抽象类(也可以称之为接口) - 抽象类:含有抽象方法的类称之为抽象类
- 抽象方法:方法体是空实现的(pass)称之为抽象方法
抽象类好比一个标准,顶层设计,要求子类必须实现
0 评论:
发表评论