天天看点

day18-面向对象进阶

对象属性的增删改查

1.查 - 获取属性值

1)对象.属性 - 获取对象指定属性的值,如果属性不存在报错

2)getattr(对象,‘属性名’) - 获取对象指定属性的值,如果属性不存在报错

​ getattr(对象,‘属性名’,默认值) - 获取对象指定属性的值,如果属性不存在返回默认值

# 在当前类的对象被打印的时候自动调用,并且将这个方法的返回值作为打印的结果(返回值必须是字符串)
def __repr__(self):
    print(type(self.__dict__)) # dict
    return str(self.__dict__)

# __slots__属性值就是当前类的对象最多能够拥有的对象属性,如果为空,那么这个类的对象就不能有对象属性
# 注意:如果给类设置了__slots__,那么这个类的对象就不能再使用__dict__属性
class A:
    __slots__=('x', 'y', 'z')
           

2.增、改

1)对象.属性 = 值 - 当属性存在的时候,修改属性的值,当属性不存在的时候添加属性

2)setattr(对象,‘属性名’,值)

3.删

1)del 对象.属性 - 删除指定对象的指定属性

2)delattr(对象,‘属性名’) - 删除指定对象的指定属性

内置属性

1.

__doc__

- 类的说明文档

2.

__module__

- 获取类所在的模块(类属性)

3.

__class__

- 获取对象的类型,功能和type()

4.

__dict__

- 获取类所有类属性和对应的值,以字典的形式返回(类属性)

​ 获取对象所有对象属性和对应的值,以字典的形式返回(对象属性)

5.

__name__

- 获取类的名字(类属性)

6.

__base__

- 获取当前类的父亲

__bases__

- 获取当前类的父类们

运算符重载

1.python中的运算符

python中每个运算符都对应一个固定的魔法方法,哪个类型中实现的对应的魔法方法,那个类型的数据就支持对应的运算符

(python中某个数据是否支持某种运算符就看这个类中是否定义了运算符对应的魔法方法)

继承

1.让子类直接拥有父类的属性和方法

子类 - 继承者

父类 - 被继承者,又叫超类

2.继承语法

class 类名(父类1,父类2,…):

​ 说明文档

​ 类的内容

注意:如果定义类的时候没有写继承关系,那么这个类默认继承基类object

class 类名: == class 类名(object):

3.添加新属性和方法

1)添加方法和添加类属性

直接再子类中定义新的类属性和方法

2)添加对象属性

class Person:
    num = 61

    def __init__(self):
        self.name = '张三'
        self.age = 30
        self.gender = '男'

    def eat(self, food):
        print(f'在吃{food}')

    @staticmethod
    def func1():
        print('静态方法')


class Student(Person):
    x = '学生'

    def __init__(self):
        # 调用当前类的父类的__init__方法
        super().__init__()
        self.study_id = '0001'
        self.subject = 'Python'

    def study(self):
        print('好好学习,天天向上!')

    @classmethod
    def func2(cls):
        print('学生的类方法')


stu = Student()
print(stu.name, stu.age, stu.gender)
stu.eat('包子')

print(Student.num)
Student.func1()

print(Student.x)
stu.study()
Student.func2()
print(stu.study_id, 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)
# b.x = 3
# b.y = 4
           
# 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的func2')


B().func2()


print('-------------------------------------------------')
class A:
    def func1(self):
        print('A的func1')

    def func2(self):
        print('A的func2')


class B(A):
    def func1(self):
        print('B的func1')


class C:
    def func1(self):
        print('C的func1')


class D(C):
    def func1(self):
        super(B, B()).func2()
        print('D的func1')


d = D()
d.func1()

print('-------------------------------------------')


# 3.多继承: 子类只能继承第一个父类的对象属性(方法和类属性都可以继承)
class AA:
    num = 100

    def __init__(self):
        self.x = 100
        self.y = 200

    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)
# print(c.m, c.n)   # AttributeError: 'CC' object has no attribute 'm'
           

4.私有化

访问权限(属性和方法的权限):公开的、保护的、私有的

公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承

保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承

私有的 - 只能在类的内部使用,不能被继承,也不能在外部使用

python中类的内容的权限只有一种:公开的

python的私有化是假的私有化,如果想让属性和方法变成私有的只需要在名字前加__(但是不能同时用__结尾)

python私有化的本质:就存储数据的时候在私有化名字前加’_类名’

python中的保护:在名字前加_

拷贝

1)直接赋值

直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,并且互相影响

2)浅拷贝

列表切片、列表.copy()、字典.copy()等都是浅拷贝

复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象

3)深拷贝

deepcopy

复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象,子对象也会被复制

2.内存管理

1)内存的申请

定义变量保存数据的时候系统会自动申请。如果定义变量保存的是时候可变数据,每次都会申请新的内存,如果是不可变的数据,会检查这个数据是否已经保存过,如果已经存储就不会再重新申请内存

2)释放

如果一个数据的引用计数(引用的个数)为0,那么这个数据就会被自动释放

引用:保存数据地址的对象就是这个数据的引用