@property
@<name>.setter
@<name>.deleter
@abstractmethod
@staticmethod
@classmethod
Why:面向对象更符合人类对客观世界的抽象和理解
一切皆对象
一只小狗,一把椅子,一张信用卡,一条巧克力。。。
一切对象,都有自己内在的属性
狗狗的品种、椅子的质地、信用卡的额度、巧克力的口味。。。
一切行为,皆是对象的行为
狗狗蹲下、椅子移动位置、刷信用卡、巧克力融化了。。。
How:类是对象的载体
不同年龄、肤色、品质的猫,每一只都是一个对象
他们有一个共同的特征:都是猫
我们可以把一类对象的公共特征抽象出来,创建通用的类
# 创建类
class Cat():"""模拟猫"""def __init__(self, name):"""初始化属性"""self.name = namedef jump(self):"""模拟猫跳跃"""print(self.name + " is jumping")
# 用类创建实例对象
my_cat = Cat("Loser")
your_cat = Cat("Lucky")
# 调用属性
print(my_cat.name)
print(your_cat.name)
# 调用方法
my_cat.jump()
your_cat.jump()
三要素:类名、属性、方法
class 类名:"""类说明文档字符串"""#----------定义类主体----------# 定义类属性(成员变量)--作用域在整个类中# 定义类方法(成员方法)
类属性:
存在于类空间,推荐用类名访问,也可以通过实例共享性访问,同一个类中该属性值唯一
成员属性:
存在于实例对象空间,通过实例访问,不同实例属性值可以不同
# 创建学生类
class Student():"""模拟学生类0. 具有类属性 numOfStudent, 分别记录男学生和女学生人数1. 具有姓名(name)、性别(sex)、年龄(age)、学号(sno)、班级(sclass)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、查看信息(queryInfo)、上某门课程(study)功能"""# 类属性numOfStudent = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, sno, sclass):# 成员属性self.name = nameself.sex = sexself.age = ageself.sno = snoself.sclass = sclassif sex == '男':Student.numOfStudent['男'] += 1 #self.numOfStudentum['男'] += 1else:Student.numOfStudent['女'] += 1 #self.numOfStudent['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...") def queryInfo(self):print(f"{self.__sclass}的{self.__name}正在查看信息公告栏") def study(self, classname):print(f"{self.sclass}的{self.name}正在上{classname}这门课程...")
将实例赋值给对象,实例化过程中,传入相应的参数
v = 类名(必要的初始化参数)
# 用类创建实例对象
stu1 = Student("白骨精","女",999,"s001","信息安全1班")
# 访问成员属性
print(stu1.name)
白骨精
stu1.sex,stu1.age,stu1.sclass,stu1.sno
('女', 999, '信息安全1班', 's001')
# 访问类属性 # 只可读,不可更改
stu1.numOfStudent
{'男': 0, '女': 1}
stu1.nums
1
Student.numOfStudent
{'男': 0, '女': 1}
Student.nums
1
stu1.nums +=1
stu1.nums
2
Student.nums
1
Student.nums += 1
Student.nums
2
stu1.nums
2
stu2 = Student("红孩儿","男",9,"s002","信息安全2班")
stu2.__dict__
{'name': '红孩儿', 'sex': '男', 'age': 9, 'sno': 's002', 'sclass': '信息安全2班'}
stu2.nums
3
stu1.nums
2
Student.nums
3
stu1.numOfStudent
{'男': 1, '女': 1}
Student.numOfStudent
{'男': 1, '女': 1}
a = 1
print(id(a))
140730165469584
b=a
print(id(b))
140730165469584
b=2
print(id(b))
140730165469616
print(id(a))
140730165469584
list1 = [1,2,3]
id(list1)
2085555428104
list2 = list1
id(list2)
2085555428104
list2.append(4)
print(list2, id(list2))
[1, 2, 3, 4, 4] 2085555428104
print(list1, id(list1))
[1, 2, 3, 4, 4] 2085555428104
实例名.方法名(必要的参数)
# 调用方法
stu1.eat()
白骨精正在吃饭...
stu1.sleep()
白骨精正在睡觉...
stu1.study()
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-60-a25e69cf1e1b> in <module>
----> 1 stu1.study()TypeError: study() missing 1 required positional argument: 'classname'
stu1.name
'白骨精'
stu1.name = '蜘蛛精'
# 创建类
class Student():"""模拟学生类0. 具有类属性 numOfStudent, 分别记录男学生和女学生人数1. 具有姓名(name)、性别(sex)、年龄(age)、学号(sno)、班级(sclass)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、查看信息(queryInfo)、上某门课程(study)功能"""# 类属性numOfStudent = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, sno, sclass):# 成员属性self.name = nameself.sex = sexself.age = ageself.sno = snoself.sclass = sclassif sex == '男':Student.numOfStudent['男'] += 1 #self.numOfStudentum['男'] += 1else:Student.numOfStudent['女'] += 1 #self.numOfStudent['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...") def queryInfo(self):print(f"{self.__sclass}的{self.__name}正在查看信息公告栏") def study(self, classname):print(f"{self.sclass}的{self.name}正在上{classname}这门课程...") def setName(self, name):self.name = name
# 用类创建实例对象
stu1 = Student("白骨精","女",999,"s001","信息安全1班")
stu1.writeIofo()
信息安全1班的白骨精写下了'我爱重庆工商职业学院!'
stu1.name
'白骨精'
stu1.setName("蜘蛛精")
stu1.name
'蜘蛛精'
在Python中,私有化是一种封装的概念,用于限制对类的属性和方法的访问。私有化的目的是为了保护类的内部实现细节,防止外部代码直接访问和修改类的私有成员。
在Python中,通过在属性或方法的名称前面添加两个下划线(__)来定义私有成员。
# 创建类
class Student():"""模拟学生类1. 具有姓名(name)、性别(sex)、年龄(age)、学号(sno)、班级(sclass)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、查看信息(queryInfo)、上某门课程(study)功能"""# 类属性numOfStudent = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, sno, sclass):# 成员属性self.__name = nameself.__sex = sexself.__age = ageself.__sno = snoself.__sclass = sclassif sex == '男':Student.numOfStudent['男'] += 1 #self.numOfStudent['男'] += 1else:Student.numOfStudent['女'] += 1 #self.numOfStudent['女'] += 1 # 成员函数def eat(self):print(f"{self.__name}正在吃饭...")def sleep(self):print(f"{self.__name}正在睡觉...") def queryInfo(self):print(f"{self.__sclass}的{self.__name}正在查看信息公告栏") def study(self, classname):print(f"{self.__sclass}的{self.__name}正在上{classname}这门课程...") def setName(self, name):self.__name = name
# 用类创建实例对象
stu1 = Student("白骨精","女",999,"s001","信息安全1班")
stu1.eat()
白骨精正在吃饭...
stu1.queryInfo()
信息安全1班的白骨精正在查看信息公告栏
stu1.__name = "蜘蛛精"
stu1.queryInfo()
信息安全1班的白骨精正在查看信息公告栏
del stu1.__name
stu1.setName("蜘蛛精")
stu1.queryInfo()
信息安全1班的蜘蛛精正在查看信息公告栏
"""
模拟教师类0. 具有类属性 numOfTeacher, 分别记录男教师和女教师人数1. 具有姓名(name)、性别(sex)、年龄(age)、工号(tno)、院系(tdept)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、发布信息(publishInfo)、教授某门课程(teach)功能
"""
# 创建教师类
class Teacher():"""模拟教师类0. 具有类属性 numOfTeacher, 分别记录男教师和女教师人数1. 具有姓名(name)、性别(sex)、年龄(age)、工号(tno)、院系(tdept)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、发布信息(publishInfo)、教授某门课程(teach)功能"""# 类属性numOfTeacher = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, tno, tdept):# 成员属性self.name = nameself.sex = sexself.age = = tnoself.tdept = tdeptif sex == '男':Teacher.numOfTeacher['男'] += 1 #self.numOfTeacher['男'] += 1else:Teacher.numOfTeacher['女'] += 1 #self.numOfTeacher['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...")def publisInfo(self):print(f"{self.tdept}的{self.name}写下了'明天考试,同学们好好复习!'") def teach(self, classname):print(f"{self.tdept}的{self.name}正在上{classname}这门课程...")
# 用类创建实例对象
t1 = Teacher("唐僧","男",29,"t001","东土大唐1班")
t1.tno,t1.name,t1.age,t1.sex,t1.tdept
('t001', '唐僧', 29, '男', '东土大唐1班')
t1.publisInfo()
东土大唐1班的唐僧写下了'明天考试,同学们好好复习!'
t1.teach("《三藏真经》")
东土大唐1班的唐僧正在上《三藏真经》这门课程...
看一下人在生物界的分支链
生物——动物界——脊索动物门——哺乳动物纲——灵长目——人科——人属——智人种
公共特征逐渐增加的过程
【问题】
假设二元系统: 人属 = {A人种, B人种, C人种。。。。}
为每一个人种构造一个类
方案一:
各自独立,分别构造各自人种的类
方案二:
1、将各人种公共特征提取出来,建立人属的类;
2、各人种继承上一级(人属)的公共特征,然后添加自身特殊特征,构建各自人种的类。
通常,我们选择方案二,因为他避免了过多的重复劳动
所谓继承,就是低层抽象继承高层抽象的过程
class 类B(类A)pass
称为类 B 继承A
继承分类:
单继承:如果一个类只有一个父类,把这种继承关系称为单继承
多继承:如果一个类有多个父类,把这种继承关系称为多继承
多层继承:C–>B–>A
如果一个类只有一个父类,把这种继承关系称为单继承
# 定义是个 动物类 animal类
class Animal(object):# 在animal类书写play方法,输出快乐的玩耍def play(self):print('快乐的玩耍...')# 定义Dog类继承animal类
# 定义Dog类继承自Animal类
class Dog(Animal):pass
# 创建dog类对象,调用父类的方法
dog = Dog()
dog.play()
快乐的玩耍...
C–>B–>A
# 定义是个 动物类 animal类
class Animal(object): # 对于Animal类和object类来说,单继承# 在animal类书写play方法,输出快乐的玩耍def play(self):print('快乐的玩耍...')# 定义Dog类继承animal类# 定义Dog类继承animal类
class Dog(Animal): # Dog-->Animal 也是单继承,Dog-->Animal-->object 这种继承关系称为多层继承def bark(self):print('汪汪叫......')# 定义类XTQ类,继承Dog类
# 多层继承中,子类可以使用所有继承链中的类中的方法和属性
class XTQ(Dog): # XTQ--->Dog 单继承,XTQ--->Dog-->Animal 类,多层继承pass
xtq = XTQ()
xtq.bark() # 调用父类Dog中的方法
xtq.play() # 调用爷爷类 animal类中的方法
汪汪叫......
快乐的玩耍...
如果一个类有多个父类,把这种继承关系称为多继承。
举个例子,我们可以以小米手机为例。如果我们将小米手机看作子类,可以认为它有三个父类。首先,小米手机本身是一款手机,这是毫无疑问的。另外,我们也知道安卓手机可以作为 NFC 读卡器使用,用于门禁卡、公交卡等的复制。此外,小米手机也可以作为红外遥控器使用,用于电视、空调等设备的控制。一个看似简单的小米手机不仅仅是一部手机,还包含了许多额外的功能。
现在我们来用这个例子来描述多继承的概念。假设在我们的程序中,我们定义了三个类:手机、NFC读卡器和红外遥控器。有了这三个类之后,我们可以构建一个小米手机,让它同时继承这三个类,这样小米手机就可以拥有它们三个类的所有属性和方法。这个想法是可行的。
现在让我们来看一下多继承的语法。与单继承类似,我们只需要在子类中的括号里写出所有要继承的父类名字即可。不同之处在于,多继承需要使用逗号来分隔不同的父类名字。如果要继承多个父类,只需在逗号后面继续添加父类名即可。因此,多继承的语法非常简单。Python的类之间也支持多继承,即一个类,可以继承多个父类:
class 类名(父类1,父类2,……,父类N):类内容体
# 手机类
class Phone:IMEI = None # 序列号producer = None # 厂商def call_by_5g(self):print("5g通话")
# NFC读卡器类
class NFCReader:nfc_type="第五代"producer = "HM"def read_card(self):print("读取NFC卡")def write_card(self):print("写入NFC卡")
# 红外遥控器类
class RemoteControl:rc_type="红外遥控"def control(self):print("红外遥控开启")
# 多继承小米手机类
class MiPhone(Phone,NFCReader,RemoteControl):pass
多继承注意事项:
多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。
即:先继承的保留,后继承的被覆盖
my_phone = MiPhone()
print(my_phone.producer) # 结果为None而非"HM"
None
my_phone.call_by_5g() # 继承自Phone的打5g电话功能
5g通话
print(my_phone.IMEI) #继承自Phone的序列号属性
None
ad_card() # 继承自NFCReader的读卡器功能
读取NFC卡
l() #继承自RemoteControl的红外遥控开启功能
红外遥控开启
针对前面的Student类与Teacher类,再次考虑下
# 学生类
class Student():"""模拟学生类1. 具有姓名(name)、性别(sex)、年龄(age)、学号(sno)、班级(sclass)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、填写信息(WriteInfo)、上某门课程(study)功能"""# 类属性numOfStudent = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, sno, sclass):# 成员属性self.name = nameself.sex = sexself.age = ageself.sno = snoself.sclass = sclassif sex == '男':Student.numOfStudent['男'] += 1 #self.numOfStudentum['男'] += 1else:Student.numOfStudent['女'] += 1 #self.numOfStudent['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...")def queryInfo(self):print(f"{self.__sclass}的{self.__name}正在查看信息公告栏") def study(self, classname):print(f"{self.sclass}的{self.name}正在上{classname}这门课程...")
# 教师类
class Teacher():"""模拟教师类1. 具有姓名(name)、性别(sex)、年龄(age)、工号(tno)、院系(tdept)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、发布信息(publishInfo)、教授某门课程(teach)功能"""# 类属性numOfTeacher = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, tno, tdept):# 成员属性self.name = nameself.sex = sexself.age = = tnoself.tdept = tdeptif sex == '男':Teacher.numOfTeacher['男'] += 1 #self.numOfTeacher['男'] += 1else:Teacher.numOfTeacher['女'] += 1 #self.numOfTeacher['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...")def publisInfo(self):print(f"{self.tdept}的{self.name}写下了'明天考试,同学们好好复习!'") def teach(self, classname):print(f"{self.tdept}的{self.name}正在上{classname}这门课程...")
# 人类
class Person():"""模拟人类1. 具有姓名(name)、性别(sex)、年龄(age)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、功能"""# 类属性numOfPerson = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age):# 成员属性self.name = nameself.sex = sexself.age = ageif sex == '男':Person.numOfPerson['男'] += 1 #self.numOfPerson['男'] += 1else:Person.numOfPerson['女'] += 1 #self.numOfPerson['女'] += 1 # 成员函数def eat(self):print(f"{self.name}正在吃饭...")def sleep(self):print(f"{self.name}正在睡觉...")
class Student(Person):# 学生类属性numOfStudent = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, sno, sclass):super().__init__(name, sex, age) # 调用父类初始化方法# 成员属性
# self.name = name #父类属性,父类种初始化
# self.sex = sex
# self.age = age# 子类独有成员属性,子类中初始化self.sno = snoself.sclass = sclassif sex == '男':Student.numOfStudent['男'] += 1 #self.numOfStudentum['男'] += 1else:Student.numOfStudent['女'] += 1 #self.numOfStudent['女'] += 1 # 父类共有成员函数,父类中定义
# def eat(self):
# print(f"{self.name}正在吃饭...")# def sleep(self):
# print(f"{self.name}正在睡觉...")# 子类独有方法,子类中定义 def queryInfo(self):print(f"{self.sclass}的{self.name}正在查看信息公告栏") def study(self, classname):print(f"{self.sclass}的{self.name}正在上{classname}这门课程...")
# 用类创建实例对象
stu1 = Student("白骨精","女",999,"s001","信息安全1班")
stu2 = Student("红孩儿","男",9,"s002","信息安全2班")
stu1.eat() # 父类中方法
白骨精正在吃饭...
stu2.eat()
红孩儿正在吃饭...
stu1.study("《炼化白骨》") #子类方法
信息安全1班的白骨精正在上《炼化白骨》这门课程...
stu2.queryInfo()
信息安全2班的红孩儿正在查看信息公告栏
# 教师类
class Teacher(Person):"""模拟教师类1. 具有姓名(name)、性别(sex)、年龄(age)、工号(tno)、院系(tdept)这几个属性 2. 具有吃饭(eat)、睡觉(sleep)、发布信息(publishInfo)、教授某门课程(teach)功能"""# 类属性numOfTeacher = {'男':0, '女':0}# 初始化函数def __init__(self, name, sex, age, tno, tdept):super().__init__(name, sex, age) # 调用父类初始化方法# 成员属性
# self.name = name
# self.sex = sex
# self.age = = tnoself.tdept = tdeptif sex == '男':Teacher.numOfTeacher['男'] += 1 #self.numOfTeacher['男'] += 1else:Teacher.numOfTeacher['女'] += 1 #self.numOfTeacher['女'] += 1 # 成员函数
# def eat(self):
# print(f"{self.name}正在吃饭...")# def sleep(self):
# print(f"{self.name}正在睡觉...")def publisInfo(self):print(f"{self.tdept}的{self.name}写下了'明天考试,同学们好好复习!'") def teach(self, classname):print(f"{self.tdept}的{self.name}正在上{classname}这门课程...")
# 用类创建实例对象
t1 = Teacher("唐僧","男",29,"t001","东土大唐1班")
t2 = Teacher("观音","女",666,"t002","南海普陀2班")
t1.eat() #父类方法
唐僧正在吃饭...
t2.sex #父类属性
'女'
t1.publisInfo() #子类方法
东土大唐1班的唐僧写下了'明天考试,同学们好好复习!'
Student.numOfStudent #学生类自己的类属性
{'男': 1, '女': 1}
Student.numOfPerson #学生类继承的父类的类属性
{'男': 2, '女': 2}
stu1.numOfStudent #通过实例访问的类属性
{'男': 1, '女': 1}
stu1.numOfPerson #通过实例访问的类属性
{'男': 2, '女': 2}
Teacher.numOfTeacher
{'男': 1, '女': 1}
Teacher.numOfPerson
{'男': 2, '女': 2}
面向对象编程的三大特性:
多态实际上指的是多种状态。
当我们完成某个具体的行为时,使用不同的对象就会得到不同的状态。
使用一个同样的行为(例如函数),但是传入不同的对象可以得到不同的运行状态。
那么如何理解这句话呢?我们可以看一下如下示例代码:
# 父类: Animal
class Animal():def speak():pass# 讲了属性修饰符时再添加@staticmethoddef makeNoise2(animal):animal.speak()
# 子类:Dog
class Dog(Animal):def speak(self):print("小狗汪汪叫")
# 子类:Cat
class Cat(Animal):def speak(self):print("小猫喵喵喵")
# 实例化一只猫,一条狗
cat = Cat()
dog = Dog()
# 定义一个函数
def makeNoise(animal):animal.speak()
makeNoise(dog)
小狗汪汪叫
makeNoise(cat)
小猫喵喵喵
以下内容讲了属性修饰符时再添加
Animal.makeNoise2(dog)
小狗汪汪叫
cat.makeNoise2(dog) # 对象是谁不重要,重要的是参数是谁
小狗汪汪叫
cat.makeNoise2(cat) # 对象是谁不重要,重要的是参数是谁
小猫喵喵喵
属性修饰符(Property Decorators)是 Python 中一个重要的特性,它可以帮助我们控制类的属性的访问方式。
@property
@property修饰符将一个方法转换为只读属性。
使用@property修饰符的方法可以像访问属性一样被调用,而无需使用函数调用的方式。
class Circle:def __init__(self, radius):self.radius = radius@propertydef diameter(self):return self.radius * 2
# 实例化
circle = Circle(5)
circle.diameter
10
@<name>.setter
@<name>.setter
修饰符用于将一个方法转换为可写属性的赋值方法。其中<name>
是属性名。
需要注意的是,使用@<name>.setter
修饰符时,需要先定义一个同名的只读属性,否则会抛出AttributeError异常。
class Circle:def __init__(self, radius):self._radius = radius@propertydef radius(self):return self._radius@radius.setterdef radius(self, value):self._radius = value@propertydef diameter(self):return self._radius * 2
circle = Circle(5)
print(circle.diameter) # 输出10
circle.radius = 10
print(circle.diameter) # 输出20
10
20
@<name>.deleter
@<name>.deleter
修饰符用于在类中定义一个属性的删除方法。这个修饰符是用来定义一个方法,当删除一个实例中的属性时,该方法就会被调用。
class MyClass:def __init__(self):self._name = None@propertydef name(self):return self._name@name.setterdef name(self, value):self._name = value@name.deleterdef name(self):print('deleter is called!')del self._name
obj = MyClass()
obj.name = "John"
print(obj.name) # Output: Johndel obj.name
print(obj.name)
John
deleter is called!---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-42-8d122c5f1601> in <module>4 5 del obj.name
----> 6 print(obj.name)<ipython-input-41-b4d1f73c186a> in name(self)5 @property6 def name(self):
----> 7 return self._name8 9 @name.setterAttributeError: 'MyClass' object has no attribute '_name'
@abstractmethod
在Python中,抽象基类是一种特殊类型的类,它不能被实例化,只能被继承,并且它定义了一组抽象方法,子类必须实现这些方法。Python提供了abc模块来支持抽象基类的定义和使用。
@abstractmethod
是Python中用于定义抽象方法的装饰器。定义一个抽象方法时,需要使用该装饰器标记方法,以指示该方法是抽象的。如果子类没有实现该方法,将会抛出TypeError异常。
from abc import ABC, abstractmethodclass Shape(ABC):@abstractmethoddef area(self):pass@abstractmethoddef perimeter(self):passclass Square(Shape):def __init__(self, side):self.side = sidedef area(self):return self.side ** 2def perimeter(self):return 4 * self.side
s = Square(5)
print("Area:", s.area())
print("Perimeter:", s.perimeter())
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-46-24cd40342252> in <module>
----> 1 s = Square(5)2 print("Area:", s.area())3 print("Perimeter:", s.perimeter())TypeError: Can't instantiate abstract class Square with abstract methods area
@staticmethod
Python中的@staticmethod属性修饰符用于定义一个静态方法。
静态方法是一个不需要类实例化就可以被类直接调用的方法。
它可以用来执行与类相关的操作,但不需要访问类的实例。
Python里面静态方法和我们平时写的函数def是一样的。唯一不同之处就是它定义于类控件,可以存在于类中。
静态方法可以通过类名.静态方法名()
调用,以恶可以通过实例对象.静态方法名()
调用
# 定义静态方法
class MyClass():@staticmethoddef my_static_method():print("This is a static method.")
# 调用静态方法
# 通过类名调用(推荐)
_static_method()
This is a static method.
# 调用静态方法
# 通过实例对象调用(不推荐)
myclass1 = MyClass()
_static_method()
This is a static method.
@classmethod
@classmethod
是一个属性修饰符,用于定义类方法。
类方法是在类级别上运行的方法,可以通过类或类的实例调用。
类方法不需要访问实例变量,也不需要创建实例。
在类方法中,第一个参数通常是cls(代表类本身),而不是self(代表实例)。
@classmethod
属性修饰符用于将普通的方法转换为类方法。
它接受一个cls参数,这个参数是类对象本身,并且可以用于访问类变量和调用其他类方法。
class Person:total_people = 0def __init__(self, name):self.name = al_people += 1@classmethoddef show_total_people(cls):print("Total people:", al_people)
person1 = Person("Alice")
person2 = Person("Bob")Person.show_total_people()# 通过类名访问类方法(不推荐)
Total people: 4
person1.show_total_people() # 通过实例访问类方法(不推荐)
Total people: 4
补充区分:实例方法、类方法 & 静态方法:
在开发的时候, 可以使用类对方法进行封装。
Python中的魔法方法(Magic Methods),也称为双下划线方法(Dunder Methods),是特殊方法,其名称以双下划线开头和结尾,例如__init__、str、__add__等。这些方法提供了一种使Python对象能够使用内置函数和语言结构的方式。
详细介绍见:
__init__()
: 当一个实例被创建的时候调用的初始化方法__new__()
: 对象实例化的时候所调用的第一个方法.在对象初始化时,首先执行__new__()方法,再执行__init__()方法。__del__()
:当一个实例被销毁时自动执行,无需调用。class Test():def __new__(cls, *args, **kwargs):obj = object.__new__(cls)print('__new__()方法被调用')print(obj)return objdef __init__(self):print('__init__()方法被调用')print(self)
t = Test()
__new__()方法被调用
<__main__.Test object at 0x0000017FE9A4E348>
__init__()方法被调用
<__main__.Test object at 0x0000017FE9A4E348>
class Test():def __new__(cls, *args, **kwargs):obj = object.__new__(cls)print('__new__()方法被调用')print(obj)return objdef __init__(self):print('__init__()方法被调用')print(self)def __del__(self):print('对象被销毁')
t = Test() # 需要到pycharm中运行
__new__()方法被调用
<__main__.Test object at 0x0000017FEA56E248>
__init__()方法被调用
<__main__.Test object at 0x0000017FEA56E248>
__str__() / __repr__()
:
这两个方法都是用来描述类或对象信息的,比如你直接实例化了一个对象,打印出来的是这个对象的地址。而要是重新在类中定义了这两个方法,那打印对象的结果就是方法返回的信息。
__bool__()
:
当调用 bool(obj) 时,会调用 bool() 方法,返回 True 或 False:
__str__() / __repr__()
class Washer:def __int__(self):passdef __repr__(self):return '我是__repr__()魔法方法!'def __str__(self):"""这个str的作用就是:类的说明或对象状态的说明:return:"""return '我是__str__魔法方法!'
haier = Washer()
# 不定义str方法,直接打印,结果是对象的内存地址,定义了str方法,
# 显示的就是str方法返回的内容
print(haier) # 我是__str__魔法方法
我是__repr__()魔法方法!
str(haier)
'我是__repr__()魔法方法!'
要是同时写了这两个方法,只会调用__str__方法。都是用来描述类或对象的信息,那为啥要定义两个呢?
设计的目的是不一样的:
1. __repr__的目标是准确性,或者说,__repr__的结果是让解释器用的。
2. __str__的目标是可读性,或者说,__str__的结果是让人看的。更详细的信息参考:link。
__bool__()
class Person(object):def __init__(self, uid):self.uid = uiddef __bool__(self):return self.uid > 10
p1 = Person(4)
p2 = Person(14)
print(bool(p1)) # False
print(bool(p2)) # True
False
True
__eq__()
:可以判断两个对象是否相等:__ne__()
:可以判断两个对象是否不箱等__lt__()
: <__gt__()
: >class Test:def __init__(self, name, age):self.name = nameself.age = agedef __eq__(self, other):return self.age == other.agedef __gt__(self, other):return self.age > other.agedef __lt__(self, other):return self.age < other.agedef __ne__(self, other):return self.age != other.age
t1 = Test('小王', 20)
t2 = Test('小张', 30)
print(t1 == t2) # False
print(t1 > t2) # False
print(t1 < t2) # True
print(t1 != t2) # True
False
False
True
True
__add__
:加__sub__
:减__mul__
:乘__truediv__
:除__floordiv__
:向下取整__mod__
:取余__pow__
:乘方class Test:def __init__(self, name, age):self.name = nameself.age = agedef __add__(self, other):return self.age + other.agedef __sub__(self, other):return self.age - other.agedef __mul__(self, other):return self.age * other.agedef __truediv__(self, other):return self.age / other.agedef __floordiv__(self, other):return self.age // other.agedef __mod__(self, other):return self.age % other.agedef __pow__(self, power, modulo=None):return pow(self.age, power)
t1 = Test('小王', 20)
t2 = Test('小张', 30)
print(t1 + t2) # 50
print(t1 - t2) # -10
print(t1 * t2) # 600
print(t1 / t2) # 0.666
print(t1 // t2) # 0
print(t1 % t2) # 20
print(t1 ** 3) # 8000
50
-10
600
0.6666666666666666
0
20
8000
__setitem__(self, key, value)
: 赋值操作,a[key]=value__getitem__(self, item)
: 索引操作,a[item]__delitem__(self, key)
: 删除元素,del a[key]__len__(self)
: 容器长度,len(a)__iter__(self)
:定义当迭代容器中的元素的行为;__contains__(self, item)
: 是否包含某个元素,in/not in__reversed__(self)
: 反转容器,reversed() - `class Mylist:def __init__(self, values):self._index = 0self.values = values or []def __setitem__(self, key, value):self.values[key] = valuedef __getitem__(self, item):return self.values[item]def __delitem__(self, key):del self.values[key]def __len__(self):return len(self.values)def __contains__(self, item):return item in self.valuesdef __reversed__(self):return list(reversed(self.values))def __str__(self):return str(self.values)def __iter__(self):# 可迭代return selfdef __next__(self):# 迭代的具体细节# 如果__iter__返回self 则必须实现此方法if self._index >= len(self.values):raise StopIteration()value = self.values[self._index]self._index += 1return value
a = Mylist([1, 2, 3, 4])
print(a) # [1, 2, 3, 4]print(a[2]) # 3a[2] = 10
print(a) # [1, 2, 10, 4]print(len(a)) # 4print(1 in a) # Trueprint(reversed(a)) # [4, 10, 2, 1]del a[2]
print(a) # [1, 2, 4]
[1, 2, 3, 4]
3
[1, 2, 10, 4]
4
True
[4, 10, 2, 1]
[1, 2, 4]
[d for d in a]
[1, 2, 4]
__call__
: 允许实例当成函数去执行。当在实例后加括号即实例()或者类()()时,会自动调用__call__方法。class Test:def __init__(self, name, age):self.name = nameself.age = agedef __call__(self, x, y):return x + y
a = Test('小王', 20)
print(a.name, a.age) # 小王 20t = a(100, 200)
print(t) # 300
print(callable(a)) # True
小王 20
300
True
本文发布于:2024-02-01 04:06:28,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170673158933734.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |