day18-面向对象进阶

对象属性的增删改查

class Student:
    def __init__(self, name, age=18, study_id='0000'):
        self.name = name
        self.age = age
        self.study_id = study_id

    # 在当前类的对象被打印的时候自动调用,并且将这个方法的返回值作为打印结果
    def __repr__(self):
        # return str(self.__dict__)
        return f'<{str(self.__dict__)[1:-1]}>'


stu1 = Student('小明')
stu2 = Student('小花', 20, '0001')

1.查 - 获取属性值

1)对象.属性 - 获取对象指定属性的值,如果属性不存在报错
2)getattr(对象,属性名) - 获取对象指定属性的值,如果属性不存在报错
3)getattr(对象,属性名,默认值) - 获取对象指定属性的值,如果属性不存在返回默认值

print(stu1.name)
print(getattr(stu1, 'name'))

value = input('请输入需要获取的属性:')
# print(stu1.value)
print(getattr(stu1, value))
print(getattr(stu1, 'gender', '男'))  # 男

2.增、改

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

stu1.name = '张三'
print(stu1)  # <'name': '张三', 'age': 18, 'study_id': '0000'>
print(stu2)  # <'name': '小花', 'age': 20, 'study_id': '0001'>

stu1.gender = '女'
print(stu1)  # <'name': '张三', 'age': 18, 'study_id': '0000', 'gender': '女'>

setattr(stu1, 'age', 30)
print(stu1.age)  # 30

setattr(stu1, 'score', 100)
print(stu1)  # <'name': '张三', 'age': 30, 'study_id': '0000', 'gender': '女', 'score': 100>
print(stu1.score)  # 100

3.删

1)del 对象.属性 - 删除指定对象的指定属性
2)delattr(对象,属性名) - 删除指定对象的指定属性

del stu1.age
print(stu1)  # 'name': '张三', 'study_id': '0000', 'gender': '女', 'score': 100>

delattr(stu1, 'study_id')
print(stu1)  # <'name': '张三', 'gender': '女', 'score': 100>
class A:
    # __slots__属性的值就是当前类的对象最多能够拥有的对象属性,如果为空,那么这个类的对象就不能有对象属性
    # 注意:如果给类设置了__slots__,那么这个类的对象就不能再使用__dict__属性
    __slots__ = ('x', 'y', 'z')

    def __init__(self):
        self.x = 10
 
a = A()
a.y = 100
a.z = 200
# a.m = 300  # AttributeError

内置属性

class A:
    """数据库"""
    pass

1.doc - 类的说明文档(类属性)

print(A.__doc__)
print(dict.__doc__)

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 - 获取对象所有的对象属性和对应的值,以字典的形式返回(对象属性)

print(a.__dict__)  # {}

5.name - 获取类的名字(类属性)

print(A.__name__)  # 'A'

print(f'是{a.__class__.__name__}的类型')  # 是A的类型

6.

base - 获取当前类的父类

bases - 获取当前类的父类们

print(A.__base__)  # <class 'object'> - 基类
print(A.__bases__)  # (<class 'object'>,)

运算符重载

1.Python中的运算符

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

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

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __add__(self, other):
        return self.age + other.age

    def __repr__(self):
        return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'

    def __gt__(self, other):
        return self.age > other.age



stu1 = Student('小明', 18)
stu2 = Student('小花', 20)

a = stu1+stu2  # a = stu1.__add__(stu2)
print(a)   # 38


stu_list = [stu1, stu2, Student('张三', 12)]
print(stu_list)

# print(max(stu_list, key=lambda item: item.age))
print(max(stu_list))

继承

1.继承

继承就是让子类直接拥有父类的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类

2.继承的语法

class 类名(父类):
说明文档
类的内容

class 类名(父类1,父类2,…):
说明文档
类的内容

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

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

3.添加新属性和方法

1)添加方法和添加类属性
直接在子类中定义新的类属性和方法

2)添加对象属性

class Person:
    num = 41

    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.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)
stu.func1()

print(Student.x)
stu.study()
Student.func2()
print(stu.study_id, stu.subject)

继承细节问题

1.子类和父类有相同的方法(重写)

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


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


B().func1()  # B的func1
A().func1()  # A的func1

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()  # A的func1 B的func1

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

class AA:
    num = 100

    def __init__(self):
        self.x = 1111
        self.y = 2222

    def func1(self):
        print('对象方法AA')


class BB:
    message = '你好'

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

    def func2(self):
        print('对象方法BB')


class CC(AA, BB):
    pass


c = CC()
print(CC.num, CC.message)   # 100 你好

c.func1()  # 对象方法AA
c.func2()  # 对象方法BB

print(c.x, c.y)  # 1111 2222
# print(c.m, c.n) # AttributeError: 'CC' object has no attribute 'm'

4.私有化

访问权限(属性和方法的权限):公开的、保护的、私有的
公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
私有的 - 只能在类的内部使用、不能被继承、也不能在外部使用

Python中类的内容的权限只有一种:公开的
Python的私有:想要让属性和方法变成私有的,只需要在名字前加__(但是不能同时用__结尾)
Python私有化的本质:就存储数据的时候在私有化名字前加’_类名’

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

class A:
    m = 1000
    __n = 200

    @staticmethod
    def func1():
        print(A.m, A.__n)


print(A.m)  # 1000
A.func1()  # 1000 200

# print(A.__n)  # AttributeError: type object 'A' has no attribute '__n'
print(A._A__n)  # 200

拷贝

1.拷贝

1)直接赋值
直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,并且相互影响
2)浅拷贝
列表切片、列表.copy()、字典.copy()等都是浅拷贝
赋值原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象
3)深拷贝
deepcopy
复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),子对象也会被复制

class Dog:
    def __init__(self, name, gender='公'):
        self.name = name
        self.gender = gender

    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,那么这个数据就会被自动释放。
引用:保存数据地址的对象就是这个数据的引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值