OOP):Object Oriented Programming所谓的面向对象,就是在编程的时候尽可能的去模拟真实的现实世界,按照现实世界中的逻辑去处理问题,分析问题中参与其中的有哪些实体,这些实体应该有什么属性和方法,我们如何通过调用这些实体的属性和方法去解决问题。
面向过程
面向对象
class): 用来描述具有相同的属性和方法的对象的集合。它定义了集合中每个对象所共有的属性和方法。object):也称为类的实例,是一个具体存在的实体。class 关键字# 语法
class 类名(父类名):
"""类的帮助信息"""
属性
方法
# class_def.py
# 类的声明
class Human(object): #object可以省略。在python中如果没有声明继承的类的话,那默认继承的是超类object。
"""人类"""
# 定义属性(类属性)
message = "这是类属性"
# 通过类访问类属性
print(Human.message)
def __init__(self, 参数列表)
类名(参数列表)# constructor_method.py
class Human:
# 定义属性(类属性)
message = "这是类属性"
# 构造方法
def __init__(self, name, age):
# 实例变量(实例属性)
self.name = name
self.age = age
print("这是构造方法")
# 实例化对象
person = Human("哈利波特", 12)
# 通过实例访问类属性
print(person.message)
# 通过实例访问实例属性
print(person.name)
print(person.age)
def 方法名(self, 参数列表)
实例.方法名(参数列表)# instance_method.py
class Human:
# 实例方法
def study(self, course):
print("正在学习{course}")
# 实例化
person = Human()
# 通过实例访问实例方法
person.study("python")
@classmethod 装饰器装饰的方法。用于设置或获取类的详细信息或者状态。@classmethod类名.类方法名(参数列表)cls参数不是self参数。不使用cls不会报错,但是最好按照惯例来,cls指向对象其实就是类名本身。# class_method.py
class Human:
# 类属性
population = []
# 类方法
@classmethod
def born(cls): #使用类方法装饰器,定义类时会自动添加cls参数
print("这是类方法")
cls.population += 1
# 通过类名访问类方法
Human.born()
print(Human.population)
@staticmethod装饰的方法。静态方法不需要访问数据,没有cls、self这种关键字。静态函数可以独立工作,不能设置类的状态或者实例的状态。@staticmethod类名.静态方法名()# static_method.py
class Human:
# 静态方法
@staticmethod
def grow_up():#使用静态方法声明后,不会绑定cls或者self参数
print("这是静态方法")
# 通过类名访问静态方法
Human.grow_up()
封装(Encapsulation):
python中没有既定的关键字或者机制来实现真正的封装,但是使用命名方式来实现
_属性名__属性名
_类名,变相的实现了属性的隐藏,即被视为: _类名__属性名__属性名去访问属性的话,实际上访问不到的。#定义一个Account类
class Account:
# 普通属性
bank = "BOC"
# 内部属性
_username = "Hogwarts"
# 私有属性
__password = "888"
# 通过类名访问类属性
print(Account.bank) # 将会打印 BOC
print(Account._username) # 将会打印 Hogwarts
print(Account.__password) # 将会引发 AttributeError,打印内容:AttributeError: type object 'Account' has no attribute '__password'
print(Account.__dict__) # 将会打印类中实际有用属性
#打印内容:{'__module__': '__main__', 'bank': 'BOC', '_username': 'Hogwarts', '_Account__password': '888', '__dict__': , '__weakref__': , '__doc__': None}
#注:__dict__:python内置特殊属性,字典格式,保存类中所拥有的可写的属性
@property合成的属性成为计算属性)@property装饰器实例.方法名注意: 计算属性并不真正的存储状态,其值是通过某种算法计算得到的,当程序对该属性赋值时,所赋值实际是存放在对应的实例变量中。
class Account:
# 普通属性
bank = "BOC"
# 内部属性
_username = "Hogwarts"
# 私有属性
__password = "888"
@property
def password(self):
return self.__password
# 实例化对象
obj = Account()
# 访问实例的私有属性
print(obj.password) # 将会打印 888
#注意:password虽然是方法,但是已经被装饰成计算属性,因此访问的时候不需要加()
@计算属性名.setter装饰器实例.方法名class Account:
# 普通属性
bank = "BOC"
# 内部属性
_username = "Hogwarts"
# 私有属性
__password = "888"
@property
def password(self):
return self.__password
@password.setter
def password(self, value):
# 增加数据的校验
if len(value) >= 8:
self.__password = value
else:
print("密码长度最少要有8位!")
# 实例化对象
obj = Account()
# 修改私有属性(满足校验条件)
obj.password = "hogwarts666" # 修改成功
print(obj.password) # 将会打印 hogwarts666
# 修改私有属性(不满足校验条件)
obj.password = "123" # 修改不会生效
print(obj.password) # 将会打印 888
继承(Inheritance):
class 类名(父类列表)object# inheritance_demo.py
class Human:
"""人类"""
# 类属性
message = "这是Human的类属性"
# 构造方法
def __init__(self, name, age):
# 实例属性
self.name = name
self.age = age
# 实例方法
def live(self):
print("住在地球上")
class Student(Human):
"""学生类"""
def study(self):
print("正在学习")
# 实例化子类对象
stu = Student("哈利波特", 12)
# 访问类属性(继承)
print(stu.message)
# 访问实例属性(继承)
print(stu.name, stu.age)
# 访问实例方法(继承)
stu.live()
# 访问实例方法(扩展)
stu.study()
isinstance(实例, 类名)
issubclass(类名1, 类名2)
# relation_demo.py
# 人类
class Human:
pass
# 学生类
class Student(Human):
pass
# 老师类
class Teacher(Human):
pass
# 检查实例与类的关系
stu = Student()
print(isinstance(stu, Human)) # 将会打印 True
# 检查类与类的关系
print(issubclass(Student, Human)) # 将会打印 True
print(issubclass(Student, Teacher)) # 将会打印 False
多态(Polymorphism):同名方法呈现多种行为
python弱类型语言,变量并没有声明类型,因此完全可以在不同的时间代表不同的变量,当同一个变量在调用同一个方法时,完全可能呈现出多种行为,具体呈现的哪些行为由该变量所引用的对象来决定。这就是多态。
+号
# 加法:数字+数字
print(1 + 1) # 打印 2
# 拼接:字符串+字符串
print("Hello" + "World") # 打印 Hello World
# 合并:列表+列表
print([1, 2] + [3]) # 打印 [1, 2, 3]
len()函数
# 参数是字符串
print(len("Hogwarts"))
# 参数是列表
print(len([1, 3, 5]))
同名变量调用同名方法呈现多种行为。
# poly_method.py
class China:
def speak(self):
print("汉语")
class Usa:
def speak(self):
print("英语")
# 实例化对象
cn = China()
us = Usa()
for x in (cn, us):
# 同一个变量在调用同名方法时,呈现不同的行为
# 具体呈现哪种行为,由该变量所引用的对象决定
x.speak()
Override):子类的方法名称与父类的相同super().__init__()父类名.__init__(self)# override_demo.py
class Human:
"""人类"""
message = "这是Human的类属性"
# 构造方法
def __init__(self, name, age):
# 实例属性
self.name = name
self.age = age
# 实例方法
def live(self):
print(f"住在地球上")
class Student(Human):
"""学生类"""
# 重写父类的构造方法
def __init__(self, name, age, school):
# 方式一:访问父类的构造方法
super().__init__(name, age)
#方式二:访问父类的构造方法
# super(Student, self).__init__(name, age)
#方式三:访问父类的构造方法
# Human.__init__(self, name, age)
# 子类特有的实例属性(个性)
self.school = school
# 重写父类的实例方法
def live(self):
print(f"住在{self.school}")
# 实例化子类对象
stu = Student("哈利波特", 12, "Hogwarts")
# 访问实例方法
stu.live() # 将会打印 住在Hogwarts