一、类与实例
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。对象可以包含任意数量和类型的数据。
类:类型
实例(对象):类型塑造出来的某一个具体的内容
isinstance(对象,类) 返回一个对象是否是一个类的实例
class MyClass:
pass
# 声明一个MyClass类的实例
mc1 = MyClass()
print(type(mc1), isinstance(mc1, MyClass)) #运行结果:<class '__main__.MyClass'> True
# callable 可调用 (函数名,类名)
def my_fun():
pass
print(callable(my_fun), callable(MyClass) #运行结果:True True
# 函数返回计算结果 默认返回None return 后内容
r = my_fun()
print(r, type(r)) #运行结果:None <class 'NoneType'>
# 类的调用结果 返回的就是一个实例 就是类的对象
mc2 = MyClass()
print(mc2, type(mc2))
#运行结果:<__main__.MyClass object at 0x00000143F89A5850> <class '__main__.MyClass'>
二、初始化函数
类:抽象的 模板,约定了未来实例的样子(约定未来实例要有什么内容) 实例:具体的,内容由类来限定, 拥有具体的数据值
class Student:
def __init__(self, _name, _age):
print("这是初始化函数")
self._name = _name
self._age = _age
def get_name(self):
return self._name
def get_age(self, ):
return self._age
def set_name(self,_name):
self._name=_name
s0 = Student("哗哗哗", 30)
print(s0._name) #哗哗哗
print(s0.get_age())#30
print(s0.get_name())#哗哗哗
s0.set_name("huahua")
print(s0.get_name())#huahua
三、类中封装数据与操作
class Light:
def __init__(self):
self.state = False
self.colors = ["红色", "绿色", "蓝色"]
self.current = 0
def is_open(self):
return self.state
def change_state(self):
self.state = not self.state
def get_color(self):
return self.colors[self.current]
def set_color(self):
self.current += 1
if self.current == len(self.colors): #灯的颜色在"红色", "绿色", "蓝色"中循环
self.current = 0 #当 self.current = 3 时 ,将灯的颜色设置为红色
l0 = Light()#实例化
print(l0.is_open())#当前灯是否打开 False
l0.change_state()#改变当前灯的状态
print(l0.is_open())#当前灯是否打开 True
print(l0.get_color())#当前灯的颜色 红色
l0.set_color() #设置灯的颜色
print(l0.get_color())#当前灯的颜色 绿色
三、魔法函数
class MyClass:
def __init__(self, name, age):
# __init__ 用于初始化self
print(f"初始化函数执行了")
self.name = name
self.age = age
def __str__(self):
# __str__ 返回实例的字符串表示:自定义内容的字符串
return f"醒醒啦:{self.name}"
def __len__(self):
# __len__ 使用len函数 返回实例对应的长度: 自定义返回的数值
return len(self.name)
def __gt__(self, other):
# __gt__ 使用>触发
return self.age > other.age
def __lt__(self, other):
# __lt__ 使用<触发
return self.age < other.age
def __ge__(self, other):
# __ge__ 使用>=触发
return self.age >= other.age
def __le__(self, other):
# __le__ 使用<=触发
return self.age <= other.age
def __eq__(self, other):
# __eq__ 使用== 触发
return self.age == other.age and self.name == other.name
def __ne__(self, other):
# __ne__ 使用!= 触发
return self.age != other.age or self.name != other.name
def __add__(self, other):
# __add__ 使用+触发
return self.age + other.age
def __sub__(self, other):
# __sub__ 使用-触发
return self.age - other.age
def __mul__(self, other):
# __mul__ 使用*触发
return self.age * other.age
def __divmod__(self, other):
# __divmod__ 使用div(x,y)触发返回一个元组先整除,在求余数
return divmod(self.age, other.age)
def __mod__(self, other):
# __mod__ 使用%触发
return self.age % other.age
def __truediv__(self, other):
# __truediv__ 使用/触发
return self.age / other.age
def __floordiv__(self, other):
# __floordiv__ 使用//触发
return self.age // other.age
mc = MyClass("张飞", 30)
print(mc)
print(len(mc))#2
mc2 = MyClass("孙尚香", 18)
print(mc != mc2, mc == mc2)#True False
print(mc + mc2, mc - mc2, mc * mc2, mc % mc2,
divmod(mc, mc2), mc / mc2, mc // mc2)#48 12 540 12 (1, 12) 1.6666666666666667 1
四、构造函数与析构函数
构造函数:创建并且返回实例(self) 初始化函数: self已经创建完成,可以向self中添加数据
class MyClass:
def __new__(cls, *args, **kwargs):
# 调用父类的new方法创建一个实例
instance = super().__new__(cls)
print(f"构造函数执行了", id(instance))
# 将创建好的实例返回 返回给初始化函数
return instance
def __init__(self, name):
print(f"初始化函数执行了", id(self))
self.name = name
def __del__(self):
print(f"析构函数执行了")
mc1 = MyClass("阿拉伯")
print(id(mc1), id(None), mc1 is None)
mc1 = None
print("程序执行完毕 将要退出")
# 程序退出执行析构mc1
析构函数: 销毁实例 清理实例内存 实例不在使用则回收实例内存之前汇执行对应的析构函数
# __del__当对象被删除或程序运行结束是垃圾回收器会自动调用这个函数
class Car:
# __init__方法是一个构造函数,用于初始化汽车实例的model属性。
def __init__(self, model):
self.model = model
def __del__(self):
print(f"A Car instance of model {self.model} is being destroyed.")
# 创建对象
my_car = Car("Toyota Camry")
#删除对象,Python的垃圾回收器随后会调用__del__方法
#__del__方法是一个析构函数,
#当对象被删除时会被调用,打印一条消息表示该汽车实例正在被销毁。
#del my_car语句用于显式地
#删除my_car对象,触发垃圾回收并调用__del__方法。
五、继承
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"名字:{self.name} 年纪:{self.age}"
def walk(self):
print(f"走路")
p1 = Person("张飞", 20)
print(p1)
p1.walk()
class SuperPerson(Person):
def __init__(self, name, age, skill):
super().__init__(name, age)#使用super()调用父类中的方法
self.skill = skill
def __str__(self):
return f"{super().__str__()} 技能:{self.skill}" #
def fly(self):
print(f"飞行")
sp1 = SuperPerson("绿巨人", 30, "变绿")
print(sp1)
sp1.walk()
sp1.fly()
六、多继承
子类可以调用并使用父类中的任何方法
class MoveAble:
def __init__(self, speed):
self.speed = speed
def move(self):
print(f"i can move, my speed is {self.speed}")
def __str__(self):
return "我是移动类"
class SpeakAble:
def __init__(self, language):
self.language = language
def speak(self):
print(f"i can speak {self.language}")
def __str__(self):
return "我是说话类"
class AttackAble:
def __init__(self, skill):
self.skill = skill
def attack(self):
print(f"使用{self.skill}发起攻击")
def __str__(self):
return "我是攻击类"
class Person(MoveAble, SpeakAble):
def __init__(self, name, speed, language):
# super().__init__() 会执行第一个父类
# super().__init__(speed)
# 通过类名表名 需要初始化哪个父类 必须传入self
MoveAble.__init__(self, speed)
SpeakAble.__init__(self, language)
self.name = name
def show(self):
print(f"my name is {self.name}")
def __str__(self):
return "我是人类"
p0 = Person("小张", 50, "汉语")
p0.show()
p0.move()
p0.speak()
class ATM(Person, AttackAble):
def __init__(self, name, speed, language, skill):
Person.__init__(self, name, speed, language)
AttackAble.__init__(self, skill)
def __str__(self):
return f"我是奥特曼类"
atm0 = ATM("赛罗", 1000, "光之语言", "赛罗光线")
atm0.show()
atm0.move()
atm0.speak()
atm0.attack()
print(atm0)
# 多继承 mro: method(方法) retrieval(检索) order(顺序)
# Python3 使用广度优先
print(ATM.mro())
七、多态
python中的多态主要通过以下几种方式实现:
-
方法重写(Override):子类可以重写父类的方法来改变其行为。当调用子类实例的方法时,Python会根据实例的类型来确定调用哪个方法。 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
class Parent:
def show(self):
print("Parent's show")
class Child(Parent):
def show(self):
print("Child's show")
# 当我们调用 show 方法时,会根据对象的实际类型调用相应的版本
parent = Parent()
child = Child()
parent.show() # 输出 Parent's show
child.show() # 输出 Child's show
def quack_and_fly(bird):
bird.quack()
bird.fly()
class Duck:
def quack(self):
print("DDD!")
def fly(self):
print("FFF")
class Person:
def quack(self):
print("PPP")
def fly(self):
print("AAA")
# 由于 Person 类提供了 quack 和 fly 方法,它也可以被 quack_and_fly 函数接受
quack_and_fly(Duck()) # Duck 的行为
quack_and_fly(Person()) # Person 模拟 Duck 的行为
2.抽象类
抽象类:不直接实例化, 通过子类来产生实例
抽象类:拥有抽象方法 不能直接实例化 通过装饰器abstractmethod把 walk 变为抽象方法
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print("Woof!")
# Dog 类实现了 make_sound 方法,因此可以被实例化
dog = Dog()
dog.make_sound() # 输出 Woof!
# 如果尝试实例化一个没有实现所有抽象方法的子类,将引发 TypeError
class Cat(Animal):
pass
# cat = Cat() # 这将引发 TypeError,因为 Cat 没有实现 make_sound 方法
可以通过默认参数、可变参数列表或使用*args
和**kwargs
来
class Example:
def show(self, *args):
for arg in args:
print(arg)
ex = Example()
ex.show(1) # 输出 1
ex.show(1, 2) # 输出 1 然后输出 2
ex.show(1, 2, 3, 4) # 输出 1 2 3 4
八、实例属性与实例方法
1.实例属性向实例中添加数据类内使用self调用类外使用实例调用
class Person:
# 实例属性向实例中添加数据
def __init__(self,name,age):
self.name = name
self.age = age
# 类内使用self调用
def __str__(self):
return f"{self.name}{self.age}"
p0=Person("哗哗哗",20)
# 类外使用实例调用
print(p0)
print(p0.age,p0.name)
2.实例方法在类内使用self调用在类外使用实例调用
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
# 实例方法
def set_name(self,name):
self.name=name
# 类内 通过self
def get_name(self):
return self.name
p0=Person("哗哗哗",20)
# 类外 通过实例调用
p0.set_name("哗哗")
print(p0.get_name())
3.类属性 ,向类中添加数据获取与设置,直接通过类名,通过实例不可以设置类属性
class Person:
# 向类中添加数据
MAX_AGE = 150
MIN_AGE = 0
print(Person.MAX_AGE, Person.MIN_AGE)
4.
类方法,第一个形参一般是cls,带有装饰器classmethod,将第一个形参编程类名 目的: 为了获取类相关信息 类名、 父类 、类注释
class Person:
"""哗哗哗"""
@classmethod
def info(cls):
print(cls.__doc__,cls.__name__,cls.__bases__)
Person.info()
5. 静态方法, 没有特殊形参
有装饰器staticmethod ,将方法升级为静态方法
通过类名调用 , 项目的辅助类一般都会使用静态方法
class Person:
@staticmethod
def my_fun(a,b):
return a == b
print(Person.my_fun(100, 200))
九、动态语言
# 添加实例属性
# 实例名.属性名=值
import types
class Person:
pass
p0 = Person()
p0.name = ("哗哗哗")
print(p0.name)
# 添加实例方法
# 实例名.实例方法=types.MethodType(原始方法名, 实例)
# 原始方法第一个参数是self
def my_set_name(self, name):
self.name = name
p0.set_name = types.MethodType(my_set_name, p0)
p0.set_name("哗哗")
print(p0.name)
# 添加类属性
# 向类中添加类属性 类可以正常访问 所有实例均可访问
Person.MAX_AGE = 120
Person.MIN_AGE = 120
print(Person.MAX_AGE)
@classmethod
def my_info(cls):
print(cls.__bases__)
# 向类中添加类方法 方法格式符合类方法格式 类与所有实例均可访问
Person.info = my_info
Person.info()
@staticmethod
def my_max(x, y):
return x == y
Person.max = my_max
print(Person.max(10, 20))
十.属性封装
私有属性: 在Python中,通常约定以双下划线__
开头的属性或方法是私有的(name mangling)。这意味着它们不应该被类的外部直接访问。
属性装饰器: Python提供了@property
装饰器,
使用__getattr__
和__setattr__
方法: 通过定义__getattr__
和__setattr__
方法来控制属性的访问和赋值。
class Person:
def __init__(self, sex, height):
self.__sex = sex
self.__height = height
# 将函数变为属性
@property
def height(self):
return self.__height
# 指明属性的setter
@height.setter
def height(self, height):
self.__height = height
def __get_sex(self):
print(f"发现你在获取")
"""当获取属性时 会触发"""
return self.__sex
def __set_sex(self, sex):
print(f"发现你在设置")
"""当修改属性时 会触发"""
if sex in ["男", "女"]:
self.__sex = sex
else:
print(f"设置失败")
# 封装真正属性 拥有get与set方法
sex = property(__get_sex, __set_sex)
p = Person( "男", 180)
print(p.sex)
p.sex = "保密"
print(p.sex)
p.sex = "女"
print(p.sex)
print(p.height)
p.height = 190
print(p.height)
十一、属性操作
hasattr:检测当前实例中是否有当前属性
setattr为当前类添加一个属性的属性的值
delattr删除当前对象和属性名
getatter获取当前对象的属性名返回属性值
class Person:
pass
p0 = Person
p0.name = "哗哗哗"
print(hasattr(p0, "name"))
print(getattr(p0, "name"))
if hasattr(p0, "ser"):
pass
else:
setattr(p0, "open", "你好")
print(getattr(p0, "open"))
if hasattr(p0, "open"):
delattr(p0, "open")
print(hasattr(p0, "open"))