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

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?

 

使用type()

首先,我们来判断对象类型,使用type()函数

基本类型都可以用type()类型:

>>> type(123)
<class 'int'>
>>> type('str')
<class 'str'>
>>> type(None)
<class 'NoneType'>

如果一个变量指向函数或者类,也可以用type()判断:

>>> type(abs)
<class 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>

但是type()函数返回的是什么类型呢?它返回对应的class类型。如果我们要在if语句中判断,就需要比较两个变量的type类型是否相同:

>>> type(123) == type(456)
True
>>> type(123) == int
True
>>> type('123') == type('abc')
True
>>> type('abc') == str
True
>>> type('abc') == type(123)
False

判断基本数据类型可以直接写int,str等,但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:

>>> 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()函数。

我们回顾上次的例子,如过继承关系是:

object -> Animal -> Dog -> Husky

那么,isinstance()就可以告诉我们,一个对象是否是某种类型。先创建3种类型的对象:

>>>a = Animal()
>>>d = Dog()
>>>h = Husky()

然后,判断:

>>>isinstance(h,Husky)
True

没有问题,因为h变量指向的就是Husky对象。

再判断:

>>>isinstance(h,Dog)
True

h虽然自身是Husky类型,但由于Husky是从Dog继承下来的,所以,h也还是Dog类型。换句话说,isinstance()判断的是一个对象是否是类型本身,或者位于该类型的父继承链上。

因此,我们可以确信,h还是Animal类型:

>>>isinstance(h,Animal)
True

同理,实际类型是Dog的d也是Animal类型:

>>>isinstance(d,Dog) and isinstance(d,Animal)
True

但是,d不是Husky类型:

>>>isinstance(d,Husky)
True

能用type()判断的基本类型也可以用isinstance()判断:

>>> isinstance('a',str)
True
>>> isinstance(123,int)
True
>>> isinstance(b'a',bytes)
True

并且可以判断可以判断某些变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple:

>>> isinstance([1,2,3],(list,tuple))  #一对多匹配
True
>>> isinstance((1,2,3),(list,tuple))
True
>>> isinstance([1,2,3],[list,tuple])  #后面不能使用列表
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: isinstance() arg 2 must be a type or tuple of types

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

 

使用dir()

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

>>> dir('ABC')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__',........'upper', 'zfill']

类似__xxx__的属性和方法在python中都有特殊用途,比如__len__方法返回长度。

在python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以下面的代码是等价的:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

我自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法:

>>> class MyDog(object):
...     def __len__(self):
...         return 100
...
>>> dog = MyDog()
>>> len(dog)   #调用自己的方法
100

剩下的都是普通属性或方法,比如lower()返回小写的字符串:

>>> 'ABC'.lower()
'abc'

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()

紧接着可以测试该对象的属性:

>>> hasattr(obj,'x')   #该对象有“x”属性吗?
True
>>> hasattr(obj,'y')   #该对象有“y”属性吗?
False
>>> setattr(obj,'y',19)#设置一个新的属性“y”
>>> hasattr(obj,'y')   #该对象有“y”属性吗?
True                   #有
>>> getattr(obj,'y')   #获取该对象的“y”属性的值
19
>>> obj.y   #还可以这样获取属性喔
19

如果试图获取不存在的属性,会抛出AttributeError的错误:

>>> getattr(obj,'z')
Traceback (most recent call last):File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'

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

>>> getattr(obj,'z',404)
404

也可以获得对象的方法:

>>> hasattr(obj,'power')   #有属性‘power’吗?
True
>>> getattr(obj,'power')   #获取属性“power”
<bound method MyObject.power of <__main__.MyObject object at 0x000002B4BA7C1710>>
>>> fn = getattr(obj,'power')  #获取属性“power”并赋值到变量fn
>>> fn   #fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x000002B4BA7C1710>>
>>> obj.power  #其实是一样的
<bound method MyObject.power of <__main__.MyObject object at 0x000002B4BA7C1710>>
>>> fn()   #执行方法
81

 

