• python 面向对象


    Prerequisite

    如题所示,面向对象
    参考文章:廖雪峰

    基础面向对象

    访问限制

    • 实例的变量名如果以 __ 开头,就变成了一个私有变量,只有内部可以访问
    • 如果以一个下划线开头的实例变量名,比如 _name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”
    • 类似 __xxx__ 的属性和方法在 Python 中都是有特殊用途的,比如 __len__ 方法返回长度,如果你调用 len() 函数试图获取一个对象的长度,实际上,在 len() 函数内部,它自动去调用该对象的 __len__() 方法
    # 所以,下面的代码是等价的
    len('ABC')
    # 3
    'ABC'.__len__()
    # 3
    
    class Student(object):
    
        def __init__(self, name, score):
            self.__name = name
            self.__score = score
    
        def print_score(self):
            print('%s: %s' % (self.__name, self.__score))
    
    student = Student("tuan", "666")
    
    # 报错,访问不了私有变量
    print(student.__name)
    print(student.__score)
    
    student.print_score()
    # tuan: 666
    

    如果突然运行外部获取私有变量,可以设置 get_name 函数
    如果要更改里面的私有变量,不妨设置 set_name 函数

    def get_name(self):
        return self.__name
    
    def set_score(self, score):
        if 0 <= score <= 100:
            self.__score = score
        else:
            raise ValueError('bad score')
    

    鸭子类型

    简单的说,就是无论是不是源自同一个父类或者祖父类等,只有它们有相同的函数,那么就是鸭子类型

    class Animal(object):   #编写Animal类
        def run(self):
            print("Animal is running...")
    
    class Dog(Animal):  #Dog类继承Amimal类,没有run方法
        pass
    
    class Cat(Animal):  #Cat类继承Animal类,有自己的run方法
        def run(self):
            print('Cat is running...')
        pass
    
    class Car(object):  #Car类不继承,有自己的run方法
        def run(self):
            print('Car is running...')
    
    class Stone(object):  #Stone类不继承,也没有run方法
        pass
    
    def run_twice(animal):
        animal.run()
        animal.run()
        print('\n')
    
    run_twice(Animal())
    run_twice(Dog())
    run_twice(Cat())
    run_twice(Car())
    run_twice(Stone())
    
    """
    Animal is running...
    Animal is running...
    
    
    Animal is running...
    Animal is running...
    
    
    Cat is running...
    Cat is running...
    
    
    Car is running...
    Car is running...
    
    # Stone 类就报错了,因为他没有 run 函数
    Traceback (most recent call last):
      File "C:\Users\WPS\Desktop\Temporary\test.py", line 29, in <module>
        run_twice(Stone())
      File "C:\Users\WPS\Desktop\Temporary\test.py", line 21, in run_twice
        animal.run()
    AttributeError: 'Stone' object has no attribute 'run'
    """
    

    实例属性和类属性

    实例属性大于类属性,直接举例

    class Student(object):
        name = 'Bob'
    
    # 类属性
    student = Student()
    print(student.name)
    # Bob
    
    # 添加实例属性
    student.name = 'Alice'
    print(student.name)
    # Alice
    
    # 删除实例属性
    del student.name
    print(student.name)
    # Bob
    

    高级面向对象

    限制实例属性使用 slots

    class Student(object):
        __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
    
    s = Student() # 创建新的实例
    s.name = 'Michael' # 绑定属性'name'
    s.age = 25 # 绑定属性'age'
    
    s.score = 99 # 绑定属性'score'
    # 失败,因为 score 没有被放到__slots__中
    
    
    class GraduateStudent(Student):
        pass
    
    g = GraduateStudent()
    g.score = 9999
    # 成功,因为__slots__对继承的子类是不起作用的
    # 但是如果子类也使用__slots__,那么__slots__不仅对自己起作用,也会继承父类的__slots__
    

    直接调用/修改类属性和只读使用 @property

    class Student(object):
    
        @property # 调用属性
        def birth(self):
            return self._birth
    
        @birth.setter # 修改属性
        def birth(self, value):
            self._birth = value
    
        @property # 只读
        def age(self):
            return 2015 - self._birth
    
    student = Student()
    student.birth = 2002 # 修改
    print(student.birth) # 调用
    print(student.age) # 只读
    

    多继承

    原理很简单,就是一个类继承一个主类,再添加额外的功能(额外的类),其实一般的设计思路就是如此

    class Animal(object):
        pass
    
    # 大类:
    class Mammal(Animal):
        pass
    
    class Bird(Animal):
        pass
    
    # 各种动物:
    class Dog(Mammal):
        pass
    
    class Bat(Mammal):
        pass
    
    class Parrot(Bird):
        pass
    
    class Ostrich(Bird):
        pass
    
    # 额外的功能
    class Runnable(object):
        def run(self):
            print('Running...')
    
    class Flyable(object):
        def fly(self):
            print('Flying...')
    
    # 多继承
    class Dog(Mammal, Runnable):
        pass
    
    class Bat(Mammal, Flyable):
        pass
    

    定制类

    这些功能在廖雪峰这篇文章里面,我基本用不到,了解一下即可

    • 调用函数名字(strrepr
    • 类使用 for 循环(iternextgetitem
    • 调用不存在的属性(getattr
    • 链式调用 API(getattr
    • 调用实例自身(call

    使用枚举类

    以星期的枚举类举例:

    from enum import Enum, unique
    
    @unique
    class Weekday(Enum):
        Sun = 0 # Sun的value被设定为0
        Mon = 1
        Tue = 2
        Wed = 3
        Thu = 4
        Fri = 5
        Sat = 6
    

    使用案例

    >>> day1 = Weekday.Mon
    >>> print(day1)
    Weekday.Mon
    >>> print(Weekday.Tue)
    Weekday.Tue
    >>> print(Weekday['Tue'])
    Weekday.Tue
    >>> print(Weekday.Tue.value)
    2
    >>> print(day1 == Weekday.Mon)
    True
    >>> print(day1 == Weekday.Tue)
    False
    >>> print(Weekday(1))
    Weekday.Mon
    >>> print(day1 == Weekday(1))
    True
    >>> Weekday(7)
    Traceback (most recent call last):
      ...
    ValueError: 7 is not a valid Weekday
    >>> for name, member in Weekday.__members__.items():
    ...     print(name, '=>', member)
    ...
    Sun => Weekday.Sun
    Mon => Weekday.Mon
    Tue => Weekday.Tue
    Wed => Weekday.Wed
    Thu => Weekday.Thu
    Fri => Weekday.Fri
    Sat => Weekday.Sat
    

    使用元类

    看不懂,略(●'◡'●)

  • 相关阅读:
    迅为4412开发板一键烧写QT程序到开发板
    迅为-i.IMX6Q开发板QT系统移植wifi-mt6620(一)
    迅为3399开发板人工智能测试-对象检测
    迅为IMX6ULL开发板搭建 Web 服务器
    迅为IMX6开发板AndroidStudio-ledtest小灯_测试
    迅为3399开发板Android7/Android8修改开机动画
    layui
    MyBatis
    开发过程,一个完整的开发过程需要完成哪些工作?分别由哪些不同的角色来完成这些工作?
    做好测试计划工作的关键是什么?
  • 原文地址:https://www.cnblogs.com/CourserLi/p/16523583.html
Copyright © 2020-2023  润新知