python_面向对象进价

1.对象属性的增删改查

  • 查 - 获取属性值
  1. 对象.属性 - 获取对象指定属性的值,如果属性不存在报错
  2. getattr(对象, 属性名) - 获取对象指定属性的值,如果属性不存在报错
  3. getattr(对象, 属性名, 默认值) - 获取对象指定属性的值,如果属性不存在返回默认值
  • 代码如下:
    class Student:
        def __init__(self, name, age=18, study_id='000'):
            self.name = name
            self.age = age
            self.study_id = study_id
    
        # 在当前类的对象被打印的时候自动调用,并且将这个方法的返回值作为打印结果(返回值必须是字符串)
        def __repr__(self):
            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'))
    print(getattr(stu1, 'name', '无名氏'))
    
    # value = input('请输入需要获取的属性:')
    # print(getattr(stu1, value))
    
    # print(stu1.gender)    # AttributeError: 'Student' object has no attribute 'gender'
    # print(getattr(stu1, 'gender'))      # AttributeError: 'Student' object has no attribute 'gender'
    print(getattr(stu1, 'gender', '男'))     # 男
    
  • 增、改
  1. 对象.属性 = 值 - 当属性存在的时候修改属性的值,当属性不存在的时候添加属性
  2. setattr(对象, 属性名, 值) - 当属性存在的时候修改属性的值,当属性不存在的时候添加属性
  • 代码如下:
    stu1.name = '张三'
    # print(stu1.__dict__)    # {'name': '张三', 'age': 18, 'study_id': '000'}
    print(stu1)     # "{'name': '张三', 'age': 18, 'study_id': '000'}"
    
    stu1.gender = '女'
    print(stu1)     # <'name': '张三', 'age': 18, 'study_id': '000', 'gender': '女'>
    print(stu1.gender)
    
    setattr(stu1, 'age', 30)
    print(stu1.age)     # 30
    
    setattr(stu1, 'score', 100)
    print(stu1)     # <'name': '张三', 'age': 30, 'study_id': '000', 'gender': '女', 'score': 100>
    print(stu1.score)       # 100
    

  • 1)del 对象.属性 - 删除指定对象的指定属性
    2)delattr(对象, 属性名) - 删除指定对象的指定属性
  • 代码如下:
    del stu1.age
    print(stu1)     # <'name': '张三', 'study_id': '000', 'gender': '女', 'score': 100>
    # print(stu1.age)     # AttributeError: 'Student' object has no attribute 'age'
    
    delattr(stu1, 'study_id')
    print(stu1)         # <'name': '张三', 'gender': '女', 'score': 100>
    
    stu1.neme = '李四'
    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
    

2.内置属性

  • class A:
        """还是计算机是"""
        pass
    # 1. __doc__    -   类的说明文档(类属性)
    print(int.__doc__)
    print(int(10).bit_length())
    # 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__}的类型')
    # 6.
    # __base__   -  获取当前类的父类
    # __bases__  -  获取当前类的父类们
    print(A.__base__)    # <class 'object'>  - 基类
    print(A.__bases__)      # (<class 'object'>,)
    

3.运算符重载

  • python中的运算符
    python中每个运算符都对应一个固定的魔法方法,哪个类型中实现的对应的魔法方法,那个类型的数据就支持对应的运算符。
    (python中某种数据是否支持某种运算符就看这个类中是否定义了运算符对应的魔法方法)
  • 代码如下:
    from copy import copy
    print(10 + 29)
    print('abc' + '34')
    print([10, 34] + [239, 0, 'abc'])
    print(10 - 9)
    print({23, 89} - {23})
    # 10 + 29   ==  10.__add__(29)
    # 'abc' + '34'   ==  'abc'.__add__('34')
    class Student:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        # self + other
        def __add__(self, other):
            return 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 f'<{str(self.__dict__)[1:-1]}, id: {id(self)}>'
            # return str(self.__dict__)
    stu1 = Student('小明', 18)
    stu2 = Student('小花', 20)
    a = stu1 + stu2     #  a = stu1.__add__(stu2)
    print(a)
    print(stu1 * 4)
    # print(stu1 in stu2)
    stu_list = [stu1, stu2, Student('张三', 12)]
    print(stu_list)
    # print(max(stu_list, key=lambda item: item.age))
    print(max(stu_list))
    

4.继承

+继承
继承就是让子类直接拥有父类的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类
2. 继承的语法
class 类名(父类):
说明文档
类的内容
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

5.继承细节

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

  • super的用法
    super(类, 对象).方法() - 调用指定类的父类的指定方法
    注意:()中的对象必须是()里面类的对象

  • 代码如下:

    子类和父类有相同的方法(重写)
    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'
    
  • 私有化
    访问权限(属性和方法的权限):公开的、保护的、私有的
    公开的 - 在类的外部可以使用、类的内部可以使用、也可以被继承
    保护的 - 在类的外部不可以使用、类的内部可以使用、也可以被继承
    私有的 - 只能在类的内部使用,不能被继承,也不能在外部使用
    python中类的内容的权限只有一种:公开的
    python的私有化: 想让属性和方法变成私有的只需要在名字前加__(但是不能同时用__结尾)
    python私有化的本质:就存储数据的时候在私有化名字前加 '类名’
    python中的保护:在名字前加

  • 代码如下:

    print('------------------------------------------')
    class A:
        m = 100
        __n = 200
    
        @staticmethod
        def func1():
            print(A.m, A.__n)
            A.__func2()
    
        @staticmethod
        def __func2():
            print('私有方法')
    
    print(A.m)
    A.func1()
    
    # print(A.__n)
    # A.__func2()
    
    print(A._A__n)
    # python之禅
    

6.拷贝

  1. 拷贝
    1)直接赋值
    直接将变量中的地址赋值给另外一个变量,赋值后两个变量指向同一块内存区域,并且相互影响
    2)浅拷贝
    列表切片、列表.copy()、字典.copy()等都是浅拷贝、copy()
    复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象(有可变数据),不会复制子对象
    3)深拷贝
    deepcopy
    复制原数据产生一个新的数据,将新的数据的地址返回。如果原数据中有子对象,子对象也会被复制
    2.内存管理
    1)内存的申请
    定义变量保存数据的时候系统会自动申请。如果定义变量保存的时候可变数据,每次都会申请新的内存,如果是不可变的数据,会检查这个数据
    是否已经保存过,如果已经存储就不会再重新申请内存。
    2)释放
    如果一个数据的引用计数(引用的个数)为0,那么这个数据就会被自动释放。
    引用:保存数据地址的对象就是这个数据的引用
    3.代码如下:
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)}')
上一篇:python学习day31笔记


下一篇:派生类中的构造函数