面向对象编程(获取对象信息)

判断

判断对象类型,有哪些可以使用的方法,之前讲过type() 函数

type()
print(type(123))
print(type('ABC'))
print(type(None))


#输出
<class 'int'>
<class 'str'>
<class 'NoneType'>

 


如果一个函数指向的是类,或者函数,我们也可以使用type()来判断
def abc():
    pass

class a(object):
    pass

print(type(abc))

print(type(a))

#输出
<class 'function'>
<class 'type'>




调用 types 模块对函数等,进行判断

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

 


使用isinstance()

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数

之前说了用 isinstance 来判断 继承关系,isinstance还有其他的功能

isinstance() 与 type() 区别:

  • type() 不会认为子类是一种父类类型,不考虑继承关系。

  • isinstance() 会认为子类是一种父类类型,考虑继承关系。

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

语法

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

isinstance(object, classinfo)

参数

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

返回值

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

实例

以下展示了使用 isinstance 函数的实例:

>>>a = 2
>>> isinstance (a,int)
True
>>> isinstance (a,str)
False
>>> isinstance (a,(str,int,list))    # 是元组中的一个返回 True
True

type() 与 isinstance()区别:

class A:
    pass
 
class B(A):
    pass
 
isinstance(A(), A)    # returns True
type(A()) == A        # returns True
isinstance(B(), A)    # returns True
type(B()) == A        # returns False

总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。

 

使用dir()

描述

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。

语法

dir 语法:

dir([object])

参数说明:

  • object -- 对象、变量、类型。

返回值

返回模块的属性列表。

实例

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

>>>dir()   #  获得当前模块的属性列表
['__builtins__', '__doc__', '__name__', '__package__', 'arr', 'myslice']
>>> dir([ ])    # 查看列表的方法
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>>

 

 

配合getattr()setattr()以及hasattr(),我们可以直接操作一个对象的状态:

 

class Test(object):
def __init__(self):
self.x = 9
def power(self):
return self.x + self.x

obj = Test()
print(hasattr(obj,'x')) #有属性‘x’ 吗 ?

print(hasattr(obj,'y')) #有属性'y' 吗?

setattr(obj,'y',10) #设置一个属性y并赋值10

print(getattr(obj,'y'))#获取y 的值

print(obj.y) #打印y的值

#输出
True
False
10
10

如何避免获取不存在的值报错的方法

class Test(object):
    def __init__(self):
        self.x = 9
    def power(self):
        return self.x + self.x
obj = Test()

print(getattr(obj,'k')) #如果获取不存在的值,就会抛出AttributeError的错误

#输出
Traceback (most recent call last):
  File "G:/python练习/网络编程/oop_object_1.py", line 38, in <module>
    print(getattr(obj,'k'))
AttributeError: 'Test' object has no attribute 'k'

 

可以传入一个default参数,如果获取的属性不存在,就返回默认值

class Test(object):
    def __init__(self):
        self.x = 9
    def power(self):
        return self.x + self.x

obj = Test()

#print(getattr(obj,'k')) #如果获取不存在的值,就会抛出AttributeError的错误
print(getattr(obj,'k',404))#传入default参数

#输出
404

也可以获得对象的方法:

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

 

小结

通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。如果可以直接写:

 

sum = obj.x + obj.y

就不要写:

 

sum = getattr(obj, 'x') + getattr(obj, 'y')

一个正确的用法的例子如下:

def readImage(fp):
    if hasattr(fp, 'read'):
        return readData(fp)
    return None

假设我们希望从文件流fp中读取图像,我们首先要判断该fp对象是否存在read方法,如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场。

请注意,在Python这类动态语言中,根据鸭子类型,有read()方法,不代表该fp对象就是一个文件流,它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。

posted @ 2018-04-28 13:37  SmallNine  阅读(470)  评论(0编辑  收藏  举报