小结

通过内置的一系列函数,我们可以对任意一个python对象进行剖析,拿到其内部的数据。

要注意的是,只有在不知道对象信息的时候,我们才会获取对象信息。如果可以直接写:

>>> sum = obj.x + obj.y
>>> sum
28

就不要写:

>>> num = getattr(obj,'x') + getattr(obj,'y')
>>> num
28    #虽然得到了同样的结果

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

>>> def readImage(fp):
...     if hasattr(fp,'read'):  #先判断是否有read属性
...         return readImage(fp)
...     return None

假设我们希望从文件流fp中读取图像,我们首先要判断fp对象是否存在read方法,

如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场

请注意,在python这类动态语言中,根据鸭子类型,有read()方法,不代表该对象就是一个文件流,

它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。

 

转载于:https://www.cnblogs.com/yangmingxianshen/p/7858137.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/268046.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET控件开发基础5

上一篇简单的讲了从WebControl继承的控件(好象我讲的都是简单的,嘿嘿).本次讲的更简单,主题是是属性,只当分享经验,希望对大家有帮助我们根据属性的不同表现形式,把其区分为简单属性和复杂属性下面来看下属性的表现形式简单属性表现形式如下,大家都很熟悉 <asp:TextBox ID&q…

项目Alpha冲刺Day4

一、会议照片 二、项目进展 1.今日安排 学习熟悉前台框架且搭建前台页面框架。 2.问题困难 使用了前端的构建工具webpack&#xff0c;困难在于怎么使用gradle结合它连同后台框架中的配置一起打包&#xff0c;因为本身都才刚接触这两者。本来希望每个人下好项目能配置尽量少的东…

log4j:ERROR Could not find value for key log4j.appender.stdout.layout

Connected to the target VM, address: 127.0.0.1:65401, transport: socket log4j:ERROR Could not find value for key log4j.appender.stdout.layout 此log4j:ERROR Could not find value for key log4j.appender.XXXX类型报错与log4j.properties文件写法有关系 处理方法&a…

linux下VMware_Tools虚拟机工具的安装

1 到菜单栏“虚拟机”里选择“安装VMware Tools(I)”虚拟机工具<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />2 挂载了VM虚拟机工具以后的Linux系统的界面3 右键“VMwareTools-6.0.2-59824.tar.gz”文件&#xff0c;复制到桌面…

第十二周学习笔记

先检查有没有对应类型的接口&#xff0c;没有必须先到网上下载&#xff0c;重新开启SQL SEVER即可 64位以上的系统必须用 Microsoft Ace Oledb 12.0 版本的 要选对数据库 没有查询到表格的可以建立表格 用INSERT INTO 语句可以插入数据 ----------删除 删除格式代码&#xff0c…

TechEd2010

微软&#xff08;中国&#xff09;TechEd2010今天在北京国家会议中心开幕了&#xff0c;还是和去年一样&#xff0c;场面做的很大。今年的主题是云&#xff0c;Windows Phone 7&#xff0c;和IE9。 会上&#xff0c;也见了非常多的朋友&#xff0c;有微软的老朋友&#xff0c;也…

错误: 找不到或无法加载主程序类 错误: 找不到或无法加载主类 wc.BatchWordCount

错误描述 编写完代码以后运行main方法&#xff0c;出现错误: 找不到或无法加载主类 错误: 找不到或无法加载主类 wc.BatchWordCount 解决办法 1、点击IDEA侧边的maven栏目&#xff0c;点击compile进行编译 2:显示BUILD SUCCESS表示编译成功 3、再次运行main方法&#xff0…

chmod与umask区分命令

chmod与umask区分命令chmod命令用于改变文件的目录的访问权限&#xff0c;他是一条非常重的系统命令。用户可以用其控制文件或目录的访问权限。 umask是创建文件或创建一个文件目录的一个默认权限。当使用不带参数的umask命令是&#xff0c;喜用会输出当前umask的值。 [rootloc…

