凡是过往,皆为序章

0%

Python_8(面向对象)

基于上次的文件基本知识,本篇总结python中重要面向对象知识点。


类与对象的创建

创建类

在不同的python解释器下,类分为两种 经典类新式类

  • 不由任意内置类型派生出的类,称为经典类(python2.0)

    1
    2
    class 类名():
    代码
  • 新式类(python3.0)

    1
    2
    class 类名(object): # object 为 python中的顶级类
    代码

创建对象

  • 语法

    1
    对象名 = 类名()

例子

1
2
3
4
5
6
7
class Washer():
def wash(self):
print('洗衣服')
# 创建对象
haier = Washer() # 对象名 = 类名()
print(haier) # 打印对象
haier.wash() # 使用方法

self

self指的是调用函数的对象。

即上面代码中函数内打印的self和函数外打印的haier相同。

添加和获取对象属性

属性即是特征,对象属性既可以在类外面添加和获取,也能在类里面添加和获取。

类外面添加对象属性

  • 语法

    1
    对象名.属性名 = 值
  • 例子

    1
    2
    3
    # 属性名为自定义的
    haier.width = 500
    haier.height = 800

类外面获取对象属性

  • 语法

    1
    对象名.属性名

类里面获取对象属性

  • 语法

    1
    self.属性名

魔法方法

在python中,__xx__()函数叫做魔法方法,指的是与有特殊功能的函数。

__init__()

体验__init__()

__init__()方法作用:初始化对象,设置与生俱来的初始化属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Washer():

#定义__init__(),添加实例属性
def __init__(self):
#添加实例属性
self.width = 500
self.height = 800

def print_info(self):
# 类里面调用实例属性,注意:不用在该方法内调用`__init__()`方法
print(f'洗衣机的宽度为{self.width},高度为{self.height}')

haier = Washer()
haier.print_info() # 不用传递参数

注意:

  • __init__()方法,在创建一个对象时默认被调用。
  • __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。

带参数的__init__()

思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?

可以使用传递参数的init方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def print_info(self):
print(f'洗衣机的宽度为{self.width},高度为{self.height}')

haier1 = Washer(10, 20)
haier1.print_info()

haier2 = Washer(30, 40)
haier2.print_info()

__str__()

当我们使用print输出对象的时候,默认打印对象的内存地址,如果类定义了__str__()方法,那么就会打印 从这个方法中return的数据。

该方法一般用于返回一些解释说明的语句

1
2
3
4
5
6
7
8
9
10
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def __str__(self):
return '这是海尔洗衣机的说明书'

haier1 = Washer(10, 20)
print(haier1) # 这是海尔洗衣机的说明书

__del__()

当删除对象时,python解释器就会默认调用该方法。

1
2
3
4
5
6
7
8
9
10
11
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height

def __del__(self):
print(f'{self}对象已经被销毁')

haier1 = Washer(10, 20)

del haier1

拓展
我们都知道Python一切皆对象,那么Python究竟是怎么管理对象的呢?

1
2
3
4
5
6
7
8
9
10
11
class A(object):
a = 0

def __init__(self):
self.b = 1

a = A()
# 返回类内部所有属性和方法对应的字典
print(A.__dict__)
# 返回实例属性和值组成的字典
print(a.__dict__)

结果:

