一、复习
1.类的声明
class 类名:
类的雷类容
2.类的属性
属性就是声明在类中的变量
a.对象属性:值会因为对象的不同而不同
声明在 init 方法中,
self.属性 = 值
对象.属性
b.类的字段:值不会因为对象的不同而不同
直接声明在类中
变量名 = 值
对象.属性
3.方法
a.对象方法:直接声明在类中,自带 self 参数,调用的时候不用传参,谁调用就指向谁
对象.方法()
实现函数的功能需要对象属性时
(1) init 方法:系统创建对象的时候,系统会自动调用, 需要通过构造方法来给
b.类方法:声明前加 @classmethod,自带 cls 参数,调用的时候,不用传参,谁调用就指向谁
类.方法()
实现函数的功能需要类的字段时
c.静态方法:声明前加 @stadicmethod 没有自带参数
类.方法()
实现函数的功能既不需要需要对象属性,也不需要类的字段时
二、私有化:
1.属性和方法
保护的:在外部不可以使用,可以继承
公开的:在外部可以使用,可以继承
2.python 的的私有化
在 python 中,属性或者方法名前加 (--),就可以加将属性或者方法变成私有的(注意)
私有的属性和方法只能在类的内部使用,不能在类的外面使用。
3.python 私有化的原理
在名字前是 __ 的属性和方法前再加 '_类名' 去保存属性和方法
class Person:
num = 61
__num2 = 62
def __init__(self, name='张三', age=0):
self.name = name
self.age = age
self.__sex = '男'
def eat(self, food):
print(self.__sex)
print(self.name, food)
self.__run()
def __run(self):
print('%s在跑步' % self.name)
@classmethod
def show_num(cls):
print('人类的数量:%d, %d' % (cls.num, cls.__num2))
@staticmethod
def func1():
print('人类要保护大自然!')
def main():
p1 = Person()
print(Person.num)
# print(Person.__num2)
print(p1.name)
# print(p1.__sex)
print(p1._Person__sex)
p1.eat('面条')
# p1.run()
Person.show_num()
Person.func1()
print(p1.__dict__)
if __name__ == '__main__':
main()
三、getter & setter
1.应用 getter 的场景:
getter : 获取属性的值之前想要做一些别的事情,就给这个属性添加 getter
setter : 给对象属性赋值之前想要做一些别的事情,就给这个属性添加 setter
2.getter :
第一步:申明属性时,在属性前加 ''
第二步:声明函数 @property (函数没有除了 self 以外的参数,但是要有返回值.返回值就是获取)
def 去掉 '' 的属性名(self):
做点别的事情
返回属性的值
第三步:
在类的外部,通过对象.去掉_的属性去获取相关
3.setter :
想要添加 setter 必须要先添加 getter
第一步: 声明属性的时候在属性名前面加 _
第二步:声明函数(函数除了 self 以外还需要一个参数,没有返回值.之类的参数代表给属性赋的值)
@属性名去掉.setter
def 去掉的属性名(self, 参数):
做点别的事情
给属性赋值
第三步:在类的外部通过 对象.去掉_ 的属性去给相关属性赋值
例如:
class Person:
def __init__(self, name=''):
self.name = name
self._age = 0
self._week = 1 # 属性名前面有 _ ,使用属性的时候不要直接使用
# 添加 setter
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int):
raise ValueError
if not (0 <= value <= 150):
raise ValueError
self._age = value
# 给 week 添加 getter
@property
def week(self):
print('---------------------------------')
if self._week < 7:
return '星期 %d ' % self._week
else:
print('星期天')
@week.setter
def week(self, value):
self._week = value
def main():
p1 = Person('阿黄')
p1.age = 23
p1.age = 2
print(p1.week)
p1.week = 5
if __name__ == '__main__':
main()
运行效果:
---------------------------------
星期 1
四 、继承
1.什么是继承
一个类继承一个类,其中会产生继承者和被继承者,这里的继承者加子类,被继承者叫父类/超类;
继承就是让子类直接拥有父类的方法和属性;
2.怎么继承
class 类名(父类列表)
类的内容
说明:
a.python 中所有的类都是直接或间接继承自基类 object
class 类名 --> class类名(object)
b.python 中的继承支持多继承,父类列表中可以拥有多个类,多各类之间用逗号隔开
3.继承能继承那些东西
所有的属性和方法都能继承,私有的属性都可以继承
注意:slots的值不会被继承,如果在类中给 slots 赋值后,当前类的对象不能使用 dict;但是这个类的子类对象可以使用__dict
只是 dict 中没有从父类继承下来的属性
如果父类没有给slots赋值,直接给子类的slots,会无效
例如:
class Person(object):
num1 = 123
def __init__(self, name='', age=0, sex='男'):
self.name = name
self.age = age
self.sex = sex
def eat(self, food):
print(' %s 在吃 %s' % (self.name, food))
@classmethod
def show_num(cls):
print('人类的数量为 : %s' % cls.num1)
class Student(Person):
pass
def main():
Student.num1 = 5000000
print(Student.num1)
stu = Student('阿黄')
stu.eat('火锅')
Student.show_num()
if __name__ == '__main__':
main()
运行效果:
5000000
阿黄 在吃 火锅
人类的数量为 : 5000000
五、添加属性和方法
1.添加方法
直接在子类中声明新的方法
子类可以使用父类的属性和方法,但是父类不能使用子类添加的属性和方法
2.方法的重写
在子类中重新实现父类已经拥有的方法 -----完全重写
在重写这个函数时,需要保留父类的功能在子类中添加新的功能
-----部分重写(在子类中通过'super().'的方式调用父类方法后添加新的代码)
3.类中函数的调用过程
a.
回到函数声明的位置,先看当前类中是否有方法,如果有就直接调用当前类中的方法;,没有就去看父类中有没有这个方法,
如果父类中也没有,就看父类的父类,以此类推,,,直到找到 object 类,如果 object 类里面也是没有,程序就报错
b.添加类的字段
c.添加对象属性
对象属性其实是由 init 方法继承下来的
例如:
class Person(object):
num1 = 123
def __init__(self, name, sex='男'):
self.name = name
self.age = 3
self.sex = sex
def eat(self, food):
print(' %s 再吃 %s' % (self.name, food))
@classmethod
def show_num(cls):
print('人类的数量为 : %s' % cls.num1)
class StudentPlus(Person):
def __init__(self, sno, name=None):
self.name = name
self.sno = sno
self.sex = '男'
self.age = 3
self.score = 90
class Student(Person):
def student(self):
print('%s 在睡觉' % self.name)
@classmethod
def show_num(cls):
print('学生的数量为: %d ' % cls.num1)
def main():
p1 = Person('阿黄')
stu1 = Student('大白')
stu1.student()
Person.show_num()
Student.show_num()
if __name__ == '__main__':
main()
运行效果:
大白 在睡觉
人类的数量为 : 123
学生的数量为: 123
六、多继承
一个类同时继承多个类
多继承:
class 类名(父类1, 父类2, 父类3......)
类的内容
多个父类中的所有方法和字段都可以继承,只是对象属性只能继承第一个父类的
例如:
class Animal:
def __init__(self, name, age=0, color='黑色'):
self.name = name
self.age = age
self.color = color
def func1(self):
print('对象 方法')
class Fly:
def __init__(self):
self.height = 100000
class Bride(Animal, Fly):
pass
def main():
p1 = Bride('阿黄')
print(p1.__dict__)
# print(p1.height) # 报错。 AttributeError: 'Bride' object has no attribute 'height'
if __name__ == '__main__':
main()
运行效果:
{'name': '阿黄', 'age': 0, 'color': '黑色'}
七、运算符的重载
1.什么是运算符重载
通过实现类中相应的魔法方法,来让自己的对象支持相应的运算符
注意:python 中所有的数据类型都是类,所有的数据都是对象
例如:
class Student:
def __init__(self, name='', age=0, score=0):
self.name = name
self.age = age
self.score = score
# 返回值就是运算结果
def __add__(self, other):
# 支持学生加学生
return self.age + other.age
# 大于和小于符号只需要重载一个后可以了
def __gt__(self, other):
return self.score > other.score
def main():
stu1 = Student('阿黄', 3, 50)
stu2 = Student('阿黄', 5, 50)
print(stu1 + stu2) # 相当于: print(stu1.__add__(stu2))
if __name__ == '__main__':
main()
运行效果:
8
八、内存管理机制
1.数据的存储(分为栈区间和堆区间)
栈区间:从底层来看,系统自动开辟、,释放的;一般存变量,函数的调用过程是在栈区间。
堆区间:从底层来看,由程序员自己开辟的空间;一般存数据(python 中所有的数据都是对象)。
从 python 的角度来看,程序员已经不需要写代码来开辟空间和释放空间了。
变量赋值过程:现在堆区间开辟空间把数据存起来,然后将数据对应的地址存到栈区间的变量中。
注意:数字、字符串在赋值的时候,不会直接开辟空间,会先检测之前有没有存储过这个数据,
如果有就用之前的数据地址。
2.内存释放(垃圾回收机制)原理:
python 中的每一个对象在创建的时候,都有一个属性,叫'引用计数',表示当前对象的应用个数。
判断一个对象是否销毁,就看'引用计数'是否为 0 ,为 0 就销毁,否则不销毁。
from sys import getrefcount (获取对象的引用计数)
例如:
from sys import getrefcount
def main():
list1 = [1, 2]
print(getrefcount(list1)) # 2
# 使用不同的变量存对象地址会增加引用计数
list2 = list1
print(getrefcount(list1)) # 3
[1, list1]
print(getrefcount(list1)) # 3
# def func1(obj):
# print(getrefcount(list1))
#
# func1(list1)
print(getrefcount(list1))
list1 = []
print(getrefcount(list2)) # 2
del list2
# print(getrefcount(list2)) # UnboundLocalError
# def getrefcount(obj):
# obj = list1
# 获取obj的引用计数
bullets = [{'x': 10, 'y': 20}, {'x': 30, 'y': 10}, {'x': 100, 'y': 200}]
del bullets[2]
bullets.pop(0)
if __name__ == '__main__':
main()
运行效果:
2
3
3
3
2
网友评论