复习打卡python篇——python面向对象与高级编程01
目录
1. 面向对象基本概念
2. 魔术方法
2.1 初始化方法、构造方法:__init__()
2.2 __str__()方法
2.3 __del__()方法
3. 面向对象三大特性
3.1 封装
3.2 继承
3.2 多态
4. 面向对象其他特性
4.1 类属性
4.2 类方法
4.3 静态方法
1. 面向对象基本概念
传统的面向过程的编程思想——自顶向下,逐步细化。
所谓的面向对象就是模拟现实世界,定义一个一个的实体,比如学生小明、班级3班、小狗TOM、英语老师等。每一个实体都有不同的功能,比如TOM会叫,小明会写作业、老师会改作业等。这些功能在面向对象编程中被称为方法,同时不同实体有不同的特征,比如小明有身高年龄体重,3班有人数等,这些特征被称为实体的属性,每一个实体被称为一个对象。对象使用属性(property)保存数据, 对象使用方法(method)管理数据。
而想要创建对象必须要先有类,类本来就是对现实世界的一种模拟,在现实生活中,任何一个实体都有一个类别,类就是具有相同或相似属性和动作的一组实体的集合,比如小明是学生类,TOM是狗类,三班是班级类。一个对象的所有应该具有特征特性信息,都是由其所属的类来决定的,但是每个对象又可以具有不同的特征特性信息。
类的定义
类名遵守一般的标识符的命名规则(以字母、数字和下划线构成,并且不能以数字开头),一般为了和方法名相区分,类名的首字母一般大写。这里定义了两个方法,其中self关键字指向了类实例对象本身。
class Person(object):
# 属性
# 方法
def eat(self):
print("i can eat")
def run(self):
print("i can run")
类的实例化
实例化一个p1对象,并调用方法eat和run,类中的self就是谁实例化了对象,其就指向谁。
class Person(object):
# 属性
# 方法
def eat(self):
print("i can eat")
def run(self):
print("i can run")
p1 = Person()
p1.eat()
p1.run()
在类的外面添加调用属性
class Person(object):
def eat(self):
print("i can eat")
def run(self):
print("i can run")
p1 = Person()
# 在类的外面对对象添加属性
p1.name = '小明'
p1.age = 11
# 获取类的属性
print(p1.name) # 小明
print(p1.age) # 11
在类的内部获取外部定义的属性
class Person(object):
def print_info(self):
print(f"我叫{self.name}")
p1 = Person()
# 在类的外面对对象添加属性
p1.name = '小明'
p1.age = 11
# 获取类的属性
p1.print_info() # 我叫小明
2. 魔术方法
2.1 初始化方法、构造方法:__init__()
当实例化对象时,__init__()方法会自动被触发,实例化多少次,__init__()方法就会被调用多少次。
实例化对象时,将参数传给__init__
函数自动并执行它。__init__()
函数的参数列表会在开头多出一项self,它永远指代新建的那个实例对象。
使用__init__()方法可以在创建实例时自动添加属性,__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
class Person(object):
# 定义公共属性
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("小明", 11)
print(p1.name) # 小明
print(p1.age) # 11
2.2 __str__()方法
当我们使用print()直接打印对象时,默认打印对象地址,若定义了__str__()魔术方法,则打印__str__()返回的字符串,当我们需要打印输出某个对象的信息时,一般都可以定义__str__()魔术方法。注意:必须返回字符串类型的数据,否则会直接报错!
class Person(object):
# 定义公共属性
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'姓名:{self.name},年龄:{self.age}'
p1 = Person("小明", 11)
# 直接打印对象,打印__str__返回的数据
print(p1) # 姓名:小明,年龄:11
2.3 __del__()方法
当对象被删除时(调用del删除对象或者文件执行结束后 )会自动被触发,__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 __del__(self):
print('__del__被触发了')
p1 = Person("小明", 11)
print(p1) # 姓名:小明,年龄:11
3. 面向对象三大特性
3.1 封装
把现实世界中的主体中的属性和方法书写到类的里面的操作即为封装,封装可以为属性和方法添加为私有权限,不能直接被外部访问。
私有属性:
在属性前加上__即为私有属性,私有属性在外部不能直接访问,可以通过接口访问,一般定义函数名' get_xx '用来获取私有属性,定义' set_xx '用来修改私有属性值
class Girl(object):
# 定义属性
def __init__(self, name):
self.name = name
self.__age = 18
# 给__age私有属性添加一个访问"接口"
def get_age(self):
# 获取属性之前
# 1、需要验证用户是否具有查看属性的权限
# 2、如果有,则返回私有属性;如果没有权限,则直接禁止访问
return self.__age
# 给__age私有属性添加一个设置"接口"
def set_age(self, age):
# 在设置属性之前
# 1、首先对age进行判断,判断是否是一个合理数据
if not isinstance(age, int):
print('很抱歉,您设置的age参数非整数类型')
return
if age <= 0 or age > 250:
print('很抱歉,您设置的age参数范围不合理')
return
# 2、如果是合理的数据,则允许设置;反之,则直接禁止
self.__age = age
g1 = Girl('小美')
print(g1.name) # 小美
g1.set_age(20)
print(g1.get_age()) # 20
私有属性有何意义?
明确区分内外,控制外部对内部数据访问,起到保护数据以及过滤异常数据目的!
私有方法
私有方法的定义方式与私有属性基本一致,在方法名的前面添加两个下划线。
私有方法有何意义呢?私有方法并不是用于保护数据,而是简化程序的复杂度。
class LKJ(object):
def __test01(self):
print('执行方法1')
def __test02(self):
print('执行方法2')
def __test03(self):
print('执行方法3')
# 定义一个统一的"接口"
def te(self):
self.__test01()
self.__test02()
self.__test03()
t = LKJ()
t.te()
3.2 继承
在Python代码中,为了实现代码重用,体现共性与个性的问题,可以通过继承来实现重用关系
类Student继承了类Person,其拥有Person中的属性和方法
class Person(object):
def eat(self):
print('eat')
def run(self):
print("run")
class Student(Person):
pass
stu = Student()
stu.eat() # eat
stu.run() # run
python单继承和多继承都支持
单继承
一个类只能继承一个不能同时继承多个
单继承的传递性(多层继承):A继承B,B继承C,那么A就继承了C的所有公共属性和公共方法
多继承
一个类可以继承多个类,可以使用类名.__mro__或类名.mro()查看继承信息。
虽然多继承允许我们同时继承自多个类,但是实际开发中,应尽量避免使用多继承,因为如果两个类中出现了相同的属性和方法就会产生命名冲突。
重写
继承自父类的方法属性一般是共有的方法属性,而自身也应该又属于自己独有的方法属性,否则继承就没有意义了。
如果子类中的属性和方法与父类中的属性或方法同名,则子类中的属性或方法会对父类中同名的属性或方法进行覆盖(重写)。
class Animal():
def call(self):
print("I can call")
class Dog(Animal):
# 重写
def call(self):
print("I can call with wangwangwang")
dog01 = Dog()
dog01.call() # I can call with wangwangwang
当我们在子类中重构父类的方法后,子类的实例先会在自己的类 中查找该方法,当找不到该方法时才会去父类中查找对应的方法。
super调用父类的属性和方法
如果在继承重写的基础上,我们还需要强制调用父类中的属性或方法,可以考虑使用super()
使用super().属性或super().方法名()
就可以完成调用了。
class Person():
def __init__(self, gender, name, age):
self.gender = gender
self.name = name
self.age = age
class Student(Person):
def __init__(self, gender, name, age, grade):
# 调用父类的方法
super().__init__(gender, name, age)
self.grade = grade
可以通过类名.__mro__
或类名.mro()
获得类的层次结构”
print(Student.mro()) # [<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
在类的继承中,调用属性或方法,首先在自身类中去寻找,如果未找到,继续向上一级继承的类中去寻找,没有找到则继续向上寻找…直到object类,这就是Python类继承中,其方法解析顺序。
3.2 多态
子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果。
① 多态依赖继承
② 子类还需要重写父类中的方法
首先定义一个父类,其可能拥有多个子类对象。当我们调用一个公共方法(接口)时,传递的对象不同,则返回的结果不同。
class Animal():
def func1(self):
print('I can call')
class Dog(Animal):
def func1(self):
print('I can call with 汪汪汪')
class Cat(Animal):
def func1(self):
print('I can call with 喵喵喵')
# 公共方法(接口)
def service(obj):
obj.func1()
dog = Dog()
cat = Cat()
service(dog) # I can call with 汪汪汪
service(cat) # I can call with 喵喵喵
4. 面向对象其他特性
4.1 类属性
Python中,属性可以分为实例属性和类属性。 在Python代码中,一切皆对象。类也是一种特殊的对象,所以我们也可以为类来创建一个属性 :类属性。
对象属性(成员属性)是由这个类产生的对象所拥有的属性。
类属性并不是由实例化对象拥有的,而是这个类所拥有的属性,可以理解为是所有对象共同拥有的属性,但是其不属于某一个对象。
比如我们可以利用类属性统计一共创建了多少个对象:
class Person(object):
# 定义一个类属性:用于统计到底由这个类产生了多少个对象
count = 0
# 通过__init__魔术方法定义的都是对象属性
def __init__(self, name, age):
self.name = name
self.age = age
# 对类属性进行累加计数
Person.count += 1
p1 = Person('小明', 23)
p2 = Person('小美', 18)
print(f'由Person类一共创建了{Person.count}个对象!') # 由Person类一共创建了2个对象!
4.2 类方法
Python代码中,类属性与对象属性一样,都强调封装特性,不建议直接在类的外部直接对类属性进行操作。
如果想在类的外部获取类属性的信息,必须使用类方法来实现。类方法主要用于操作类属性或类中的其他方法。
在类方法上要加上@classmethod
class Person(object):
# 定义一个类属性:用于统计到底由这个类产生了多少个对象
count = 0
# 通过__init__魔术方法定义的都是对象属性
def __init__(self, name, age):
self.name = name
self.age = age
# 对类属性进行累加计数
Person.count += 1
@classmethod
def get_count(cls):
return f"该类一个创建了{cls.count}个对象!"
p1 = Person('小明', 23)
p2 = Person('小美', 18)
print(Person.get_count()) # 该类一个创建了2个对象!
4.3 静态方法
静态方法:既不需要调用自身属性(对象属性、类属性),也不需要调用自身方法(对象方法、类方法),本身就是一个独立功能。这个时候,可以把这个方法封装成一个静态方法。
在静态方法上要加上@staticmethod
class Animal():
@staticmethod
def func1():
print("我什么也没调用!我是个独立的方法")
作者:筒栗子