1
2
{'__module__': '__main__', 'a': 0, '__init__': <function A.__init__ at 0x01719610>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{'b': 1}
  • 由此可见, 类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在dict里的。

  • 对象的dict中存储了一些self.xxx的一些东西

继承

Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 父类A
class A(object):
def __init__(self):
self.num = 1

def info_print(self):
print(self.num)

# 子类B
class B(A): # 继承写法
pass

result = B()
result.info_print() # 1

继承分为单继承和多继承两种。

单继承

只有一个父类

1
2
3
4
class A(object):
pass
class B(A):
pass

多继承

有多个父类

1
2
3
4
5
6
class A(object):
pass
class B(object):
pass
class C(A, B):
pass

注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。

拓展:查看一个类的层级继承关系

1
print(类.__mro__)

子类调用父类同名方法和属性

通过师傅徒弟案例和学校的多继承完成演示(相应含义已在注释部分说明)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '经典配方'

def make_cake(self):
print(f'运用的技术:{self.kongfu}')

# 学校类
class School(object):
def __init__(self):
self.kongfu = '新式配方'

def make_cake(self):
print(f'运用的技术:{self.kongfu}')

# 徒弟类
class Prentice(School, Master):
def __init__(self):
self.kongfu = '独创配方'

def make_cake(self):
# 加入自己的init方法原因:如果先调用了父类的属性和方法,父类属性回覆盖子类属性
self.__init__()
print(f'运用的技术:{self.kongfu}')

# 子类调用父类的同名方法和属性:即把父类的同名方法和属性再次封装
def make_master_cake(self):
# 父类名.函数
Master.__init__(self) # 调用初始化的原因:这里想要调用父类的同名方法和属性,属性在父类的init方法中被初始化,所以此处再次调用
Master.make_cake(self)

def make_school_cake(self):
# 父类名.函数
School.__init__(self)
School.make_cake(self)

daqiu = Prentice()
daqiu.make_master_cake()
daqiu.make_school_cake()

super()函数

1
2
super().__init__()
super().make_cake()

注意:使用super()可以自动查找父类。调用顺序遵循__mro__的类属性顺序。比较适合单继承使用。

私有权限

定义私有属性和方法

设置私有权限的方法:在属性名 和 方法名 前面 加上两个下划线__。

1
2
3
4
5
6
7
def __init__(self):
self.kongfu = '独创配方'
# 定义私有属性
self.__money = 200
# 定义私有方法
def __info_print(self):
print(self.__money)

注意:私有属性和私有方法只能在类里面访问和修改

获取和修改私有属性

自定义get和set方法

1
2
3
4
def get_money(self):
return self.__money
def set_money(self):
self.__money = 100

保护权限

以单下划线开头。

其他

面向对象的三个特性

  • 封装
    • 将属性和方法书写到类里的操作
    • 封装可以为属性和方法添加私有权限
  • 继承
    • 默认继承父类的所有属性和方法
    • 子类可以重写父类的属性和方法
  • 多态
    • 传入不同的对象,产生不同的结果

多态

定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Dog(object):
def work(self):
pass

class ArmyDog(Dog):
def work(self):
print('追击敌人')

class DrugDog(Dog):
def work(self):
print('追查毒品')

class Person(object):
def work_with_dog(self, dog):
dog.work()

ad = ArmyDog()
dd = DrugDog()
person1 = Person()
# 多态调用
person1.work_with_dog(ad) # 追击敌人
person1.work_with_dog(dd) # 追查毒品

类属性和实例属性

设置和访问类属性

  • 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
  • 类属性可以使用 类对象实例对象 访问。
1
2
3
4
5
6
7
8
9
class Dog(object):
tooth = 10 # 设置类属性

dog1 = Dog()
dog2 = Dog()

print(Dog.tooth)
print(dog1.tooth)
print(dog2.tooth)

类属性的优点:

  • 记录的某项数据始终保持一致,则定义类属性。
  • 实例属性要求 每个对象 *为其 单独开辟一份内存空间 来记录数据,而 *类属性 为全人类所共有,仅占用一份内存,更加节省内存空间。

修改类属性

类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。

1
2
3
4
# 修改实例属性
Dog.tooth = 12
# 修改实例属性
dog1.tooth = 20

类方法和静态方法

类方法

  • 特点

    需要用装饰器@classmethod;来标识其为类方法,对于类方法,第一个参数必须为类对象,一半以cls作为第一个参数。

  • 使用场景

    当方法中需要使用类对象(如访问私有类属性等)时,定义类方法

    类方法一般和类属性配合使用

1
2
3
4
5
6
7
8
9
10
class Dog(object):
__touth = 10

@classmethod
def get_tooth(cls):
return cls.__tooth

dog1 = Dog()
result = dog1.get_tooth()
print(result)

静态方法

  • 特点

    需要通过装饰器 @staticmethod来进行修饰,静态方法既不需要传递类对象,也不需要传递实例对象(形参没有self/cls)。

    静态方法也能通过 实例对象类对象 去访问。

  • 使用场景

    当方法中既不需要使用实例对象,也不需要使用类对象时,定义静态方法。

    取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗。

1
2
3
4
5
6
7
8
9
10
class Dog(object):

@staticmethod
def info_print():
print('该类用于创建Dog')

dog1 = Dog()
# 静态方法既可以使用对象访问,又可以使用类访问
dog1.info_print()
Dog.info_print()
~感谢你请我吃糖果~
-------------本文结束,感谢您的阅读,欢迎评论留言!-------------