Python面向对象进阶
对象属性的增删改查
-
查 — 获取属性值
1)、对象.属性 — 获取对象指定属性的值,若属性不存在则报错
2)、getattr(对象,属性名) — 获取对象指定属性的值,若属性不存在则报错
3)、getattr(对象,属性名,默认值) — 获取对象指定属性的值,若属性不存在则返回默认值
class Student:
def __init__(self,**info):
self.name = info['name']
self.age = info['age']
self.number = info['number']
#在当前类的对象被打印时自动调用,并将这个方法的返回值作为打印结果
def __repr__(self):
# return __dict__
return str(self.__dict__)
student1 = Student(name='柱子',age=18,number='001')
# 查
value = input('请输入需要查看的信息:')
print(getattr(student1,value))
# print(student1.__dict__) #{'name': '柱子', 'age': 18, 'number': '001'}
print(student1)
-
增、改
1)、对象.属性 = 值 — 当属性存在时修改属性的值,当属性不存在的时候添加属性
2)、setattr(对象,属性名,值) — 当属性存在时修改属性的值,当属性不存在的时候添加属性
# 改 # student1.age = 30 setattr(student1,'age',30) print(student1.age) # 增 # student1.score = 99 setattr(student1,'score',99) print(student1)
-
删
1)、del 对象.属性 — 删除指定对象的指定属性2)、delattr(对象,属性名) — 删除指定对象的指定属性(动态)
#删
# del student1.age
# print(student1) #{'name': '柱子', 'number': '001', 'score': 99}
delattr(student1,'age')
print(student1) #{'name': '柱子', 'number': '001', 'score': 99}
内置属性
class Test:
pass
test = Test()
- __ doc__ — 获取类的说明文档
print(int.__doc__)
print(int(99).bit_length())
- __ module__ — 获取类所在模块(类属性)
print(int.__module__)
- __ class__ — 获取对象的类型,功能和type()一样
print(test.__class__)
-
__ dict__ — 获取类所有的类属性和对应的值,以字典方式返回(类属性)
__ dict__ — 获取对象所有的对象属性和对应的值,以字典方式返回(对象属性)
print(test.__dict__)
- __ name__ — 获取类的名字(类属性)
print(test.__class__.__name__)
-
__ base__ — 获取当前类的父类
__ bases__ — 获取当前类的父类们
若无继承关系则返回基类(<class ‘object’>)
# 获取父类
print(Test.__base__) #<class 'object'>
# 获取父类们
print(Test.__bases__) #(<class 'object'>,)
运算符重载
python中每一个运算符都对应一个固定魔法方法,哪个类型中实现了对应的魔法方法,那个类型的数据就支持对
应的运算符
(Python中某种数据是否支持某种运算符就看这个类中是否定义了运算符对应的魔法方法)
from copy import copy
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
# self + other
def __add__(self, other):
return self.name + other.name,self.age + other.age
# self * other
def __mul__(self, other):
return [copy(self) for _ in range(other)]
# self > other # 重载了'>','<'可直接用
def __gt__(self, other):
return self.age > other.age
def __repr__(self): #控制输出格式
return str(self.__dict__)
student1 = Student('小明',18)
student2 = Student('小红',12)
print(student1 + student2) #('小明小红', 30)
print(student1 * 3) #[{'name': '小明', 'age': 18}, {'name': '小明', 'age': 18}, {'name': '小明', 'age': 18}]
print(min(student1,student2)) #{'name': '小红', 'age': 12}
继承
继承就是让子类直接拥有父类的属性和方法
子类 — 继承者
父类 — 被继承者,又叫超类
语法
单继承:
class 类名(父类):
说明文档
类的内容
多继承:
class 类名(父类1,父类2…):
说明文档
类的内容
注意:如果定义类的时候没有写继承关系,那么这个类默认继承基类object class 类名: == class 类名(object):
添加新属性和方法
1)、添加方法和类属性
直接在子类中定义新的类属性和方法
2)、添加对象属性
class Person:
def __init__(self,name = '张三', age = 18, sex = '男'):
self.name = name
self.age = age
self.sex = sex
def eat(self,food = '馒头'):
print(f'{self.name}在吃{food}!')
class Student(Person):
# 添加新方法与类属性
msg = '我是子类类属性'
@classmethod
def study(self):
print('好好学习!(我是子类类方法)')
@staticmethod
def static():
print('我是子类静态类方法!')
# 添加对象属性
def __init__(self,number = '001', subject = 'python'):
super().__init__() #调用当前父类的__init__方法
self.number = number
self.subject = subject
def __repr__(self):
return str(self.__dict__)
# 继承
student = Student()
print(student)
student.eat()
# 添加类属性和方法
print(Student.msg)
Student.study()
# 添加对象属性
print(f'{student.name}学号是{student.number}TA是{student.subject}班的')
重写
子类和父类有相同的方法(重写)
class A:
def func1(self):
print('我是父类A的func1')
class B(A):
def func1(self):
print('我是子类B的func1')
super()的用法
super(类,对象).方法() — 调用指定类的父类的指定方法
注意:()中的对象必须是()里面类的对象
多继承:子类只能继承第一个父类的对象属性(方法和类属性都会继承)
class AA:
def __init__(self):
self.x = 100
self.y = 200
def func(self):
print('对象方法AA')
class BB:
def __init__(self):
self.m = 100
self.n = 200
def func(self):
print('对象方法BB')
class CC(AA,BB):
def func(self):
print('对象方法AA')
# 无法继承第一个父类以外的对象属性
c = CC()
# print(c.m,c.n) #RuntimeError: super(): no arguments
print(c.x,c.y)
私有化
访问权限(属性和方法的权限):公开、保护、私有
公开:在类的外部可以使用、类的内部可以使用也可被继承
保护:在类的外部不可以使用、类的内部可以使用也可被继承
私有:在类的外部不可以使用、类的内部可以使用不可被继承
Python中类的内容的权限只有一种:公开
python中的私有化是"假"的私有化,如果想让属性和方法变成私有的只需要在前面加’_ _ ’
python 私有化的本质:就是在存储数据的时候在在私有化名字前加 ’ _ 类名’
python中的保护:在名字面前加’_’
class D:
__private = '我是私有类属性'
@classmethod
def __func1(self):
print('我是D的私有类方法')
# def __repr__(self):
# return str(self.__dict__)
d = D()
# print(d.__private) #AttributeError: 'D' object has no attribute '__private'
# 强制使用
print(d._D__private) #我是私有类属性
print(d)
拷贝与内存管理
from copy import copy,deepcopy
拷贝
1)、直接赋值
直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,相互影响
2)、浅拷贝
列表切片、列表.copy()、字典.copy()等都是浅拷贝
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象
3)、深拷贝
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),也会复制子对象
当数据为不可变数据时(元组),数据都只保存一次,所以深浅拷贝无差别;
当数据为可变数据时(列表),深浅拷贝差距一目了然
class Dog:
def __init__(self, name = '旺财', age = 1):
self.name = name
self.age = age
def __repr__(self):
return str(self.__dict__)
class Person:
def __init__(self, name = '小花', age = 18, dog = Dog()):
self.name = name
self.age = age
self.dog = dog
def __repr__(self):
return str(self.__dict__)
person1 = Person()
person2 = person1 #直接赋值
person3 = copy(person1) #浅拷贝
person4 = deepcopy(person1) #深拷贝
print(f'person1:{person1} id1:{id(person1)}')
print(f'person2:{person2} id2:{id(person2)}')
print(f'person3:{person3} id3:{id(person3)}')
print(f'person4:{person4} id4:{id(person4)}')
'''
person1:{'name': '小花', 'age': 18, 'dog': {'name': '旺财', 'age': 1}} id1:1978330611568
person2:{'name': '小花', 'age': 18, 'dog': {'name': '旺财', 'age': 1}} id2:1978330611568
person3:{'name': '小花', 'age': 18, 'dog': {'name': '旺财', 'age': 1}} id3:1978330690896
person4:{'name': '小花', 'age': 18, 'dog': {'name': '旺财', 'age': 1}} id4:1978330691040
'''
print('-----------------------------------------------------------')
person1.name = '柱子'
person1.dog.name = '来福'
print(f'person1:{person1} id1:{id(person1)}')
print(f'person2:{person2} id2:{id(person2)}')
print(f'person3:{person3} id3:{id(person3)}')
print(f'person4:{person4} id4:{id(person4)}')
'''
person1:{'name': '柱子', 'age': 18, 'dog': {'name': '来福', 'age': 1}} id1:1978330611568
person2:{'name': '柱子', 'age': 18, 'dog': {'name': '来福', 'age': 1}} id2:1978330611568
person3:{'name': '小花', 'age': 18, 'dog': {'name': '来福', 'age': 1}} id3:1978330690896
person4:{'name': '小花', 'age': 18, 'dog': {'name': '旺财', 'age': 1}} id4:1978330691040
'''
内存管理
-
内存的申请
定义变量保存数据的时候系统会自动申请,若保存的是可变数据,每次都会申请新的内存
如果是不可变的数据会检查这个数据是否保存过若已经保存过就不会再重新申请内存
-
释放
如果一个数据的引用计数(引用个数)为0,那么这个数据就会被自动释放
引用:保存数据地址的对象就是这个数据的引用