面向对象进阶
一、对象属性的增删改查
1.查获取对象的属性值
class Student:
def __init__(self, naem, age = 18, son = '000'):
self.name = naem
self. age = age
self.son = son
# 在当前类的对象被打印的时候自动调用,并且将这个方法的返回值作为打印结果(返回值必须是字符串)
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}>'
stu1 = Student('小明')
stu2 = Student('小花', 20, '00001')
"""
1)对象.属性 - 获取对象指定属性的值,属性不存在会报错
2)getattr(对象, 属性名) - 获取对象指定属性的值, 属性不存在会报错
3)getattr(对象, 属性名,默认值) - 获取对象指定属性的值, 属性不存在返回默认值
"""
print(stu1.name)
print(getattr(stu1, 'name'))
print(getattr(stu1, 'name', '无名氏'))
2.增、改
"""
1)对象.属性 = 值 - 当属性存在的时候修改属性的值,当属性不存在的时候添加属性
2)setattr(对象, 属性名,值) - 当属性的值存在就修改,不存在就增加属性
"""
stu1.name = '张三'
print(stu1)
stu1.gender = '女'
print(stu1)
setattr(stu1, 'age', 30)
print(stu1)
setattr(stu1, 'score', 100)
print(stu1)
3.删
"""
1) del 对象.属性 - 删除指定对象的指定属性
2)delattr(对象,属性名) - 删除指定对象的指定属性
"""
del stu1.age
print(stu1)
delattr(stu1, 'son')
print(stu1)
class A :
# __slots__ 属性的值就是当前类的对象最多能拥有的对象属性,如果为空,那么这个类的对象就不能有对象属性
# 注意:如果给类设置了__slots__,那么这个类的对象就不能在使用__dict__属性。
__slots__ = ('x')
def __init__(self):
self.x = 10
def __repr__(self):
return 5
a = A()
print(a)
二、内置属性
class A:
"""
什么是计算机
"""
pass
# 1.__doc__ - 类的说明文档
print(A.__doc__)
print(int(10).bit_length())
# 2.__module__ - 获取类所有的模块(类属性)
print(int.__module__)
print(A.__module__)
# 3. __class__ - 获取对象的类型,功能和type()
a = A()
print(a.__class__) # <class '__main__.A'>
print(type(a)) # <class '__main__.A'>
# 4.
# __dict__ - 获取类所有的类属性和对应的值,以字典的形式返回(类属性)
# __dict__ - 获取对象所有的对象属性和对应的值,以字典的形式返回(对象属性)
# 5. __name__ - 获取类的名字(类属性)
print(A.__name__) # 'A'
# 是?类型的数据
print('是{}的类型'.format((a.__class__.__name__)))
# 6.
# __base__ - 获取当前的父类
# __bases__ - 获取当前类的父类们
print(A.__base__) # <class 'object'> - 基类
print(A.__bases__) # (<class 'object'>,)
三、运算符重载
from copy import copy
# 1.python中的运算符
"""
python中每个运算符都对应一个固定的魔法方法,那个类型中实现了对应的魔法方法,那个类型的数据就支持对应的运算符
(python中某种数据是否支持某种运算符就看这个类中是否定义了运算对应的魔法方法)
"""
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __add__(self, other):
return self.name + other.name
# self * other
def __mul__(self, other):
return [copy(self) for _ in range(other)]
def __contains__(self, item):
pass
def __repr__(self):
return str(self.__dict__)
def __gt__(self, other):
return self.age > other.age
stu1 = Student('校花', 18)
stu2 = Student('班花', 19)
print(stu1 + stu2)
print(stu1 * 4)
stu_list = [stu1, stu2, Student('张三', 12)]
print(stu_list)
print(max(stu_list))
四、继承
1.继承
继承就是让子类直接拥有父类的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类
2.继承的语法
class 类名(父类):
说明文档
类的内容
class 类名(父类1,父类2,。。。。):
说明文档
类的内容
注意:如果定义类的时候没有写继承关系,那么这个类默认继承基类object
class 类名: == class 类名(object):
3.添加新属性和方法
添加方法和添加类属性;直接在类中定义新的属性和方法
添加对象属性
class Person:
num = 61
def __init__(self):
self.name = '张三'
self.age = 30
self.gender = '男'
def eat(self, food):
print(f'{self.name}在吃{food}')
@staticmethod
def func1():
print('静态方法')
class Student(Person):
x = '学生'
def __init__(self):
# 调用当前类的父类的__init__方法
super().__init__()
self.son = '001'
self.subject = 'python'
def study(self):
print('好好学习,天天向上!')
@classmethod
def func2(cls):
print('学生的方法')
stu = Student()
print(stu.name, stu.age)
stu.eat('包子')
print(stu.num)
print(Student.func1())
print(Student.x)
stu.study()
Student.func2()
print(stu.son, stu.subject)
class A:
def __init__(self, x, y):
self.x = x
self.y = y
class B(A):
def __init__(self, m, n, x=10, y=20):
super().__init__(x, y)
self.m = m
self.n = n
a = A(200, 300)
b = B(1, 2)
print(b.x, b.y)
五、继承的细节
子类和父类有相同的方法(重写)
super的用法
super(类,对象).方法() - 调用指定类的父类的指定方法
注意:()中的对象必须是()里面类的对象
多继承:子类只能继承第一个父类的对象属性(方法和类属性都可以继承)
私有化
访问权限(属性和方法的权限):公开的、保护的、私有的
公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
私有的 - 只能类的内部使用,不能被继承,也不能在外部使用
python中类的内容的权限只有一种:公开的
python的私有化是假的私有化,如果想要让属性和方法变成私有的,只需要在名字前加__(但是不能同时用__结尾)
python是私有化的本质:就存储数据的时候在私有化名字前加’_类名’
# 1.子类和父类有相同的方法(重写)
class A:
def func1(self):
print('A的func1')
class B(A):
def func1(self):
print('B的func1')
B().func1()
A().func1()
print('------------------------')
# 2.super的用法
"""
super(类,对象).方法() - 调用指定类的父类的指定方法
注意:()中的对象必须是()里面类的对象
"""
class A:
def func1(self):
print('A的func1')
class B(A):
def func2(self):
super(B, self).func1()
print('B的func1')
B().func2()
print('------------------------')
# 3.多继承:子类只能继承第一个父类的对象属性(方法和类属性都可以继承)
class AA:
num = 100
def __init__(self):
self.x = 1
self.y = 2
def func1(self):
print('对象方法AA')
class BB:
message = '你好'
def __init__(self):
self.m = 100
self.n = 200
def func2(self):
print('对象方法BB')
class CC(AA, BB):
pass
c = CC()
print(CC.num, CC.message)
c.func1()
c.func2()
print(c.x, c.y)
# 4.私有化
"""
访问权限(属性和方法的权限):公开的、保护的、私有的
公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
私有的 - 只能类的内部使用,不能被继承,也不能在外部使用
python中类的内容的权限只有一种:公开的
python的私有化是假的私有化,如果想要让属性和方法变成私有的,只需要在名字前加__(但是不能同时用__结尾)
python是私有化的本质:就存储数据的时候在私有化名字前加'_类名'
"""
class A:
m = 100
__n = 200
@staticmethod
def func():
print(A.m, A.__n)
A.__func2()
@staticmethod
def __func2():
print('私有方法')
A.func()
print(A._A__n)
六、拷贝
1.拷贝
1)赋值
直接将变量中的地址赋值给另一个变量,复制后两个变量指向同一块内存区域,并互相影响
2)浅拷贝
列表切片、列表.copy()、字典.copy()等都是浅拷贝
复制原数据产生一个新的数据,将新的数据的地址返回,如果原数据中有子对象(有可变数据),不会复制子对象
3)深拷贝
deepcopy
复制原数据产生一个新的数据,将新的数据的地址返回,如果原数据中有子对象(有可变数据),子对象也会被复制
from copy import copy, deepcopy
class Dog:
def __init__(self, name):
self.name = name
def __repr__(self):
return str(self.__dict__)
class Person:
def __init__(self, name, age=18, dog=None):
self.name = name
self.age = age
self.dog = dog
def __repr__(self):
return str(self.__dict__)
p1 = Person('小明', dog=Dog('财财'))
p2 = p1
p3 = copy(p1)
p4 = deepcopy(p1)
print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')
print('--------------------------------------------')
p1.name = '小花'
p1.dog.name = '大黄'
print(f'p1:{p1}, id:{id(p1)}')
print(f'p2:{p2}, id:{id(p2)}')
print(f'p3:{p3}, id:{id(p3)}')
print(f'p4:{p4}, id:{id(p4)}')
2.内存管理
1)内存的申请
定义变量保存数据的时候系统会自动申请。如果定义变量保存的时候是可变类型,每次都会申请新的内存,如果是不可变的数据,会检查这个数据是否已经保存,如果已经存储就不会再重新申请内存
2)释放
如果一个数据的引用计数(引用的个数)为0,那么这个数据就会被自动释放。
引用:保存数据地址的对象就是这个数据的引用