面向对象高级

1. issubclass和isinstance

1.1 'issubclass'

issubclass() 方法用于判断参数 class 是否是类型参数 classinfo 的子类。

语法

以下是 issubclass() 方法的语法:

issubclass(class, classinfo)

参数

  • class -- 类。
  • classinfo -- 类。

返回值

如果 class 是 classinfo 的子类返回 True,否则返回 False。

# 返回C1是否是C2的子类
issubclass(C1, C2)

1.2 isinstance

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。

isinstance() 与 type() 区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。

如果要判断两个类型是否相同推荐使用 isinstance()。

语法

以下是 isinstance() 方法的语法:

isinstance(object, classinfo)

参数

  • object -- 实例对象。
  • classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。

返回值

如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。

2. 反射

2.1 反射

反射就是通过字符串来操作类或者对象的属性

  • 反射本质就是在使用内置函数,其中反射有以下四个内置函数:

    1. hasattr:判断一个方法是否存在与这个类中
    2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行
    3. setattr:通过setattr将外部的一个函数绑定到实例中
    4. delattr:删除一个实例或者类中的方法
    

2.2 反射机制

反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!

  • getattr()函数是Python自省的核心函数,getattr() 函数用于返回一个对象属性值。

    语法

    getattr 语法:

    getattr(object, name[, default])
    

    参数

    • object -- 对象。
    • name -- 字符串,对象属性。
    • default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

    返回值

    返回对象属性值。

    实例

    以下实例展示了 getattr 的使用方法

    >>>class A(object):
    ...     bar = 1
    ... 
    >>> a = A()
    >>> getattr(a, 'bar')        # 获取属性 bar 值
    1
    >>> getattr(a, 'bar2')       # 属性 bar2 不存在,触发异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'A' object has no attribute 'bar2'
    >>> getattr(a, 'bar2', 3)    # 属性 bar2 不存在,但设置了默认值
    3
    >>>
    
    • hasattr() 函数用于判断对象是否包含对应的属性。

      语法

      hasattr 语法:

      hasattr(object, name)
      

      参数

      • object -- 对象。
    • name -- 字符串,属性名。

      返回值

    如果对象有该属性返回 True,否则返回 False。

    实例

    以下实例展示了 hasattr 的使用方法:

    class Coordinate:
        x = 10
        y = -5
        z = 0
     
    point1 = Coordinate() 
    print(hasattr(point1, 'x'))
    print(hasattr(point1, 'y'))
    print(hasattr(point1, 'z'))
    print(hasattr(point1, 'no'))  # 没有该属性
    
    • setattr() 函数对应函数 getattr(),用于设置属性值,该属性不一定是存在的。

      语法

      setattr() 语法:

      setattr(object, name, value)
      

      参数

      • object -- 对象。
      • name -- 字符串,对象属性。
      • value -- 属性值。

      返回值

      无。

      实例

      以下实例展示了 setattr() 函数的使用方法:

      对已存在的属性进行赋值:

    >>>class A(object):
    ...     bar = 1
    ... 
    >>> a = A()
    >>> getattr(a, 'bar')          # 获取属性 bar 值
    1
    >>> setattr(a, 'bar', 5)       # 设置属性 bar 值
    >>> a.bar
    5
    

    如果属性不存在会创建一个新的对象属性,并对属性赋值:

    >>>class A():
    ...     name = "runoob"
    ... 
    >>> a = A()
    >>> setattr(a, "age", 28)
    >>> print(a.age)
    28
    >>>
    
    • delattr 函数用于删除属性。

      delattr(x, 'foobar') 相等于 del x.foobar

      语法

      delattr 语法:

      delattr(object, name)
      

      参数

      • object -- 对象。
      • name -- 必须是对象的属性。

      返回值

      无。

      实例

      以下实例展示了 delattr 的使用方法:

    class Coordinate:
        x = 10
        y = -5
        z = 0
     
    point1 = Coordinate() 
     
    print('x = ',point1.x)
    print('y = ',point1.y)
    print('z = ',point1.z)
     
    delattr(Coordinate, 'z')
     
    print('--删除 z 属性后--')
    print('x = ',point1.x)
    print('y = ',point1.y)
     
    # 触发错误
    print('z = ',point1.z)
    

3. 内置方法

1. __str__与 __repr__

  • 当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
class Car:

    def __init__(self, newWheelNum, newColor):
        self.wheelNum = newWheelNum
        self.color = newColor

    def __str__(self):
        msg = "嘿。。。我的颜色是" + self.color + "我有" + int(self.wheelNum) + "个轮胎..."
        return msg

    def move(self):
        print('车在跑,目标:夏威夷')


BMW = Car(4, "白色")
print(BMW)
  • str函数或者print函数--->obj.__str__()
  • repr或者交互式解释器--->obj.__repr__()
  • 如果__str__没有被定义,那么就会使用__repr__来代替输出
  • 注意:这俩方法的返回值必须是字符串,否则抛出异常
class School:
    def __init__(self, name, addr, type):
        self.name = name
        self.addr = addr
        self.type = type

    def __repr__(self):
        return 'School(%s,%s)' % (self.name, self.addr)

    def __str__(self):
        return '(%s,%s)' % (self.name, self.addr)


s1 = School('oldboy1', '北京', '私立')

2. __setattr__和__delattr__和__getattr__

class Foo:
    x = 1

    def __init__(self, y):
        self.y = y

    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')

    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key = value  # 这就无限递归了,你好好想想
        # self.__dict__[key] = value  # 应该使用它

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item  # 无限递归了
        self.__dict__.pop(item)


f1 = Foo(10)

__setatter__

  • 添加/修改属性会触发它的执行
print(f1.__dict__
      )  # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z = 3
print(f1.__dict__)

__delatter__

  • 删除属性的时候会触发
f1.__dict__['a'] = 3  # 我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)

__getatter__

  • 只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

3. __call__

  • 对象后面加括号时,触发执行。
  • 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
    def __init__(self):
        print('__init__触发了')

    def __call__(self, *args, **kwargs):

        print('__call__触发了')


obj = Foo()  # 执行 __init__
__init__触发了
obj()  # 执行 __call__
__call__
posted @ 2019-09-02 21:42  油饼er  阅读(148)  评论(0编辑  收藏  举报