前言
记录一下复习python的过程,有不对的地方欢迎在评论区批评指正,感谢!!
一、面向对象
python中,一切皆对象。python在设计之初就是一门面向对象的语言,所以在python中创建一个类和对象是非常容易的。
先来记录一下面向对象中的一些基本概念和术语:
- 类(class):用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象共有的属性和方法,对象是类的实例。
- 方法:类中定义的函数;
- 类变量:类变量在整个实例化对象中是公用的。类变量定义在类中且在函数体之外(init(self)也是一个函数体),类变量通常不作为实例变量使用。
- 实例变量:在类的声明中,属性是用变量来表示的,这种变量就是实例变量,实例变量就是一个用self修饰的变量;
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。;
- 局部变量:定义在方法中的变量,只作用于当前实例的类;
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写;
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal);
- 实例化:创建一个类的实例,类的具体对象;
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
面向过程和面向对象的区别以及各自的优缺点我在这里就不进行记录了。
1.类的定义与使用
一个简单的类定义与使用例子:
# 定义学生类
class Student(object):
# 构造方法
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 方法
def print_age(self):
print("{}的年龄是:{}".format(self.name, self.age))
# 方法
def print_sex(self):
print("{}的性别是:{}".format(self.name, self.age))
if __name__ == '__main__':
# 创建类的实例
s_1 = Student("小明", '22', '男')
s_2 = Student("小红", "21", "女")
# 第一个学生信息
print("小明:")
s_1.print_age()
s_1.print_sex()
print("*"*20)
# 第二个学生信息
print("小红:")
s_2.print_age()
s_2.print_sex()
执行结果:
小明:
小明的年龄是:22
小明的性别是:22
********************
小红:
小红的年龄是:21
小红的性别是:21
2.类变量和实例变量
类变量又叫全局变量,是属于类的特性;实例变量是实例的特性。在调用过程中,实例可以调用类变量,但是类不可以调用实例变量。
可以这样理解:类变量是类的共有属性,而实例变量是每个实例特有的属性。例如对于“学生”这个类,“学习”是所有学生共有的属性,就可以作为类变量,而“姓名”、“学号”等这些用于区分学生的属性就是每个学生独有的了,这个学生叫“张三”,另一个学生叫“李四”,每个学生的姓名都不一样(假设没有重名),那么“姓名”这个属性就需要作为实例变量。
class MyClass(object):
name = '类变量' # 类变量
a = 10 # 类变量
b = 20
def __init__(self, name, age, sex): # 构造函数
self.name = name # self开头的这些都是实例变量
self.age = age
self.sex = sex
def func(self):
pass
if __name__ == '__main__':
# 类中调用类变量
print("类变量1:", MyClass.name)
print("类变量2:", MyClass.a)
# 实例化
my_class = MyClass('实例变量', 15, '男')
# 实例调用类变量
print("实例调用类变量:", my_class.a)
# 实例变量
print("实例变量:", my_class.age)
print("实例变量:", my_class.sex)
# 当类变量和实例变量名字相同时,实例在调用过程中,先去找实例变量,如果实例变量中没有,再去找类变量
print('实例调用类变量和实例变量共有变量:', my_class.name)
print(my_class.__dict__)
# 这里其实并不是改变类变量,而是在实例中添加了一个属性self.a=50,而类变量a=10并没有改变
my_class.a = 50
print("(假)改变后的类变量:", my_class.a) # 实例中增加变量a后,调用时先去找实例变量,此时的实例变量a=50
print("(假)改变后的类变量:", MyClass.a) # 类变量还是等于10
print(my_class.__dict__)
# 这样才能改变类变量的值
MyClass.b = 60
print("改变后的类变量:", MyClass.b)
print("改变后的类变量:", my_class.b) # 实例中没有b这个变量,所以去类变量中找
执行结果:
类变量1: 类变量
类变量2: 10
实例调用类变量: 10
实例变量: 15
实例变量: 男
实例调用类变量和实例变量共有变量: 实例变量
{'name': '实例变量', 'age': 15, 'sex': '男'}
(假)改变后的类变量: 50
(假)改变后的类变量: 10
{'name': '实例变量', 'age': 15, 'sex': '男', 'a': 50}
改变后的类变量: 60
改变后的类变量: 60
3.构造函数和析构函数
简单来说,构造函数和析构函数就是在类的初始化和删除时调用的函数。
- 构造函数__init__(self)
这个函数在定义类的时候会经常用到,具体作用就不再说。在这里记录一点:在创建对象,即类的实例化时,一定会调用该函数。所有当构造函数中有参数需要传入时,实例化对象中一定要传入对应的函数。 - 析构函数__del__(self)
这个函数并不是在del obj时候用到,而是在对象不被调用的时候就会用到析构函数,释放对象资源。
class MyClass(object):
def __init__(self):
print("构造函数")
def func(self):
print("执行一个方法")
def __del__(self):
print("析构函数")
if __name__ == '__main__':
my_class = MyClass()
my_class.func()
执行结果:
构造函数
执行一个方法
析构函数
可以看到,构造函数和析构函数并没有像调用其他方法一样进行调用,构造函数是在初始化对象时就会自动调用,而析构函数是在释放对象的时候自动调用。(当对象不被调用的时候,就会释放对象资源,此时自动调用析构函数)。
4.类的继承
4.1 多态
同一个方法在不同的类中的不同表现形式即为多态:
class A(object):
def func(self):
print("这是类A中的方法")
class B(object):
def func(self):
print("这是类B中的方法")
if __name__ == '__main__':
a, b = A(), B()
a.func()
b.func()
执行结果:
这是类A中的方法
这是类B中的方法
4.2 继承
继承是面向对象的重要特性之一,其重要性不言而喻。既然是继承,那么父类的所以公共属性和公共方法都会被子类继承。当然私有属性和私有方法还是只属于父类,子类并无权继承。
具体如何进行继承,这里就不再做记录。这里主要记录一下多继承。
4.3 多继承
一个子类可以继承多个父类,当多个父类有共同的属性或方法时,就需要有一个特定的顺序让子类进行继承。
多继承有两种不同的算法策略:深度优先和广度优先。
(调用大佬的一张图:)
python2和python3在多继承的顺序上稍有不同:
- python2:
经典类是按深度优先来继承的,新式类是按广度优先来继承的。 - python3:
经典类和新式类都是按广度优先来继承。
5.私有属性和私有方法
-
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。 -
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
实例
面向对象的其他知识先不记录了,等后续用到了再做补充。
写在最后
本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.