Linux包管理速查表

使用Linux 系统总是免不了要接触包管理工具。比如&#xff0c;Debian/Ubuntu 的apt、openSUSE 的zypp、Fedora 的yum、Mandriva 的urpmi、Slackware 的slackpkg、Archlinux 的pacman、Gentoo 的emerge、Foresight 的conary、Pardus 的pisi&#xff0c;等等。DistroWatch 针对上…

C++ 序列化 serialization 如何将类持久化?

C的类的持久化可以通过下面文章中所使用的方法来实现 其原理是将对象的内容以二进制的形式保存到文件中, 在要读取的时候再使用相反的过程来加载到对象中. 总结起来就是可以为要进行持久化的对象,比如说配置类,添加如下的两个方法: bool Config::Save(){ ofstream ofs("co…

BZOJ 4808: 马(二分图最大点独立集)

http://www.lydsy.com/JudgeOnline/problem.php?id4808 题意&#xff1a; 思路&#xff1a; 这图中的两个马只能选一个&#xff0c;二选一&#xff0c;很像二分图吧&#xff0c;对能互吃的两个棋子连线&#xff0c;在所选的任意两个棋子中&#xff0c;都不能互相有连线&#x…

使用Flink批处理实现WordCount

Flink作为一个非常优秀的大数据实时计算框架&#xff0c;在很多从事大数据开发的公司都是必备的技能&#xff0c;接下来我将通过Flink以批处理来实现入门案例WordCount 1:步骤一 idea新建设maven项目&#xff0c;并且自己配置好maven环境 2&#xff1a;步骤二 在pom文件中加…

Application.DoEvents

记得第一次使用Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示&#xff0c;不至于系统出现假死的现象&#xff0c;当时也没有深入的去研究他的原理是怎样的&#xff0c;结果在很多地方都用上了Application.DoEvents()&#xff0c;今天看到了关于这方面…

Servlet交互【重定向 与 请求分派】详解

Servlet交互 在serlvet中&#xff0c;需要调用另外一个资源来对浏览器的请求进行响应&#xff0c;两种方式实现&#xff1a; 调用HttpServletResponse.sendRedirect 方法实现 重定向 调用RequestDispatcher.forward 方法来实现请求分派 &#xff08;转发&#xff09; 1.reponse…

解决Error: No such file or directory @ rb_sysopen

mac使用brew安装flink时出现报错&#xff0c;是下载openjdk11报错的 原因是openjdk11依赖包下载不成功&#xff0c;使用brew单独下载该依赖包即可 brew install openjdk11

《Sibelius 脚本程序设计》连载(十四) - 2.1 注释、语句、语句块

《Sibelius 脚本程序设计》连载(Flash 格式) 转载于:https://www.cnblogs.com/Sibelius/archive/2010/12/11/1903389.html

Mac Brew install 报错Command failed with exit 128:git

问题&#xff1a; 记录一个问题&#xff0c;Mac使用Brew安装Flink报错 具体如图所示&#xff0c;执行brew install apache-flink Error: Command failed with exit 128: git 解决方式&#xff1a; 输入brew -v后会提示你执行两个配置命令&#xff0c;直接复制执行就ok了&am…

[转载]一个游戏程序员的学习资料

想起写这篇文章是在看侯杰先生的《深入浅出MFC》时,突然觉得自己在大学这几年关于游戏编程方面还算是有些心得&#xff0c;因此写出这篇小文,介绍我眼中的游戏程序员的书单与源代码参考。一则是作为自己今后两年学习目标的备忘录,二来没准对别人也有点参考价值。我的原则是只写…

Mac上安装flink笔记

1&#xff1a;步骤一 首先要有破jdk1.8&#xff0c;查看命令&#xff1a;java -version 2:步骤二 使用brew安装flink&#xff0c;命令如下&#xff1a; brew install apache-flink 3:步骤三 我这边安装的时候报错了&#xff0c;解决方式如下 报错1 解决方式 https://blog.…